Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: frog/leg/ssa/builder.dart

Issue 9753005: Change visitLoop to handleLoop that takes closures as arguments. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/co19/co19-leg.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 class Interceptors { 5 class Interceptors {
6 Compiler compiler; 6 Compiler compiler;
7 Interceptors(Compiler this.compiler); 7 Interceptors(Compiler this.compiler);
8 8
9 SourceString mapOperatorToMethodName(Operator op) { 9 SourceString mapOperatorToMethodName(Operator op) {
10 String name = op.source.stringValue; 10 String name = op.source.stringValue;
(...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after
1089 localsHandler.endLoop(loopEntry); 1089 localsHandler.endLoop(loopEntry);
1090 if (!breakLocals.isEmpty()) { 1090 if (!breakLocals.isEmpty()) {
1091 breakLocals.add(savedLocals); 1091 breakLocals.add(savedLocals);
1092 localsHandler = localsHandler.mergeMultiple(breakLocals, loopExitBlock); 1092 localsHandler = localsHandler.mergeMultiple(breakLocals, loopExitBlock);
1093 } else { 1093 } else {
1094 localsHandler = savedLocals; 1094 localsHandler = savedLocals;
1095 } 1095 }
1096 } 1096 }
1097 1097
1098 // For while loops, initializer and update are null. 1098 // For while loops, initializer and update are null.
1099 visitLoop(Node loop, 1099 // The condition function must return a boolean result.
ngeoffray 2012/03/21 07:58:47 Since they'are all doing, why not making it unifor
Lasse Reichstein Nielsen 2012/03/21 09:00:15 I expect to use this one in switch-with-continue,
1100 Node initializer, 1100 // None of the functions must leave anything on the stack.
1101 Expression condition, 1101 handleLoop(Node loop,
1102 NodeList updates, 1102 void initialize(),
1103 Node body) { 1103 HInstruction condition(),
1104 void update(),
1105 void body()) {
1104 // Generate: 1106 // Generate:
1105 // <initializer> 1107 // <initializer>
1106 // loop-entry: 1108 // loop-entry:
1107 // if (!<condition>) goto loop-exit; 1109 // if (!<condition>) goto loop-exit;
1108 // <body> 1110 // <body>
1109 // <updates> 1111 // <updates>
1110 // goto loop-entry; 1112 // goto loop-entry;
1111 // loop-exit: 1113 // loop-exit:
1112 if (body === null) {
1113 compiler.unimplemented(
1114 'SsaBuilder.visitLoop with empty body',
1115 node: loop);
1116 }
1117 1114
1118 localsHandler.startLoop(loop); 1115 localsHandler.startLoop(loop);
1119 1116
1120 // The initializer. 1117 // The initializer.
1121 if (initializer !== null) { 1118 if (initialize !== null) {
1122 visit(initializer); 1119 initialize();
1123 // We don't care about the value of the initialization.
1124 if (initializer.asExpression() !== null) pop();
1125 } 1120 }
1126 assert(!isAborted()); 1121 assert(!isAborted());
1127 1122
1128 JumpHandler jumpHandler = beginLoopHeader(loop); 1123 JumpHandler jumpHandler = beginLoopHeader(loop);
1129 HBasicBlock conditionBlock = current; 1124 HBasicBlock conditionBlock = current;
1130 1125
1131 HInstruction conditionInstruction; 1126 HInstruction conditionInstruction;
1132 if (condition != null) { 1127 if (condition != null) {
1133 visit(condition); 1128 conditionInstruction = condition();
1134 conditionInstruction = popBoolified();
1135 } else { 1129 } else {
1136 // TODO(ngeoffray): Once our loop recognition does not require a 1130 // TODO(ngeoffray): Once our loop recognition does not require a
1137 // HLoopBranch, we could just generate a HGoto. 1131 // HLoopBranch, we could just generate a HGoto.
1138 conditionInstruction = graph.addConstantBool(true); 1132 conditionInstruction = graph.addConstantBool(true);
1139 } 1133 }
1140 HBasicBlock conditionExitBlock = 1134 HBasicBlock conditionExitBlock =
1141 close(new HLoopBranch(conditionInstruction)); 1135 close(new HLoopBranch(conditionInstruction));
1142 1136
1143 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 1137 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
1144 1138
1145 // The body. 1139 // The body.
1146 HBasicBlock beginBodyBlock = addNewBlock(); 1140 HBasicBlock beginBodyBlock = addNewBlock();
1147 conditionExitBlock.addSuccessor(beginBodyBlock); 1141 conditionExitBlock.addSuccessor(beginBodyBlock);
1148 open(beginBodyBlock); 1142 open(beginBodyBlock);
1149 1143
1150 localsHandler.enterLoopBody(loop); 1144 localsHandler.enterLoopBody(loop);
1145 if (body !== null) {
1146 hackAroundPossiblyAbortingBody(loop, body);
1147 }
1151 1148
1152 hackAroundPossiblyAbortingBody(body);
1153 SubGraph bodyGraph = new SubGraph(beginBodyBlock, current); 1149 SubGraph bodyGraph = new SubGraph(beginBodyBlock, current);
1154 HBasicBlock bodyBlock = close(new HGoto()); 1150 HBasicBlock bodyBlock = close(new HGoto());
1155 1151
1156 // Update. 1152 // Update.
1157 // We create an update block, even when we are in a while loop. There the 1153 // We create an update block, even when we are in a while loop. There the
1158 // update block is the jump-target for continue statements. We could avoid 1154 // update block is the jump-target for continue statements. We could avoid
1159 // the creation if there is no continue, but for now we always create it. 1155 // the creation if there is no continue, but for now we always create it.
1160 HBasicBlock updateBlock = addNewBlock(); 1156 HBasicBlock updateBlock = addNewBlock();
1161 1157
1162 List<LocalsHandler> continueLocals = <LocalsHandler>[]; 1158 List<LocalsHandler> continueLocals = <LocalsHandler>[];
(...skipping 11 matching lines...) Expand all
1174 HLabeledBlockInformation labelInfo; 1170 HLabeledBlockInformation labelInfo;
1175 List<LabelElement> labels = jumpHandler.labels(); 1171 List<LabelElement> labels = jumpHandler.labels();
1176 if (!labels.isEmpty()) { 1172 if (!labels.isEmpty()) {
1177 beginBodyBlock.labeledBlockInformation = 1173 beginBodyBlock.labeledBlockInformation =
1178 new HLabeledBlockInformation(bodyGraph, updateBlock, 1174 new HLabeledBlockInformation(bodyGraph, updateBlock,
1179 jumpHandler.labels(), isContinue: true); 1175 jumpHandler.labels(), isContinue: true);
1180 } 1176 }
1181 1177
1182 localsHandler.enterLoopUpdates(loop); 1178 localsHandler.enterLoopUpdates(loop);
1183 1179
1184 if (updates !== null) { 1180 if (update !== null) {
1185 for (Expression expression in updates) { 1181 update();
1186 visit(expression);
1187 assert(!isAborted());
1188 // The result of the update instruction isn't used, and can just
1189 // be dropped.
1190 HInstruction updateInstruction = pop();
1191 }
1192 } 1182 }
1193 updateBlock = close(new HGoto()); 1183 updateBlock = close(new HGoto());
1194 // The back-edge completing the cycle. 1184 // The back-edge completing the cycle.
1195 updateBlock.addSuccessor(conditionBlock); 1185 updateBlock.addSuccessor(conditionBlock);
1196 conditionBlock.postProcessLoopHeader(); 1186 conditionBlock.postProcessLoopHeader();
1197 1187
1198 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); 1188 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals);
1199 } 1189 }
1200 1190
1201 visitFor(For node) { 1191 visitFor(For node) {
1202 assert(node.body !== null); 1192 assert(node.body !== null);
1203 visitLoop(node, node.initializer, node.condition, node.update, node.body); 1193 void buildInitializer() {
1194 Node initializer = node.initializer;
1195 if (initializer !== null) {
1196 visit(initializer);
1197 if (initializer.asExpression() !== null) {
1198 pop();
1199 }
1200 }
1201 }
1202 HInstruction buildCondition() {
1203 visit(node.condition);
1204 return popBoolified();
1205 }
1206 void buildUpdate() {
1207 for (Expression expression in node.update) {
1208 visit(expression);
1209 assert(!isAborted());
1210 // The result of the update instruction isn't used, and can just
1211 // be dropped.
1212 HInstruction updateInstruction = pop();
1213 }
1214 }
1215 handleLoop(node,
1216 node.initializer === null ? null : buildInitializer,
ngeoffray 2012/03/21 07:58:47 How about (for this one and all others): node.ini
Lasse Reichstein Nielsen 2012/03/21 09:00:15 In this case, I could just put the test into the b
1217 node.condition === null ? null : buildCondition,
1218 node.update.isEmpty() ? null : buildUpdate,
1219 () { visit(node.body); });
1204 } 1220 }
1205 1221
1206 visitWhile(While node) { 1222 visitWhile(While node) {
1207 visitLoop(node, null, node.condition, null, node.body); 1223 handleLoop(node, null, HInstruction condition() { visit(node.condition);
ngeoffray 2012/03/21 07:58:47 I'd prefer one argument per line, or write the con
Lasse Reichstein Nielsen 2012/03/21 09:00:15 Done.
1224 return popBoolified(); },
1225 null, () { visit(node.body); });
1208 } 1226 }
1209 1227
1210 visitDoWhile(DoWhile node) { 1228 visitDoWhile(DoWhile node) {
1211 localsHandler.startLoop(node); 1229 localsHandler.startLoop(node);
1212 JumpHandler jumpHandler = beginLoopHeader(node); 1230 JumpHandler jumpHandler = beginLoopHeader(node);
1213 HBasicBlock loopEntryBlock = current; 1231 HBasicBlock loopEntryBlock = current;
1214 1232
1215 localsHandler.enterLoopBody(node); 1233 localsHandler.enterLoopBody(node);
1216 hackAroundPossiblyAbortingBody(node.body); 1234 hackAroundPossiblyAbortingBody(node, () { visit(node.body); });
1217 1235
1218 // If there are no continues we could avoid the creation of the condition 1236 // If there are no continues we could avoid the creation of the condition
1219 // block. This could also lead to a block having multiple entries and exits. 1237 // block. This could also lead to a block having multiple entries and exits.
1220 HBasicBlock bodyExitBlock = close(new HGoto()); 1238 HBasicBlock bodyExitBlock = close(new HGoto());
1221 HBasicBlock conditionBlock = addNewBlock(); 1239 HBasicBlock conditionBlock = addNewBlock();
1222 bodyExitBlock.addSuccessor(conditionBlock); 1240 bodyExitBlock.addSuccessor(conditionBlock);
1223 jumpHandler.forEachContinue((x,y) { 1241 jumpHandler.forEachContinue((x,y) {
1224 // TODO(lrn): Handle continue in do-while loops. 1242 // TODO(lrn): Handle continue in do-while loops.
1225 compiler.cancel("do-while with continue", node: node); 1243 compiler.cancel("do-while with continue", node: node);
1226 }); 1244 });
(...skipping 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after
2278 return new JumpHandler(this, element); 2296 return new JumpHandler(this, element);
2279 } 2297 }
2280 2298
2281 visitForInStatement(ForInStatement node) { 2299 visitForInStatement(ForInStatement node) {
2282 // Generate a structure equivalent to: 2300 // Generate a structure equivalent to:
2283 // Iterator<E> $iter = <iterable>.iterator() 2301 // Iterator<E> $iter = <iterable>.iterator()
2284 // while ($iter.hasNext()) { 2302 // while ($iter.hasNext()) {
2285 // E <declaredIdentifier> = $iter.next(); 2303 // E <declaredIdentifier> = $iter.next();
2286 // <body> 2304 // <body>
2287 // } 2305 // }
2288 localsHandler.startLoop(node);
2289 2306
2290 SourceString iteratorName = const SourceString("iterator"); 2307 // All the generated calls are to zero-argument functions.
2308 Selector selector = Selector.INVOCATION_0;
2309 // The iterator is shared between initializer, condition and body.
2310 HInstruction iterator;
2311 void buildInitialize() {
ngeoffray 2012/03/21 07:58:47 buildInitializer?
Lasse Reichstein Nielsen 2012/03/21 09:00:15 Done.
2312 SourceString iteratorName = const SourceString("iterator");
2313 Element interceptor = interceptors.getStaticInterceptor(iteratorName, 0);
2314 assert(interceptor != null);
2315 HStatic target = new HStatic(interceptor);
2316 add(target);
2317 visit(node.expression);
2318 List<HInstruction> inputs = <HInstruction>[target, pop()];
2319 iterator = new HInvokeInterceptor(selector, iteratorName, false, inputs);
2320 add(iterator);
2321 }
2322 HInstruction buildCondition() {
2323 push(new HInvokeDynamicMethod(
2324 selector, const SourceString('hasNext'), [iterator]));
ngeoffray 2012/03/21 07:58:47 <Instruction>[iterator]
Lasse Reichstein Nielsen 2012/03/21 09:00:15 Done.
2325 return popBoolified();
2326 }
2327 void buildBody() {
2328 push(new HInvokeDynamicMethod(
2329 selector, const SourceString('next'), [iterator]));
2291 2330
2292 Selector selector = Selector.INVOCATION_0; 2331 Element variable;
2293 Element interceptor = interceptors.getStaticInterceptor(iteratorName, 0); 2332 if (node.declaredIdentifier.asSend() !== null) {
2294 assert(interceptor != null); 2333 variable = elements[node.declaredIdentifier];
2295 HStatic target = new HStatic(interceptor); 2334 } else {
2296 add(target); 2335 assert(node.declaredIdentifier.asVariableDefinitions() !== null);
2297 visit(node.expression); 2336 VariableDefinitions variableDefinitions = node.declaredIdentifier;
2298 List<HInstruction> inputs = <HInstruction>[target, pop()]; 2337 variable = elements[variableDefinitions.definitions.nodes.head];
2299 HInstruction iterator = new HInvokeInterceptor( 2338 }
2300 selector, iteratorName, false, inputs); 2339 localsHandler.updateLocal(variable, pop());
2301 add(iterator);
2302 2340
2303 JumpHandler jumpHandler = beginLoopHeader(node); 2341 visit(node.body);
2304 HBasicBlock conditionBlock = current;
2305
2306 // The condition.
2307 push(new HInvokeDynamicMethod(
2308 selector, const SourceString('hasNext'), [iterator]));
2309 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified()));
2310
2311 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
2312
2313 // The body.
2314 HBasicBlock bodyBlock = addNewBlock();
2315 conditionExitBlock.addSuccessor(bodyBlock);
2316 open(bodyBlock);
2317
2318 // The call to next is considered to be part of the loop body.
2319 localsHandler.enterLoopBody(node);
2320
2321 push(new HInvokeDynamicMethod(
2322 selector, const SourceString('next'), [iterator]));
2323
2324 Element variable;
2325 if (node.declaredIdentifier.asSend() !== null) {
2326 variable = elements[node.declaredIdentifier];
2327 } else {
2328 assert(node.declaredIdentifier.asVariableDefinitions() !== null);
2329 VariableDefinitions variableDefinitions = node.declaredIdentifier;
2330 variable = elements[variableDefinitions.definitions.nodes.head];
2331 } 2342 }
2332 localsHandler.updateLocal(variable, pop()); 2343 handleLoop(node, buildInitialize, buildCondition, null, buildBody);
2333
2334 hackAroundPossiblyAbortingBody(node.body);
2335 bodyBlock = close(new HGoto());
2336
2337 jumpHandler.forEachContinue((x,y) {
2338 // TODO(lrn): Handle continue in for-in.
2339 // TODO(lrn): Or, preferably, use an abstraction of visitLoop for for-in.
2340 compiler.cancel('for-in with continue', node: node);
2341 });
2342
2343 // Update.
2344 // We create an update block, even if we are in a for-in loop. The
2345 // update block is the jump-target for continue statements. We could avoid
2346 // the creation if there is no continue, but for now we always create it.
2347 HBasicBlock updateBlock = addNewBlock();
2348
2349 bodyBlock.addSuccessor(updateBlock);
2350 open(updateBlock);
2351 updateBlock = close(new HGoto());
2352 // The back-edge completing the cycle.
2353 updateBlock.addSuccessor(conditionBlock);
2354 conditionBlock.postProcessLoopHeader();
2355
2356 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals);
2357 jumpHandler.close();
2358 } 2344 }
2359 2345
2360 visitLabeledStatement(LabeledStatement node) { 2346 visitLabeledStatement(LabeledStatement node) {
2361 Statement body = node.getBody(); 2347 Statement body = node.getBody();
2362 if (body is Loop || body is SwitchStatement) { 2348 if (body is Loop || body is SwitchStatement) {
2363 // Loops and switches handle their own labels. 2349 // Loops and switches handle their own labels.
2364 visit(body); 2350 visit(body);
2365 return; 2351 return;
2366 } 2352 }
2367 // Non-loop statements can only be break targets, not continue targets. 2353 // Non-loop statements can only be break targets, not continue targets.
2368 TargetElement targetElement = elements[body]; 2354 TargetElement targetElement = elements[body];
2369 if (targetElement === null || targetElement.statement !== body) { 2355 if (targetElement === null || targetElement.statement !== body) {
2370 // Labeled statements with no element on the body have no breaks. 2356 // Labeled statements with no element on the body have no breaks.
2371 // A different target statement only happens if the body is itself 2357 // A different target statement only happens if the body is itself
2372 // a break or continue for a different target. In that case, this 2358 // a break or continue for a different target. In that case, this
2373 // label is also always unused. 2359 // label is also always unused.
2374 visit(body); 2360 visit(body);
2375 return; 2361 return;
2376 } 2362 }
2377 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); 2363 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler);
2378 assert(targetElement.isBreakTarget); 2364 assert(targetElement.isBreakTarget);
2379 JumpHandler handler = new JumpHandler(this, targetElement); 2365 JumpHandler handler = new JumpHandler(this, targetElement);
2380 // Introduce a new basic block. 2366 // Introduce a new basic block.
2381 HBasicBlock entryBlock = graph.addNewBlock(); 2367 HBasicBlock entryBlock = graph.addNewBlock();
2382 goto(current, entryBlock); 2368 goto(current, entryBlock);
2383 open(entryBlock); 2369 open(entryBlock);
2384 hackAroundPossiblyAbortingBody(body); 2370 hackAroundPossiblyAbortingBody(node, () { visit(body); });
2385 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock); 2371 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock);
2386 2372
2387 HBasicBlock joinBlock = graph.addNewBlock(); 2373 HBasicBlock joinBlock = graph.addNewBlock();
2388 List<LocalsHandler> breakLocals = <LocalsHandler>[]; 2374 List<LocalsHandler> breakLocals = <LocalsHandler>[];
2389 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { 2375 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
2390 breakInstruction.block.addSuccessor(joinBlock); 2376 breakInstruction.block.addSuccessor(joinBlock);
2391 breakLocals.add(locals); 2377 breakLocals.add(locals);
2392 }); 2378 });
2393 bool hasBreak = breakLocals.length > 0; 2379 bool hasBreak = breakLocals.length > 0;
2394 if (!isAborted()) { 2380 if (!isAborted()) {
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
2692 // another unimplemented feature: aborting loop body. Simply 2678 // another unimplemented feature: aborting loop body. Simply
2693 // calling [add] does not work as it asserts that the instruction 2679 // calling [add] does not work as it asserts that the instruction
2694 // isn't a control flow instruction. So we inline parts of [add]. 2680 // isn't a control flow instruction. So we inline parts of [add].
2695 current.addAfter(current.last, new HThrow(message)); 2681 current.addAfter(current.last, new HThrow(message));
2696 if (isExpression) { 2682 if (isExpression) {
2697 stack.add(graph.addConstantNull()); 2683 stack.add(graph.addConstantNull());
2698 } 2684 }
2699 } 2685 }
2700 2686
2701 /** HACK HACK HACK */ 2687 /** HACK HACK HACK */
2702 void hackAroundPossiblyAbortingBody(Node body) { 2688 void hackAroundPossiblyAbortingBody(Node statement, void body()) {
2703 stack.add(graph.addConstantBool(true)); 2689 stack.add(graph.addConstantBool(true));
2704 buildBody() { 2690 buildBody() {
2705 // TODO(lrn): Make sure to take continue into account. 2691 // TODO(lrn): Make sure to take continue into account.
2706 visit(body); 2692 body();
2707 if (isAborted()) { 2693 if (isAborted()) {
2708 compiler.reportWarning(body, "aborting loop body"); 2694 compiler.reportWarning(statement, "aborting loop body");
2709 } 2695 }
2710 } 2696 }
2711 handleIf(buildBody, null); 2697 handleIf(buildBody, null);
2712 } 2698 }
2713 } 2699 }
2714 2700
2715 /** 2701 /**
2716 * Visitor that handles generation of string literals (LiteralString, 2702 * Visitor that handles generation of string literals (LiteralString,
2717 * StringInterpolation), and otherwise delegates to the given visitor for 2703 * StringInterpolation), and otherwise delegates to the given visitor for
2718 * non-literal subexpressions. 2704 * non-literal subexpressions.
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
2805 HInstruction concat = new HAdd(target, left, right); 2791 HInstruction concat = new HAdd(target, left, right);
2806 builder.add(concat); 2792 builder.add(concat);
2807 return concat; 2793 return concat;
2808 } 2794 }
2809 2795
2810 HInstruction result() { 2796 HInstruction result() {
2811 flushAccumulator(); 2797 flushAccumulator();
2812 return prefix; 2798 return prefix;
2813 } 2799 }
2814 } 2800 }
OLDNEW
« no previous file with comments | « no previous file | tests/co19/co19-leg.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698