Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
| 9 * methods. We need to override [Element.computeType] because our | 9 * methods. We need to override [Element.computeType] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 878 | 878 |
| 879 void close() { | 879 void close() { |
| 880 // The mapping from TargetElement to JumpHandler is no longer needed. | 880 // The mapping from TargetElement to JumpHandler is no longer needed. |
| 881 for (TargetElement target in targetIndexMap.keys) { | 881 for (TargetElement target in targetIndexMap.keys) { |
| 882 builder.jumpTargets.remove(target); | 882 builder.jumpTargets.remove(target); |
| 883 } | 883 } |
| 884 super.close(); | 884 super.close(); |
| 885 } | 885 } |
| 886 } | 886 } |
| 887 | 887 |
| 888 class SsaBuilder extends ResolvedVisitor implements Visitor { | 888 class SsaGraphBuilderMixin { |
| 889 final SsaBuilderTask builder; | 889 final HGraph graph = new HGraph(); |
| 890 final JavaScriptBackend backend; | |
| 891 final CodegenWorkItem work; | |
| 892 final ConstantSystem constantSystem; | |
| 893 HGraph graph; | |
| 894 LocalsHandler localsHandler; | |
| 895 HInstruction rethrowableException; | |
| 896 Map<Element, HInstruction> parameters; | |
| 897 final RuntimeTypes rti; | |
| 898 HParameterValue lastAddedParameter; | |
| 899 | |
| 900 Map<TargetElement, JumpHandler> jumpTargets; | |
| 901 | |
| 902 /** | |
| 903 * Variables stored in the current activation. These variables are | |
| 904 * being updated in try/catch blocks, and should be | |
| 905 * accessed indirectly through [HLocalGet] and [HLocalSet]. | |
| 906 */ | |
| 907 Map<Element, HLocalValue> activationVariables; | |
| 908 | |
| 909 // We build the Ssa graph by simulating a stack machine. | |
| 910 List<HInstruction> stack; | |
| 911 | 890 |
| 912 /** | 891 /** |
| 913 * The current block to add instructions to. Might be null, if we are | 892 * The current block to add instructions to. Might be null, if we are |
| 914 * visiting dead code, but see [isReachable]. | 893 * visiting dead code, but see [isReachable]. |
| 915 */ | 894 */ |
| 916 HBasicBlock _current; | 895 HBasicBlock _current; |
| 917 | 896 |
| 918 /** | 897 /** |
| 919 * The most recently opened block. Has the same value as [_current] while | 898 * The most recently opened block. Has the same value as [_current] while |
| 920 * the block is open, but unlike [_current], it isn't cleared when the | 899 * the block is open, but unlike [_current], it isn't cleared when the |
| 921 * current block is closed. | 900 * current block is closed. |
| 922 */ | 901 */ |
| 923 HBasicBlock lastOpenedBlock; | 902 HBasicBlock lastOpenedBlock; |
| 924 | 903 |
| 925 /** | 904 /** |
| 926 * Indicates whether the current block is dead (because it has a throw or a | 905 * Indicates whether the current block is dead (because it has a throw or a |
| 927 * return further up). If this is false, then [_current] may be null. If the | 906 * return further up). If this is false, then [_current] may be null. If the |
| 928 * block is dead then it may also be aborted, but for simplicity we only | 907 * block is dead then it may also be aborted, but for simplicity we only |
| 929 * abort on statement boundaries, not in the middle of expressions. See | 908 * abort on statement boundaries, not in the middle of expressions. See |
| 930 * isAborted. | 909 * isAborted. |
| 931 */ | 910 */ |
| 932 bool isReachable = true; | 911 bool isReachable = true; |
| 933 | 912 |
| 913 HBasicBlock get current => _current; | |
| 914 void set current(c) { | |
| 915 isReachable = c != null; | |
| 916 _current = c; | |
| 917 } | |
| 918 | |
| 919 HBasicBlock addNewBlock() { | |
| 920 HBasicBlock block = graph.addNewBlock(); | |
| 921 // If adding a new block during building of an expression, it is due to | |
| 922 // conditional expressions or short-circuit logical operators. | |
| 923 return block; | |
| 924 } | |
| 925 | |
| 926 void open(HBasicBlock block) { | |
| 927 block.open(); | |
| 928 current = block; | |
| 929 lastOpenedBlock = block; | |
| 930 } | |
| 931 | |
| 932 HBasicBlock close(HControlFlow end) { | |
| 933 HBasicBlock result = current; | |
| 934 current.close(end); | |
| 935 current = null; | |
| 936 return result; | |
| 937 } | |
| 938 | |
| 939 HBasicBlock closeAndGotoExit(HControlFlow end) { | |
| 940 HBasicBlock result = current; | |
| 941 current.close(end); | |
| 942 current = null; | |
| 943 result.addSuccessor(graph.exit); | |
| 944 return result; | |
| 945 } | |
| 946 | |
| 947 void goto(HBasicBlock from, HBasicBlock to) { | |
| 948 from.close(new HGoto()); | |
| 949 from.addSuccessor(to); | |
| 950 } | |
| 951 | |
| 952 bool isAborted() { | |
| 953 return _current == null; | |
| 954 } | |
| 955 | |
| 956 /** | |
| 957 * Creates a new block, transitions to it from any current block, and | |
| 958 * opens the new block. | |
| 959 */ | |
| 960 HBasicBlock openNewBlock() { | |
| 961 HBasicBlock newBlock = addNewBlock(); | |
| 962 if (!isAborted()) goto(current, newBlock); | |
| 963 open(newBlock); | |
| 964 return newBlock; | |
| 965 } | |
| 966 | |
| 967 void add(HInstruction instruction) { | |
| 968 current.add(instruction); | |
| 969 } | |
| 970 } | |
| 971 | |
| 972 class SsaBuilder extends ResolvedVisitor with SsaGraphBuilderMixin { | |
| 973 final SsaBuilderTask builder; | |
| 974 final JavaScriptBackend backend; | |
| 975 final CodegenWorkItem work; | |
| 976 final ConstantSystem constantSystem; | |
| 977 LocalsHandler localsHandler; | |
| 978 HInstruction rethrowableException; | |
| 979 Map<Element, HInstruction> parameters; | |
| 980 final RuntimeTypes rti; | |
| 981 HParameterValue lastAddedParameter; | |
| 982 | |
| 983 Map<TargetElement, JumpHandler> jumpTargets; | |
| 984 | |
| 985 /** | |
| 986 * Variables stored in the current activation. These variables are | |
| 987 * being updated in try/catch blocks, and should be | |
| 988 * accessed indirectly through [HLocalGet] and [HLocalSet]. | |
| 989 */ | |
| 990 Map<Element, HLocalValue> activationVariables; | |
| 991 | |
| 992 // We build the Ssa graph by simulating a stack machine. | |
| 993 List<HInstruction> stack; | |
| 994 | |
| 934 /** | 995 /** |
| 935 * True if we are visiting the expression of a throw expression. | 996 * True if we are visiting the expression of a throw expression. |
| 936 */ | 997 */ |
| 937 bool inThrowExpression = false; | 998 bool inThrowExpression = false; |
| 938 | 999 |
| 939 final List<Element> sourceElementStack; | 1000 final List<Element> sourceElementStack; |
| 940 | 1001 |
| 941 Element get currentElement => sourceElementStack.last.declaration; | 1002 Element get currentElement => sourceElementStack.last.declaration; |
| 942 Element get currentNonClosureClass { | 1003 Element get currentNonClosureClass { |
| 943 ClassElement cls = currentElement.getEnclosingClass(); | 1004 ClassElement cls = currentElement.getEnclosingClass(); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 964 // types of the type variables in an environment (like the [LocalsHandler]). | 1025 // types of the type variables in an environment (like the [LocalsHandler]). |
| 965 final List<DartType> currentInlinedInstantiations = <DartType>[]; | 1026 final List<DartType> currentInlinedInstantiations = <DartType>[]; |
| 966 | 1027 |
| 967 Compiler get compiler => builder.compiler; | 1028 Compiler get compiler => builder.compiler; |
| 968 CodeEmitterTask get emitter => builder.emitter; | 1029 CodeEmitterTask get emitter => builder.emitter; |
| 969 | 1030 |
| 970 SsaBuilder(this.constantSystem, SsaBuilderTask builder, CodegenWorkItem work) | 1031 SsaBuilder(this.constantSystem, SsaBuilderTask builder, CodegenWorkItem work) |
| 971 : this.builder = builder, | 1032 : this.builder = builder, |
| 972 this.backend = builder.backend, | 1033 this.backend = builder.backend, |
| 973 this.work = work, | 1034 this.work = work, |
| 974 graph = new HGraph(), | |
| 975 stack = new List<HInstruction>(), | 1035 stack = new List<HInstruction>(), |
| 976 activationVariables = new Map<Element, HLocalValue>(), | 1036 activationVariables = new Map<Element, HLocalValue>(), |
| 977 jumpTargets = new Map<TargetElement, JumpHandler>(), | 1037 jumpTargets = new Map<TargetElement, JumpHandler>(), |
| 978 parameters = new Map<Element, HInstruction>(), | 1038 parameters = new Map<Element, HInstruction>(), |
| 979 sourceElementStack = <Element>[work.element], | 1039 sourceElementStack = <Element>[work.element], |
| 980 inliningStack = <InliningState>[], | 1040 inliningStack = <InliningState>[], |
| 981 rti = builder.backend.rti, | 1041 rti = builder.backend.rti, |
| 982 super(work.resolutionTree, builder.compiler) { | 1042 super(work.resolutionTree, builder.compiler) { |
| 983 localsHandler = new LocalsHandler(this); | 1043 localsHandler = new LocalsHandler(this); |
| 984 } | 1044 } |
| 985 | 1045 |
| 986 List<InliningState> inliningStack; | 1046 List<InliningState> inliningStack; |
| 987 | 1047 |
| 988 Element returnElement; | 1048 Element returnElement; |
| 989 DartType returnType; | 1049 DartType returnType; |
| 990 | 1050 |
| 991 bool inTryStatement = false; | 1051 bool inTryStatement = false; |
| 992 int loopNesting = 0; | 1052 int loopNesting = 0; |
| 993 | 1053 |
| 994 HBasicBlock get current => _current; | |
| 995 void set current(c) { | |
| 996 isReachable = c != null; | |
| 997 _current = c; | |
| 998 } | |
| 999 | |
| 1000 Constant getConstantForNode(Node node) { | 1054 Constant getConstantForNode(Node node) { |
| 1001 ConstantHandler handler = compiler.constantHandler; | 1055 ConstantHandler handler = compiler.constantHandler; |
| 1002 Constant constant = elements.getConstant(node); | 1056 Constant constant = elements.getConstant(node); |
| 1003 assert(invariant(node, constant != null, | 1057 assert(invariant(node, constant != null, |
| 1004 message: 'No constant computed for $node')); | 1058 message: 'No constant computed for $node')); |
| 1005 return constant; | 1059 return constant; |
| 1006 } | 1060 } |
| 1007 | 1061 |
| 1008 HInstruction addConstant(Node node) { | 1062 HInstruction addConstant(Node node) { |
| 1009 return graph.addConstant(getConstantForNode(node), compiler); | 1063 return graph.addConstant(getConstantForNode(node), compiler); |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1218 assert(succeeded); | 1272 assert(succeeded); |
| 1219 } | 1273 } |
| 1220 | 1274 |
| 1221 // Create the inlining state after evaluating the arguments, that | 1275 // Create the inlining state after evaluating the arguments, that |
| 1222 // may have an impact on the state of the current method. | 1276 // may have an impact on the state of the current method. |
| 1223 InliningState state = new InliningState( | 1277 InliningState state = new InliningState( |
| 1224 function, returnElement, returnType, elements, stack, | 1278 function, returnElement, returnType, elements, stack, |
| 1225 localsHandler, inTryStatement); | 1279 localsHandler, inTryStatement); |
| 1226 inTryStatement = false; | 1280 inTryStatement = false; |
| 1227 LocalsHandler newLocalsHandler = new LocalsHandler(this); | 1281 LocalsHandler newLocalsHandler = new LocalsHandler(this); |
| 1228 newLocalsHandler.closureData = | 1282 if (function.hasIrNode(compiler)) { |
| 1229 compiler.closureToClassMapper.computeClosureToClassMapping( | 1283 // TODO(lry): handle ir functions with nested closure definitions. |
|
ngeoffray
2013/11/20 14:55:27
Why can't you call computeClosureToClassMapping?
lukas
2013/11/20 15:13:26
It is an AST visitor, but we don't have a tree ava
| |
| 1230 function, function.parseNode(compiler), elements); | 1284 newLocalsHandler.closureData = |
| 1285 new ClosureClassMap(null, null, null, new ThisElement(function)); | |
| 1286 } else { | |
| 1287 newLocalsHandler.closureData = | |
| 1288 compiler.closureToClassMapper.computeClosureToClassMapping( | |
| 1289 function, function.parseNode(compiler), elements); | |
| 1290 } | |
| 1231 int argumentIndex = 0; | 1291 int argumentIndex = 0; |
| 1232 if (isInstanceMember) { | 1292 if (isInstanceMember) { |
| 1233 newLocalsHandler.updateLocal(newLocalsHandler.closureData.thisElement, | 1293 newLocalsHandler.updateLocal(newLocalsHandler.closureData.thisElement, |
| 1234 compiledArguments[argumentIndex++]); | 1294 compiledArguments[argumentIndex++]); |
| 1235 } | 1295 } |
| 1236 | 1296 |
| 1237 FunctionSignature signature = function.computeSignature(compiler); | 1297 FunctionSignature signature = function.computeSignature(compiler); |
| 1238 signature.orderedForEachParameter((Element parameter) { | 1298 signature.orderedForEachParameter((Element parameter) { |
| 1239 HInstruction argument = compiledArguments[argumentIndex++]; | 1299 HInstruction argument = compiledArguments[argumentIndex++]; |
| 1240 newLocalsHandler.updateLocal(parameter, argument); | 1300 newLocalsHandler.updateLocal(parameter, argument); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1343 && returnType.isEmpty | 1403 && returnType.isEmpty |
| 1344 && !returnType.isNullable) { | 1404 && !returnType.isNullable) { |
| 1345 isReachable = false; | 1405 isReachable = false; |
| 1346 return false; | 1406 return false; |
| 1347 } | 1407 } |
| 1348 } | 1408 } |
| 1349 | 1409 |
| 1350 return true; | 1410 return true; |
| 1351 } | 1411 } |
| 1352 | 1412 |
| 1353 bool heuristicSayGoodToGo(FunctionExpression functionExpression) { | 1413 bool heuristicSayGoodToGo(bool canBeInlined(int maxNodes)) { |
| 1354 // Don't inline recursivly | 1414 // Don't inline recursivly |
| 1355 if (inliningStack.any((entry) => entry.function == function)) { | 1415 if (inliningStack.any((entry) => entry.function == function)) { |
| 1356 return false; | 1416 return false; |
| 1357 } | 1417 } |
| 1358 | 1418 |
| 1359 if (element.isSynthesized) return true; | 1419 if (element.isSynthesized) return true; |
| 1360 | 1420 |
| 1361 if (cachedCanBeInlined == true) return cachedCanBeInlined; | 1421 if (cachedCanBeInlined == true) return cachedCanBeInlined; |
| 1362 | 1422 |
| 1363 if (inThrowExpression) return false; | 1423 if (inThrowExpression) return false; |
| 1364 | 1424 |
| 1365 int numParameters = function.functionSignature.parameterCount; | 1425 int numParameters = function.functionSignature.parameterCount; |
| 1366 int maxInliningNodes; | 1426 int maxInliningNodes; |
| 1367 if (insideLoop) { | 1427 if (insideLoop) { |
| 1368 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + | 1428 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + |
| 1369 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; | 1429 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; |
| 1370 } else { | 1430 } else { |
| 1371 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + | 1431 maxInliningNodes = InlineWeeder.INLINING_NODES_OUTSIDE_LOOP + |
| 1372 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; | 1432 InlineWeeder.INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR * numParameters; |
| 1373 } | 1433 } |
| 1374 bool canBeInlined = InlineWeeder.canBeInlined( | 1434 bool canInline = canBeInlined(maxInliningNodes); |
| 1375 functionExpression, maxInliningNodes); | 1435 if (canInline) { |
| 1376 if (canBeInlined) { | |
| 1377 backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop); | 1436 backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop); |
| 1378 } else { | 1437 } else { |
| 1379 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); | 1438 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); |
| 1380 } | 1439 } |
| 1381 return canBeInlined; | 1440 return canInline; |
| 1382 } | 1441 } |
| 1383 | 1442 |
| 1384 void doInlining(FunctionExpression functionExpression) { | 1443 void doInlining(void visitBody()) { |
| 1385 // Add an explicit null check on the receiver before doing the | 1444 // Add an explicit null check on the receiver before doing the |
| 1386 // inlining. We use [element] to get the same name in the | 1445 // inlining. We use [element] to get the same name in the |
| 1387 // NoSuchMethodError message as if we had called it. | 1446 // NoSuchMethodError message as if we had called it. |
| 1388 if (element.isInstanceMember() | 1447 if (element.isInstanceMember() |
| 1389 && !element.isGenerativeConstructorBody() | 1448 && !element.isGenerativeConstructorBody() |
| 1390 && (selector.mask == null || selector.mask.isNullable)) { | 1449 && (selector.mask == null || selector.mask.isNullable)) { |
| 1391 addWithPosition( | 1450 addWithPosition( |
| 1392 new HFieldGet(null, providedArguments[0], backend.dynamicType, | 1451 new HFieldGet(null, providedArguments[0], backend.dynamicType, |
| 1393 isAssignable: false), | 1452 isAssignable: false), |
| 1394 currentNode); | 1453 currentNode); |
| 1395 } | 1454 } |
| 1396 InliningState state = enterInlinedMethod( | 1455 InliningState state = enterInlinedMethod( |
| 1397 function, selector, providedArguments, currentNode); | 1456 function, selector, providedArguments, currentNode); |
| 1398 | 1457 |
| 1399 inlinedFrom(element, () { | 1458 inlinedFrom(element, () { |
| 1400 FunctionElement function = element; | 1459 FunctionElement function = element; |
| 1401 FunctionSignature signature = function.computeSignature(compiler); | 1460 FunctionSignature signature = function.computeSignature(compiler); |
| 1402 signature.orderedForEachParameter((Element parameter) { | 1461 signature.orderedForEachParameter((Element parameter) { |
| 1403 HInstruction argument = localsHandler.readLocal(parameter); | 1462 HInstruction argument = localsHandler.readLocal(parameter); |
| 1404 potentiallyCheckType(argument, parameter.computeType(compiler)); | 1463 potentiallyCheckType(argument, parameter.computeType(compiler)); |
| 1405 }); | 1464 }); |
| 1406 addInlinedInstantiation(instantiatedType); | 1465 addInlinedInstantiation(instantiatedType); |
| 1407 if (element.isGenerativeConstructor()) { | 1466 if (element.isGenerativeConstructor()) { |
| 1408 buildFactory(element); | 1467 buildFactory(element); |
| 1409 } else { | 1468 } else { |
| 1410 functionExpression.body.accept(this); | 1469 visitBody(); |
| 1411 } | 1470 } |
| 1412 removeInlinedInstantiation(instantiatedType); | 1471 removeInlinedInstantiation(instantiatedType); |
| 1413 }); | 1472 }); |
| 1414 leaveInlinedMethod(state); | 1473 leaveInlinedMethod(state); |
| 1415 } | 1474 } |
| 1416 | 1475 |
| 1417 if (meetsHardConstraints()) { | 1476 if (meetsHardConstraints()) { |
| 1418 FunctionExpression functionExpression = function.parseNode(compiler); | 1477 if (function.hasIrNode(compiler)) { |
| 1419 | 1478 IrFunction irFunction = function.irNode(compiler); |
| 1420 if (heuristicSayGoodToGo(functionExpression)) { | 1479 bool canInline(int n) => IrInlineWeeder.canBeInlined(irFunction, n); |
| 1421 doInlining(functionExpression); | 1480 if (heuristicSayGoodToGo(canInline)) { |
| 1422 return true; | 1481 SsaFromIrInliner irInliner = new SsaFromIrInliner(this); |
| 1482 doInlining(() => irInliner.visitAll(irFunction.statements)); | |
| 1483 return true; | |
| 1484 } | |
| 1485 } else { | |
| 1486 FunctionExpression functionNode = function.parseNode(compiler); | |
| 1487 bool canInline(int n) => InlineWeeder.canBeInlined(functionNode, n); | |
| 1488 if (heuristicSayGoodToGo(canInline)) { | |
| 1489 doInlining(() => functionNode.body.accept(this)); | |
| 1490 return true; | |
| 1491 } | |
| 1423 } | 1492 } |
| 1424 } | 1493 } |
| 1425 | 1494 |
| 1426 return false; | 1495 return false; |
| 1427 } | 1496 } |
| 1428 | 1497 |
| 1429 addInlinedInstantiation(DartType type) { | 1498 addInlinedInstantiation(DartType type) { |
| 1430 if (type != null) { | 1499 if (type != null) { |
| 1431 currentInlinedInstantiations.add(type); | 1500 currentInlinedInstantiations.add(type); |
| 1432 } | 1501 } |
| (...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2040 add(assertIsSubtype); | 2109 add(assertIsSubtype); |
| 2041 } | 2110 } |
| 2042 | 2111 |
| 2043 HGraph closeFunction() { | 2112 HGraph closeFunction() { |
| 2044 // TODO(kasperl): Make this goto an implicit return. | 2113 // TODO(kasperl): Make this goto an implicit return. |
| 2045 if (!isAborted()) closeAndGotoExit(new HGoto()); | 2114 if (!isAborted()) closeAndGotoExit(new HGoto()); |
| 2046 graph.finalize(); | 2115 graph.finalize(); |
| 2047 return graph; | 2116 return graph; |
| 2048 } | 2117 } |
| 2049 | 2118 |
| 2050 HBasicBlock addNewBlock() { | |
| 2051 HBasicBlock block = graph.addNewBlock(); | |
| 2052 // If adding a new block during building of an expression, it is due to | |
| 2053 // conditional expressions or short-circuit logical operators. | |
| 2054 return block; | |
| 2055 } | |
| 2056 | |
| 2057 void open(HBasicBlock block) { | |
| 2058 block.open(); | |
| 2059 current = block; | |
| 2060 lastOpenedBlock = block; | |
| 2061 } | |
| 2062 | |
| 2063 HBasicBlock close(HControlFlow end) { | |
| 2064 HBasicBlock result = current; | |
| 2065 current.close(end); | |
| 2066 current = null; | |
| 2067 return result; | |
| 2068 } | |
| 2069 | |
| 2070 HBasicBlock closeAndGotoExit(HControlFlow end) { | |
| 2071 HBasicBlock result = current; | |
| 2072 current.close(end); | |
| 2073 current = null; | |
| 2074 result.addSuccessor(graph.exit); | |
| 2075 return result; | |
| 2076 } | |
| 2077 | |
| 2078 void goto(HBasicBlock from, HBasicBlock to) { | |
| 2079 from.close(new HGoto()); | |
| 2080 from.addSuccessor(to); | |
| 2081 } | |
| 2082 | |
| 2083 bool isAborted() { | |
| 2084 return _current == null; | |
| 2085 } | |
| 2086 | |
| 2087 /** | |
| 2088 * Creates a new block, transitions to it from any current block, and | |
| 2089 * opens the new block. | |
| 2090 */ | |
| 2091 HBasicBlock openNewBlock() { | |
| 2092 HBasicBlock newBlock = addNewBlock(); | |
| 2093 if (!isAborted()) goto(current, newBlock); | |
| 2094 open(newBlock); | |
| 2095 return newBlock; | |
| 2096 } | |
| 2097 | |
| 2098 void add(HInstruction instruction) { | |
| 2099 current.add(instruction); | |
| 2100 } | |
| 2101 | |
| 2102 void addWithPosition(HInstruction instruction, Node node) { | 2119 void addWithPosition(HInstruction instruction, Node node) { |
| 2103 add(attachPosition(instruction, node)); | 2120 add(attachPosition(instruction, node)); |
| 2104 } | 2121 } |
| 2105 | 2122 |
| 2106 void push(HInstruction instruction) { | 2123 void push(HInstruction instruction) { |
| 2107 add(instruction); | 2124 add(instruction); |
| 2108 stack.add(instruction); | 2125 stack.add(instruction); |
| 2109 } | 2126 } |
| 2110 | 2127 |
| 2111 void pushWithPosition(HInstruction instruction, Node node) { | 2128 void pushWithPosition(HInstruction instruction, Node node) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2148 | 2165 |
| 2149 SourceFileLocation sourceFileLocationForToken(Node node, Token token) { | 2166 SourceFileLocation sourceFileLocationForToken(Node node, Token token) { |
| 2150 Element element = sourceElementStack.last; | 2167 Element element = sourceElementStack.last; |
| 2151 // TODO(johnniwinther): remove the 'element.patch' hack. | 2168 // TODO(johnniwinther): remove the 'element.patch' hack. |
| 2152 if (element is FunctionElement) { | 2169 if (element is FunctionElement) { |
| 2153 FunctionElement functionElement = element; | 2170 FunctionElement functionElement = element; |
| 2154 if (functionElement.patch != null) element = functionElement.patch; | 2171 if (functionElement.patch != null) element = functionElement.patch; |
| 2155 } | 2172 } |
| 2156 Script script = element.getCompilationUnit().script; | 2173 Script script = element.getCompilationUnit().script; |
| 2157 SourceFile sourceFile = script.file; | 2174 SourceFile sourceFile = script.file; |
| 2158 SourceFileLocation location = new SourceFileLocation(sourceFile, token); | 2175 SourceFileLocation location = |
| 2176 new TokenSourceFileLocation(sourceFile, token); | |
| 2159 if (!location.isValid()) { | 2177 if (!location.isValid()) { |
| 2160 throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message( | 2178 throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message( |
| 2161 {'offset': token.charOffset, | 2179 {'offset': token.charOffset, |
| 2162 'fileName': sourceFile.filename, | 2180 'fileName': sourceFile.filename, |
| 2163 'length': sourceFile.length}); | 2181 'length': sourceFile.length}); |
| 2164 } | 2182 } |
| 2165 return location; | 2183 return location; |
| 2166 } | 2184 } |
| 2167 | 2185 |
| 2168 void visit(Node node) { | 2186 void visit(Node node) { |
| (...skipping 3720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5889 new HSubGraphBlockInformation(elseBranch.graph)); | 5907 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5890 | 5908 |
| 5891 HBasicBlock conditionStartBlock = conditionBranch.block; | 5909 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5892 conditionStartBlock.setBlockFlow(info, joinBlock); | 5910 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5893 SubGraph conditionGraph = conditionBranch.graph; | 5911 SubGraph conditionGraph = conditionBranch.graph; |
| 5894 HIf branch = conditionGraph.end.last; | 5912 HIf branch = conditionGraph.end.last; |
| 5895 assert(branch is HIf); | 5913 assert(branch is HIf); |
| 5896 branch.blockInformation = conditionStartBlock.blockFlow; | 5914 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5897 } | 5915 } |
| 5898 } | 5916 } |
| OLD | NEW |