|
1 | 1 | using Neo.SmartContract;
|
2 | 2 | using Neo.VM;
|
3 | 3 | using System;
|
4 |
| -using System.Collections.Concurrent; |
5 | 4 | using System.Collections.Generic;
|
6 | 5 | using System.Linq;
|
7 |
| -using System.Threading.Tasks; |
8 | 6 | using static Neo.Optimizer.OpCodeTypes;
|
9 | 7 | using static Neo.VM.OpCode;
|
10 | 8 |
|
11 | 9 | namespace Neo.Optimizer
|
12 | 10 | {
|
13 |
| - public static class JumpTarget |
| 11 | + static class JumpTarget |
14 | 12 | {
|
15 | 13 | public static bool SingleJumpInOperand(Instruction instruction) => SingleJumpInOperand(instruction.OpCode);
|
16 | 14 | public static bool SingleJumpInOperand(OpCode opcode)
|
@@ -56,36 +54,60 @@ public static (int catchTarget, int finallyTarget) ComputeTryTarget(int addr, In
|
56 | 54 | };
|
57 | 55 | }
|
58 | 56 |
|
59 |
| - public static (ConcurrentDictionary<Instruction, Instruction>, |
60 |
| - ConcurrentDictionary<Instruction, (Instruction, Instruction)>) |
| 57 | + public static (Dictionary<Instruction, Instruction>, |
| 58 | + Dictionary<Instruction, (Instruction, Instruction)>, |
| 59 | + Dictionary<Instruction, HashSet<Instruction>>) |
61 | 60 | FindAllJumpAndTrySourceToTargets(NefFile nef)
|
62 | 61 | {
|
63 | 62 | Script script = nef.Script;
|
64 | 63 | return FindAllJumpAndTrySourceToTargets(script);
|
65 | 64 | }
|
66 |
| - public static (ConcurrentDictionary<Instruction, Instruction>, |
67 |
| - ConcurrentDictionary<Instruction, (Instruction, Instruction)>) |
| 65 | + public static (Dictionary<Instruction, Instruction>, |
| 66 | + Dictionary<Instruction, (Instruction, Instruction)>, |
| 67 | + Dictionary<Instruction, HashSet<Instruction>>) |
68 | 68 | FindAllJumpAndTrySourceToTargets(Script script) => FindAllJumpAndTrySourceToTargets(script.EnumerateInstructions().ToList());
|
69 |
| - public static (ConcurrentDictionary<Instruction, Instruction>, |
70 |
| - ConcurrentDictionary<Instruction, (Instruction, Instruction)>) |
| 69 | + public static ( |
| 70 | + Dictionary<Instruction, Instruction>, // jump source to target |
| 71 | + Dictionary<Instruction, (Instruction, Instruction)>, // try source to targets |
| 72 | + Dictionary<Instruction, HashSet<Instruction>> // target to source |
| 73 | + ) |
71 | 74 | FindAllJumpAndTrySourceToTargets(List<(int, Instruction)> addressAndInstructionsList)
|
72 | 75 | {
|
73 | 76 | Dictionary<int, Instruction> addressToInstruction = new();
|
74 | 77 | foreach ((int a, Instruction i) in addressAndInstructionsList)
|
75 | 78 | addressToInstruction.Add(a, i);
|
76 |
| - ConcurrentDictionary<Instruction, Instruction> jumpSourceToTargets = new(); |
77 |
| - ConcurrentDictionary<Instruction, (Instruction, Instruction)> trySourceToTargets = new(); |
78 |
| - Parallel.ForEach(addressAndInstructionsList, item => |
| 79 | + Dictionary<Instruction, Instruction> jumpSourceToTargets = new(); |
| 80 | + Dictionary<Instruction, (Instruction, Instruction)> trySourceToTargets = new(); |
| 81 | + Dictionary<Instruction, HashSet<Instruction>> targetToSources = new(); |
| 82 | + foreach ((int a, Instruction i) in addressAndInstructionsList) |
79 | 83 | {
|
80 |
| - (int a, Instruction i) = (item.Item1, item.Item2); |
81 | 84 | if (SingleJumpInOperand(i))
|
82 |
| - jumpSourceToTargets.TryAdd(i, addressToInstruction[ComputeJumpTarget(a, i)]); |
| 85 | + { |
| 86 | + Instruction target = addressToInstruction[ComputeJumpTarget(a, i)]; |
| 87 | + jumpSourceToTargets.TryAdd(i, target); |
| 88 | + if (!targetToSources.TryGetValue(target, out HashSet<Instruction>? sources)) sources = new(); |
| 89 | + sources.Add(i); |
| 90 | + } |
83 | 91 | if (i.OpCode == TRY)
|
84 |
| - trySourceToTargets.TryAdd(i, (addressToInstruction[a + i.TokenI8], addressToInstruction[a + i.TokenI8_1])); |
| 92 | + { |
| 93 | + (Instruction t1, Instruction t2) = (addressToInstruction[a + i.TokenI8], addressToInstruction[a + i.TokenI8_1]); |
| 94 | + trySourceToTargets.TryAdd(i, (t1, t2)); |
| 95 | + if (!targetToSources.TryGetValue(t1, out HashSet<Instruction>? sources1)) sources1 = new(); |
| 96 | + sources1.Add(i); |
| 97 | + if (!targetToSources.TryGetValue(t2, out HashSet<Instruction>? sources2)) sources2 = new(); |
| 98 | + sources2.Add(i); |
| 99 | + } |
85 | 100 | if (i.OpCode == TRY_L)
|
86 |
| - trySourceToTargets.TryAdd(i, (addressToInstruction[a + i.TokenI32], addressToInstruction[a + i.TokenI32_1])); |
87 |
| - }); |
88 |
| - return (jumpSourceToTargets, trySourceToTargets); |
| 101 | + { |
| 102 | + (Instruction t1, Instruction t2) = (addressToInstruction[a + i.TokenI32], addressToInstruction[a + i.TokenI32_1]); |
| 103 | + trySourceToTargets.TryAdd(i, (t1, t2)); |
| 104 | + if (!targetToSources.TryGetValue(t1, out HashSet<Instruction>? sources1)) sources1 = new(); |
| 105 | + sources1.Add(i); |
| 106 | + if (!targetToSources.TryGetValue(t2, out HashSet<Instruction>? sources2)) sources2 = new(); |
| 107 | + sources2.Add(i); |
| 108 | + } |
| 109 | + } |
| 110 | + return (jumpSourceToTargets, trySourceToTargets, targetToSources); |
89 | 111 | }
|
90 | 112 | }
|
91 | 113 | }
|
0 commit comments