44 public class DirectiveBuilder implements StateBuilder<CompileCommand> { |
44 public class DirectiveBuilder implements StateBuilder<CompileCommand> { |
45 private static final List<Pair<Executable, Callable<?>>> METHODS |
45 private static final List<Pair<Executable, Callable<?>>> METHODS |
46 = new PoolHelper().getAllMethods(); |
46 = new PoolHelper().getAllMethods(); |
47 private final Map<Executable, State> stateMap = new HashMap<>(); |
47 private final Map<Executable, State> stateMap = new HashMap<>(); |
48 private final String fileName; |
48 private final String fileName; |
49 private Map<MethodDescriptor, List<CompileCommand>> matchBlocks |
49 private final Map<MethodDescriptor, List<CompileCommand>> matchBlocks |
50 = new LinkedHashMap<>(); |
50 = new LinkedHashMap<>(); |
51 private List<String> inlineMatch = new ArrayList<>(); |
51 private final List<CompileCommand> inlines = new ArrayList<>(); |
52 private boolean isFileValid = true; |
52 private boolean isFileValid = true; |
53 |
53 |
54 public DirectiveBuilder(String fileName) { |
54 public DirectiveBuilder(String fileName) { |
55 this.fileName = fileName; |
55 this.fileName = fileName; |
56 } |
56 } |
79 return isFileValid; |
79 return isFileValid; |
80 } |
80 } |
81 |
81 |
82 @Override |
82 @Override |
83 public Map<Executable, State> getStates() { |
83 public Map<Executable, State> getStates() { |
|
84 writeDirectiveFile(); |
|
85 if (isFileValid) { |
|
86 // Build states for each method according to match blocks |
|
87 for (Pair<Executable, Callable<?>> pair : METHODS) { |
|
88 State state = getState(pair); |
|
89 if (state != null) { |
|
90 stateMap.put(pair.first, state); |
|
91 } |
|
92 } |
|
93 return stateMap; |
|
94 } else { |
|
95 // return empty map because invalid file doesn't change states |
|
96 return new HashMap<>(); |
|
97 } |
|
98 } |
|
99 |
|
100 private void writeDirectiveFile() { |
84 try (DirectiveWriter dirFile = new DirectiveWriter(fileName)) { |
101 try (DirectiveWriter dirFile = new DirectiveWriter(fileName)) { |
85 for (MethodDescriptor matchDescriptor : matchBlocks.keySet()) { |
102 for (MethodDescriptor matchDescriptor : matchBlocks.keySet()) { |
86 // Write match block with all options converted from commands |
103 // Write match block with all options converted from commands |
87 dirFile.match(matchDescriptor); |
104 dirFile.match(matchDescriptor); |
88 for (CompileCommand compileCommand : |
105 for (CompileCommand compileCommand : |
89 matchBlocks.get(matchDescriptor)) { |
106 matchBlocks.get(matchDescriptor)) { |
90 isFileValid &= compileCommand.isValid(); |
|
91 handleCommand(dirFile, compileCommand); |
107 handleCommand(dirFile, compileCommand); |
92 } |
108 } |
93 if ("Inlinee.caller".matches((matchDescriptor.getRegexp()))) { |
109 if ("Inlinee.caller()".matches(matchDescriptor.getRegexp()) |
|
110 && !inlines.isEmpty()) { |
94 // Got a *.* match block, where inline would be written |
111 // Got a *.* match block, where inline would be written |
95 dirFile.inline(inlineMatch.toArray( |
112 writeInlines(dirFile); |
96 new String[inlineMatch.size()])); |
113 inlines.clear(); |
97 inlineMatch.clear(); |
|
98 } |
114 } |
99 dirFile.end(); // ends match block |
115 dirFile.end(); // ends match block |
100 } |
116 } |
101 |
117 |
102 /* |
118 /* |
103 * Write inline directive in the end to the latest match block |
119 * Write inline directive in the end to the latest match block |
104 * if we didn't do this before |
120 * if we didn't do this before |
105 * Inlinee caller methods should match this block only |
121 * Inlinee caller methods should match this block only |
106 */ |
122 */ |
107 if (!inlineMatch.isEmpty()) { |
123 if (!inlines.isEmpty()) { |
108 Pair<Executable, Callable<?>> pair = METHODS.get(0); |
124 Pair<Executable, Callable<?>> pair = METHODS.get(0); |
109 MethodDescriptor md = MethodGenerator.anyMatchDescriptor( |
125 MethodDescriptor md = MethodGenerator.anyMatchDescriptor( |
110 pair.first); |
126 pair.first); |
111 CompileCommand cc = new CompileCommand(Command.QUIET, md, null, |
127 CompileCommand cc = new CompileCommand(Command.QUIET, md, |
112 Scenario.Type.DIRECTIVE); |
128 null, Scenario.Type.DIRECTIVE); |
113 List<CompileCommand> commands = new ArrayList<>(); |
129 List<CompileCommand> commands = new ArrayList<>(); |
114 |
130 |
115 // Add appropriate "*.*" match block |
131 // Add appropriate "*.*" match block |
116 commands.add(cc); |
132 commands.add(cc); |
117 matchBlocks.put(md, commands); |
133 matchBlocks.put(md, commands); |
118 // Add match block for this descriptor with inlines |
134 // Add match block for this descriptor with inlines |
119 dirFile.match(md); |
135 dirFile.match(md); |
120 dirFile.inline(inlineMatch.toArray( |
136 writeInlines(dirFile); |
121 new String[inlineMatch.size()])); |
|
122 dirFile.end(); |
137 dirFile.end(); |
123 } |
138 } |
124 if (!matchBlocks.isEmpty()) { |
139 if (!matchBlocks.isEmpty()) { |
125 // terminates file |
140 // terminates file |
126 dirFile.end(); |
141 dirFile.end(); |
127 } |
142 } |
128 |
143 |
129 // Build states for each method according to match blocks |
|
130 for (Pair<Executable, Callable<?>> pair : METHODS) { |
|
131 State state = getState(pair); |
|
132 if (state != null) { |
|
133 stateMap.put(pair.first, state); |
|
134 } |
|
135 } |
|
136 } |
|
137 if (isFileValid) { |
|
138 return stateMap; |
|
139 } else { |
|
140 // return empty map because invalid file doesn't change states |
|
141 return new HashMap<>(); |
|
142 } |
144 } |
143 } |
145 } |
144 |
146 |
145 private State getState(Pair<Executable, Callable<?>> pair) { |
147 private State getState(Pair<Executable, Callable<?>> pair) { |
146 State state = null; |
148 State state = null; |
186 dirFile.excludeCompile(cmd.compiler, false); |
190 dirFile.excludeCompile(cmd.compiler, false); |
187 break; |
191 break; |
188 case EXCLUDE: |
192 case EXCLUDE: |
189 dirFile.excludeCompile(cmd.compiler, true); |
193 dirFile.excludeCompile(cmd.compiler, true); |
190 break; |
194 break; |
|
195 case QUIET: |
|
196 /* there are no appropriate directive for this, just make |
|
197 match be enabled */ |
191 case INLINE: |
198 case INLINE: |
192 case DONTINLINE: |
199 case DONTINLINE: |
193 // Inline commands will be written later |
200 /* Inline commands will be written later. |
|
201 Just make this match be enabled */ |
|
202 dirFile.emitCompiler(Scenario.Compiler.C1); |
|
203 dirFile.option(DirectiveWriter.Option.ENABLE, true); |
|
204 dirFile.end(); |
|
205 dirFile.emitCompiler(Scenario.Compiler.C2); |
|
206 dirFile.option(DirectiveWriter.Option.ENABLE, true); |
|
207 dirFile.end(); |
194 break; |
208 break; |
195 case LOG: |
209 case LOG: |
196 dirFile.option(DirectiveWriter.Option.LOG, true); |
210 dirFile.option(DirectiveWriter.Option.LOG, true); |
197 break; |
|
198 case QUIET: |
|
199 // there are no appropriate directive for this |
|
200 break; |
211 break; |
201 case PRINT: |
212 case PRINT: |
202 dirFile.option(DirectiveWriter.Option.PRINT_ASSEMBLY, true); |
213 dirFile.option(DirectiveWriter.Option.PRINT_ASSEMBLY, true); |
203 break; |
214 break; |
204 case NONEXISTENT: |
215 case NONEXISTENT: |
212 default: |
223 default: |
213 throw new Error("TESTBUG: wrong command: " + command); |
224 throw new Error("TESTBUG: wrong command: " + command); |
214 } |
225 } |
215 } |
226 } |
216 |
227 |
|
228 private void writeInlines(DirectiveWriter dirFile) { |
|
229 List<String> c1Block = new ArrayList<>(); |
|
230 List<String> c2Block = new ArrayList<>(); |
|
231 List<String> allBlock = new ArrayList<>(); |
|
232 for (CompileCommand cc : inlines) { |
|
233 String inlineMethodPattern; |
|
234 switch (cc.command) { |
|
235 case INLINE: |
|
236 inlineMethodPattern = "+" + cc.methodDescriptor.getString(); |
|
237 break; |
|
238 case DONTINLINE: |
|
239 inlineMethodPattern = "-" + cc.methodDescriptor.getString(); |
|
240 break; |
|
241 default: |
|
242 throw new Error("TESTBUG: incorrect command got in " |
|
243 + "the list: " + cc.command); |
|
244 } |
|
245 if (cc.compiler == Scenario.Compiler.C1) { |
|
246 c1Block.add(inlineMethodPattern); |
|
247 } else if (cc.compiler == Scenario.Compiler.C2) { |
|
248 c2Block.add(inlineMethodPattern); |
|
249 } else { |
|
250 allBlock.add(inlineMethodPattern); |
|
251 } |
|
252 } |
|
253 dirFile.emitCompiler(Scenario.Compiler.C1); |
|
254 if (!c1Block.isEmpty()) { |
|
255 dirFile.inline(c1Block); |
|
256 } else { |
|
257 dirFile.option(DirectiveWriter.Option.ENABLE, true); |
|
258 } |
|
259 dirFile.end(); |
|
260 dirFile.emitCompiler(Scenario.Compiler.C2); |
|
261 if (!c2Block.isEmpty()) { |
|
262 dirFile.inline(c2Block); |
|
263 } else { |
|
264 dirFile.option(DirectiveWriter.Option.ENABLE, true); |
|
265 } |
|
266 dirFile.end(); |
|
267 if (!allBlock.isEmpty()) { |
|
268 dirFile.inline(allBlock); |
|
269 } |
|
270 } |
|
271 |
217 @Override |
272 @Override |
218 public void add(CompileCommand compileCommand) { |
273 public void add(CompileCommand compileCommand) { |
|
274 isFileValid &= compileCommand.isValid(); |
219 MethodDescriptor methodDescriptor = compileCommand.methodDescriptor; |
275 MethodDescriptor methodDescriptor = compileCommand.methodDescriptor; |
220 |
276 |
221 switch (compileCommand.command) { |
277 switch (compileCommand.command) { |
222 case INLINE: |
278 case INLINE: |
223 inlineMatch.add("+" + methodDescriptor.getString()); |
|
224 break; |
|
225 case DONTINLINE: |
279 case DONTINLINE: |
226 inlineMatch.add("-" + methodDescriptor.getString()); |
280 inlines.add(compileCommand); |
227 break; |
281 break; |
228 } |
282 } |
229 for (MethodDescriptor md: matchBlocks.keySet()) { |
283 for (MethodDescriptor md: matchBlocks.keySet()) { |
230 if (methodDescriptor.getCanonicalString().matches(md.getRegexp())) { |
284 if (methodDescriptor.getCanonicalString().matches(md.getRegexp())) { |
231 matchBlocks.get(md).add(compileCommand); |
285 matchBlocks.get(md).add(compileCommand); |