| 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 /** |
| 889 final SsaBuilderTask builder; | 889 * This mixin implements functionality that is shared between the [SsaBuilder] |
| 890 final JavaScriptBackend backend; | 890 * and the [SsaFromIrBuilder] classes. |
| 891 final CodegenWorkItem work; | 891 */ |
| 892 final ConstantSystem constantSystem; | 892 class SsaGraphBuilderMixin { |
| 893 HGraph graph; | 893 final HGraph graph = new HGraph(); |
| 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 | 894 |
| 912 /** | 895 /** |
| 913 * The current block to add instructions to. Might be null, if we are | 896 * The current block to add instructions to. Might be null, if we are |
| 914 * visiting dead code, but see [isReachable]. | 897 * visiting dead code, but see [isReachable]. |
| 915 */ | 898 */ |
| 916 HBasicBlock _current; | 899 HBasicBlock _current; |
| 917 | 900 |
| 918 /** | 901 /** |
| 919 * The most recently opened block. Has the same value as [_current] while | 902 * 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 | 903 * the block is open, but unlike [_current], it isn't cleared when the |
| 921 * current block is closed. | 904 * current block is closed. |
| 922 */ | 905 */ |
| 923 HBasicBlock lastOpenedBlock; | 906 HBasicBlock lastOpenedBlock; |
| 924 | 907 |
| 925 /** | 908 /** |
| 926 * Indicates whether the current block is dead (because it has a throw or a | 909 * 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 | 910 * 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 | 911 * 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 | 912 * abort on statement boundaries, not in the middle of expressions. See |
| 930 * isAborted. | 913 * isAborted. |
| 931 */ | 914 */ |
| 932 bool isReachable = true; | 915 bool isReachable = true; |
| 933 | 916 |
| 917 HBasicBlock get current => _current; |
| 918 void set current(c) { |
| 919 isReachable = c != null; |
| 920 _current = c; |
| 921 } |
| 922 |
| 923 HBasicBlock addNewBlock() { |
| 924 HBasicBlock block = graph.addNewBlock(); |
| 925 // If adding a new block during building of an expression, it is due to |
| 926 // conditional expressions or short-circuit logical operators. |
| 927 return block; |
| 928 } |
| 929 |
| 930 void open(HBasicBlock block) { |
| 931 block.open(); |
| 932 current = block; |
| 933 lastOpenedBlock = block; |
| 934 } |
| 935 |
| 936 HBasicBlock close(HControlFlow end) { |
| 937 HBasicBlock result = current; |
| 938 current.close(end); |
| 939 current = null; |
| 940 return result; |
| 941 } |
| 942 |
| 943 HBasicBlock closeAndGotoExit(HControlFlow end) { |
| 944 HBasicBlock result = current; |
| 945 current.close(end); |
| 946 current = null; |
| 947 result.addSuccessor(graph.exit); |
| 948 return result; |
| 949 } |
| 950 |
| 951 void goto(HBasicBlock from, HBasicBlock to) { |
| 952 from.close(new HGoto()); |
| 953 from.addSuccessor(to); |
| 954 } |
| 955 |
| 956 bool isAborted() { |
| 957 return _current == null; |
| 958 } |
| 959 |
| 960 /** |
| 961 * Creates a new block, transitions to it from any current block, and |
| 962 * opens the new block. |
| 963 */ |
| 964 HBasicBlock openNewBlock() { |
| 965 HBasicBlock newBlock = addNewBlock(); |
| 966 if (!isAborted()) goto(current, newBlock); |
| 967 open(newBlock); |
| 968 return newBlock; |
| 969 } |
| 970 |
| 971 void add(HInstruction instruction) { |
| 972 current.add(instruction); |
| 973 } |
| 974 } |
| 975 |
| 976 class SsaBuilder extends ResolvedVisitor with SsaGraphBuilderMixin { |
| 977 final SsaBuilderTask builder; |
| 978 final JavaScriptBackend backend; |
| 979 final CodegenWorkItem work; |
| 980 final ConstantSystem constantSystem; |
| 981 LocalsHandler localsHandler; |
| 982 HInstruction rethrowableException; |
| 983 Map<Element, HInstruction> parameters; |
| 984 final RuntimeTypes rti; |
| 985 HParameterValue lastAddedParameter; |
| 986 |
| 987 Map<TargetElement, JumpHandler> jumpTargets; |
| 988 |
| 989 /** |
| 990 * Variables stored in the current activation. These variables are |
| 991 * being updated in try/catch blocks, and should be |
| 992 * accessed indirectly through [HLocalGet] and [HLocalSet]. |
| 993 */ |
| 994 Map<Element, HLocalValue> activationVariables; |
| 995 |
| 996 // We build the Ssa graph by simulating a stack machine. |
| 997 List<HInstruction> stack; |
| 998 |
| 934 /** | 999 /** |
| 935 * True if we are visiting the expression of a throw expression. | 1000 * True if we are visiting the expression of a throw expression. |
| 936 */ | 1001 */ |
| 937 bool inThrowExpression = false; | 1002 bool inThrowExpression = false; |
| 938 | 1003 |
| 939 final List<Element> sourceElementStack; | 1004 final List<Element> sourceElementStack; |
| 940 | 1005 |
| 941 Element get currentElement => sourceElementStack.last.declaration; | 1006 Element get currentElement => sourceElementStack.last.declaration; |
| 942 Element get currentNonClosureClass { | 1007 Element get currentNonClosureClass { |
| 943 ClassElement cls = currentElement.getEnclosingClass(); | 1008 ClassElement cls = currentElement.getEnclosingClass(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 964 // types of the type variables in an environment (like the [LocalsHandler]). | 1029 // types of the type variables in an environment (like the [LocalsHandler]). |
| 965 final List<DartType> currentInlinedInstantiations = <DartType>[]; | 1030 final List<DartType> currentInlinedInstantiations = <DartType>[]; |
| 966 | 1031 |
| 967 Compiler get compiler => builder.compiler; | 1032 Compiler get compiler => builder.compiler; |
| 968 CodeEmitterTask get emitter => builder.emitter; | 1033 CodeEmitterTask get emitter => builder.emitter; |
| 969 | 1034 |
| 970 SsaBuilder(this.constantSystem, SsaBuilderTask builder, CodegenWorkItem work) | 1035 SsaBuilder(this.constantSystem, SsaBuilderTask builder, CodegenWorkItem work) |
| 971 : this.builder = builder, | 1036 : this.builder = builder, |
| 972 this.backend = builder.backend, | 1037 this.backend = builder.backend, |
| 973 this.work = work, | 1038 this.work = work, |
| 974 graph = new HGraph(), | |
| 975 stack = new List<HInstruction>(), | 1039 stack = new List<HInstruction>(), |
| 976 activationVariables = new Map<Element, HLocalValue>(), | 1040 activationVariables = new Map<Element, HLocalValue>(), |
| 977 jumpTargets = new Map<TargetElement, JumpHandler>(), | 1041 jumpTargets = new Map<TargetElement, JumpHandler>(), |
| 978 parameters = new Map<Element, HInstruction>(), | 1042 parameters = new Map<Element, HInstruction>(), |
| 979 sourceElementStack = <Element>[work.element], | 1043 sourceElementStack = <Element>[work.element], |
| 980 inliningStack = <InliningState>[], | 1044 inliningStack = <InliningState>[], |
| 981 rti = builder.backend.rti, | 1045 rti = builder.backend.rti, |
| 982 super(work.resolutionTree, builder.compiler) { | 1046 super(work.resolutionTree, builder.compiler) { |
| 983 localsHandler = new LocalsHandler(this); | 1047 localsHandler = new LocalsHandler(this); |
| 984 } | 1048 } |
| 985 | 1049 |
| 986 List<InliningState> inliningStack; | 1050 List<InliningState> inliningStack; |
| 987 | 1051 |
| 988 Element returnElement; | 1052 Element returnElement; |
| 989 DartType returnType; | 1053 DartType returnType; |
| 990 | 1054 |
| 991 bool inTryStatement = false; | 1055 bool inTryStatement = false; |
| 992 int loopNesting = 0; | 1056 int loopNesting = 0; |
| 993 | 1057 |
| 994 HBasicBlock get current => _current; | |
| 995 void set current(c) { | |
| 996 isReachable = c != null; | |
| 997 _current = c; | |
| 998 } | |
| 999 | |
| 1000 Constant getConstantForNode(Node node) { | 1058 Constant getConstantForNode(Node node) { |
| 1001 ConstantHandler handler = compiler.constantHandler; | 1059 ConstantHandler handler = compiler.constantHandler; |
| 1002 Constant constant = elements.getConstant(node); | 1060 Constant constant = elements.getConstant(node); |
| 1003 assert(invariant(node, constant != null, | 1061 assert(invariant(node, constant != null, |
| 1004 message: 'No constant computed for $node')); | 1062 message: 'No constant computed for $node')); |
| 1005 return constant; | 1063 return constant; |
| 1006 } | 1064 } |
| 1007 | 1065 |
| 1008 HInstruction addConstant(Node node) { | 1066 HInstruction addConstant(Node node) { |
| 1009 return graph.addConstant(getConstantForNode(node), compiler); | 1067 return graph.addConstant(getConstantForNode(node), compiler); |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1218 assert(succeeded); | 1276 assert(succeeded); |
| 1219 } | 1277 } |
| 1220 | 1278 |
| 1221 // Create the inlining state after evaluating the arguments, that | 1279 // Create the inlining state after evaluating the arguments, that |
| 1222 // may have an impact on the state of the current method. | 1280 // may have an impact on the state of the current method. |
| 1223 InliningState state = new InliningState( | 1281 InliningState state = new InliningState( |
| 1224 function, returnElement, returnType, elements, stack, | 1282 function, returnElement, returnType, elements, stack, |
| 1225 localsHandler, inTryStatement); | 1283 localsHandler, inTryStatement); |
| 1226 inTryStatement = false; | 1284 inTryStatement = false; |
| 1227 LocalsHandler newLocalsHandler = new LocalsHandler(this); | 1285 LocalsHandler newLocalsHandler = new LocalsHandler(this); |
| 1228 newLocalsHandler.closureData = | 1286 if (compiler.irBuilder.hasIr(function)) { |
| 1229 compiler.closureToClassMapper.computeClosureToClassMapping( | 1287 // TODO(lry): handle ir functions with nested closure definitions. |
| 1230 function, function.parseNode(compiler), elements); | 1288 newLocalsHandler.closureData = |
| 1289 new ClosureClassMap(null, null, null, new ThisElement(function)); |
| 1290 } else { |
| 1291 newLocalsHandler.closureData = |
| 1292 compiler.closureToClassMapper.computeClosureToClassMapping( |
| 1293 function, function.parseNode(compiler), elements); |
| 1294 } |
| 1231 int argumentIndex = 0; | 1295 int argumentIndex = 0; |
| 1232 if (isInstanceMember) { | 1296 if (isInstanceMember) { |
| 1233 newLocalsHandler.updateLocal(newLocalsHandler.closureData.thisElement, | 1297 newLocalsHandler.updateLocal(newLocalsHandler.closureData.thisElement, |
| 1234 compiledArguments[argumentIndex++]); | 1298 compiledArguments[argumentIndex++]); |
| 1235 } | 1299 } |
| 1236 | 1300 |
| 1237 FunctionSignature signature = function.computeSignature(compiler); | 1301 FunctionSignature signature = function.computeSignature(compiler); |
| 1238 signature.orderedForEachParameter((Element parameter) { | 1302 signature.orderedForEachParameter((Element parameter) { |
| 1239 HInstruction argument = compiledArguments[argumentIndex++]; | 1303 HInstruction argument = compiledArguments[argumentIndex++]; |
| 1240 newLocalsHandler.updateLocal(parameter, argument); | 1304 newLocalsHandler.updateLocal(parameter, argument); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1343 && returnType.isEmpty | 1407 && returnType.isEmpty |
| 1344 && !returnType.isNullable) { | 1408 && !returnType.isNullable) { |
| 1345 isReachable = false; | 1409 isReachable = false; |
| 1346 return false; | 1410 return false; |
| 1347 } | 1411 } |
| 1348 } | 1412 } |
| 1349 | 1413 |
| 1350 return true; | 1414 return true; |
| 1351 } | 1415 } |
| 1352 | 1416 |
| 1353 bool heuristicSayGoodToGo(FunctionExpression functionExpression) { | 1417 bool heuristicSayGoodToGo(bool canBeInlined(int maxNodes, bool useMax)) { |
| 1354 // Don't inline recursivly | 1418 // Don't inline recursivly |
| 1355 if (inliningStack.any((entry) => entry.function == function)) { | 1419 if (inliningStack.any((entry) => entry.function == function)) { |
| 1356 return false; | 1420 return false; |
| 1357 } | 1421 } |
| 1358 | 1422 |
| 1359 if (element.isSynthesized) return true; | 1423 if (element.isSynthesized) return true; |
| 1360 | 1424 |
| 1361 if (cachedCanBeInlined == true) return cachedCanBeInlined; | 1425 if (cachedCanBeInlined == true) return cachedCanBeInlined; |
| 1362 | 1426 |
| 1363 if (inThrowExpression) return false; | 1427 if (inThrowExpression) return false; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1375 | 1439 |
| 1376 // If a method is called only once, and all the methods in the | 1440 // If a method is called only once, and all the methods in the |
| 1377 // inlining stack are called only once as well, we know we will | 1441 // inlining stack are called only once as well, we know we will |
| 1378 // save on output size by inlining this method. | 1442 // save on output size by inlining this method. |
| 1379 TypesInferrer inferrer = compiler.typesTask.typesInferrer; | 1443 TypesInferrer inferrer = compiler.typesTask.typesInferrer; |
| 1380 if (inferrer.isCalledOnce(element) | 1444 if (inferrer.isCalledOnce(element) |
| 1381 && (inliningStack.every( | 1445 && (inliningStack.every( |
| 1382 (entry) => inferrer.isCalledOnce(entry.function)))) { | 1446 (entry) => inferrer.isCalledOnce(entry.function)))) { |
| 1383 useMaxInliningNodes = false; | 1447 useMaxInliningNodes = false; |
| 1384 } | 1448 } |
| 1385 bool canBeInlined = InlineWeeder.canBeInlined( | 1449 bool canInline = canBeInlined(maxInliningNodes, useMaxInliningNodes); |
| 1386 functionExpression, maxInliningNodes, useMaxInliningNodes); | 1450 if (canInline) { |
| 1387 if (canBeInlined) { | |
| 1388 backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop); | 1451 backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop); |
| 1389 } else { | 1452 } else { |
| 1390 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); | 1453 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); |
| 1391 } | 1454 } |
| 1392 return canBeInlined; | 1455 return canInline; |
| 1393 } | 1456 } |
| 1394 | 1457 |
| 1395 void doInlining(FunctionExpression functionExpression) { | 1458 void doInlining(void visitBody()) { |
| 1396 // Add an explicit null check on the receiver before doing the | 1459 // Add an explicit null check on the receiver before doing the |
| 1397 // inlining. We use [element] to get the same name in the | 1460 // inlining. We use [element] to get the same name in the |
| 1398 // NoSuchMethodError message as if we had called it. | 1461 // NoSuchMethodError message as if we had called it. |
| 1399 if (element.isInstanceMember() | 1462 if (element.isInstanceMember() |
| 1400 && !element.isGenerativeConstructorBody() | 1463 && !element.isGenerativeConstructorBody() |
| 1401 && (selector.mask == null || selector.mask.isNullable)) { | 1464 && (selector.mask == null || selector.mask.isNullable)) { |
| 1402 addWithPosition( | 1465 addWithPosition( |
| 1403 new HFieldGet(null, providedArguments[0], backend.dynamicType, | 1466 new HFieldGet(null, providedArguments[0], backend.dynamicType, |
| 1404 isAssignable: false), | 1467 isAssignable: false), |
| 1405 currentNode); | 1468 currentNode); |
| 1406 } | 1469 } |
| 1407 InliningState state = enterInlinedMethod( | 1470 InliningState state = enterInlinedMethod( |
| 1408 function, selector, providedArguments, currentNode); | 1471 function, selector, providedArguments, currentNode); |
| 1409 | 1472 |
| 1410 inlinedFrom(element, () { | 1473 inlinedFrom(element, () { |
| 1411 FunctionElement function = element; | 1474 FunctionElement function = element; |
| 1412 FunctionSignature signature = function.computeSignature(compiler); | 1475 FunctionSignature signature = function.computeSignature(compiler); |
| 1413 signature.orderedForEachParameter((Element parameter) { | 1476 signature.orderedForEachParameter((Element parameter) { |
| 1414 HInstruction argument = localsHandler.readLocal(parameter); | 1477 HInstruction argument = localsHandler.readLocal(parameter); |
| 1415 potentiallyCheckType(argument, parameter.computeType(compiler)); | 1478 potentiallyCheckType(argument, parameter.computeType(compiler)); |
| 1416 }); | 1479 }); |
| 1417 addInlinedInstantiation(instantiatedType); | 1480 addInlinedInstantiation(instantiatedType); |
| 1418 if (element.isGenerativeConstructor()) { | 1481 if (element.isGenerativeConstructor()) { |
| 1419 buildFactory(element); | 1482 buildFactory(element); |
| 1420 } else { | 1483 } else { |
| 1421 functionExpression.body.accept(this); | 1484 visitBody(); |
| 1422 } | 1485 } |
| 1423 removeInlinedInstantiation(instantiatedType); | 1486 removeInlinedInstantiation(instantiatedType); |
| 1424 }); | 1487 }); |
| 1425 leaveInlinedMethod(state); | 1488 leaveInlinedMethod(state); |
| 1426 } | 1489 } |
| 1427 | 1490 |
| 1428 if (meetsHardConstraints()) { | 1491 if (meetsHardConstraints()) { |
| 1429 FunctionExpression functionExpression = function.parseNode(compiler); | 1492 if (compiler.irBuilder.hasIr(function)) { |
| 1430 | 1493 IrFunction irFunction = compiler.irBuilder.getIr(function); |
| 1431 if (heuristicSayGoodToGo(functionExpression)) { | 1494 bool canInline(int n, bool b) { |
| 1432 doInlining(functionExpression); | 1495 return IrInlineWeeder.canBeInlined(irFunction, n, b); |
| 1433 return true; | 1496 } |
| 1497 if (heuristicSayGoodToGo(canInline)) { |
| 1498 SsaFromIrInliner irInliner = new SsaFromIrInliner(this); |
| 1499 doInlining(() => irInliner.visitAll(irFunction.statements)); |
| 1500 return true; |
| 1501 } |
| 1502 } else { |
| 1503 FunctionExpression functionNode = function.parseNode(compiler); |
| 1504 bool canInline(int n, bool b) { |
| 1505 return InlineWeeder.canBeInlined(functionNode, n, b); |
| 1506 } |
| 1507 if (heuristicSayGoodToGo(canInline)) { |
| 1508 doInlining(() => functionNode.body.accept(this)); |
| 1509 return true; |
| 1510 } |
| 1434 } | 1511 } |
| 1435 } | 1512 } |
| 1436 | 1513 |
| 1437 return false; | 1514 return false; |
| 1438 } | 1515 } |
| 1439 | 1516 |
| 1440 addInlinedInstantiation(DartType type) { | 1517 addInlinedInstantiation(DartType type) { |
| 1441 if (type != null) { | 1518 if (type != null) { |
| 1442 currentInlinedInstantiations.add(type); | 1519 currentInlinedInstantiations.add(type); |
| 1443 } | 1520 } |
| (...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2051 add(assertIsSubtype); | 2128 add(assertIsSubtype); |
| 2052 } | 2129 } |
| 2053 | 2130 |
| 2054 HGraph closeFunction() { | 2131 HGraph closeFunction() { |
| 2055 // TODO(kasperl): Make this goto an implicit return. | 2132 // TODO(kasperl): Make this goto an implicit return. |
| 2056 if (!isAborted()) closeAndGotoExit(new HGoto()); | 2133 if (!isAborted()) closeAndGotoExit(new HGoto()); |
| 2057 graph.finalize(); | 2134 graph.finalize(); |
| 2058 return graph; | 2135 return graph; |
| 2059 } | 2136 } |
| 2060 | 2137 |
| 2061 HBasicBlock addNewBlock() { | |
| 2062 HBasicBlock block = graph.addNewBlock(); | |
| 2063 // If adding a new block during building of an expression, it is due to | |
| 2064 // conditional expressions or short-circuit logical operators. | |
| 2065 return block; | |
| 2066 } | |
| 2067 | |
| 2068 void open(HBasicBlock block) { | |
| 2069 block.open(); | |
| 2070 current = block; | |
| 2071 lastOpenedBlock = block; | |
| 2072 } | |
| 2073 | |
| 2074 HBasicBlock close(HControlFlow end) { | |
| 2075 HBasicBlock result = current; | |
| 2076 current.close(end); | |
| 2077 current = null; | |
| 2078 return result; | |
| 2079 } | |
| 2080 | |
| 2081 HBasicBlock closeAndGotoExit(HControlFlow end) { | |
| 2082 HBasicBlock result = current; | |
| 2083 current.close(end); | |
| 2084 current = null; | |
| 2085 result.addSuccessor(graph.exit); | |
| 2086 return result; | |
| 2087 } | |
| 2088 | |
| 2089 void goto(HBasicBlock from, HBasicBlock to) { | |
| 2090 from.close(new HGoto()); | |
| 2091 from.addSuccessor(to); | |
| 2092 } | |
| 2093 | |
| 2094 bool isAborted() { | |
| 2095 return _current == null; | |
| 2096 } | |
| 2097 | |
| 2098 /** | |
| 2099 * Creates a new block, transitions to it from any current block, and | |
| 2100 * opens the new block. | |
| 2101 */ | |
| 2102 HBasicBlock openNewBlock() { | |
| 2103 HBasicBlock newBlock = addNewBlock(); | |
| 2104 if (!isAborted()) goto(current, newBlock); | |
| 2105 open(newBlock); | |
| 2106 return newBlock; | |
| 2107 } | |
| 2108 | |
| 2109 void add(HInstruction instruction) { | |
| 2110 current.add(instruction); | |
| 2111 } | |
| 2112 | |
| 2113 void addWithPosition(HInstruction instruction, Node node) { | 2138 void addWithPosition(HInstruction instruction, Node node) { |
| 2114 add(attachPosition(instruction, node)); | 2139 add(attachPosition(instruction, node)); |
| 2115 } | 2140 } |
| 2116 | 2141 |
| 2117 void push(HInstruction instruction) { | 2142 void push(HInstruction instruction) { |
| 2118 add(instruction); | 2143 add(instruction); |
| 2119 stack.add(instruction); | 2144 stack.add(instruction); |
| 2120 } | 2145 } |
| 2121 | 2146 |
| 2122 void pushWithPosition(HInstruction instruction, Node node) { | 2147 void pushWithPosition(HInstruction instruction, Node node) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2159 | 2184 |
| 2160 SourceFileLocation sourceFileLocationForToken(Node node, Token token) { | 2185 SourceFileLocation sourceFileLocationForToken(Node node, Token token) { |
| 2161 Element element = sourceElementStack.last; | 2186 Element element = sourceElementStack.last; |
| 2162 // TODO(johnniwinther): remove the 'element.patch' hack. | 2187 // TODO(johnniwinther): remove the 'element.patch' hack. |
| 2163 if (element is FunctionElement) { | 2188 if (element is FunctionElement) { |
| 2164 FunctionElement functionElement = element; | 2189 FunctionElement functionElement = element; |
| 2165 if (functionElement.patch != null) element = functionElement.patch; | 2190 if (functionElement.patch != null) element = functionElement.patch; |
| 2166 } | 2191 } |
| 2167 Script script = element.getCompilationUnit().script; | 2192 Script script = element.getCompilationUnit().script; |
| 2168 SourceFile sourceFile = script.file; | 2193 SourceFile sourceFile = script.file; |
| 2169 SourceFileLocation location = new SourceFileLocation(sourceFile, token); | 2194 SourceFileLocation location = |
| 2195 new TokenSourceFileLocation(sourceFile, token); |
| 2170 if (!location.isValid()) { | 2196 if (!location.isValid()) { |
| 2171 throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message( | 2197 throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message( |
| 2172 {'offset': token.charOffset, | 2198 {'offset': token.charOffset, |
| 2173 'fileName': sourceFile.filename, | 2199 'fileName': sourceFile.filename, |
| 2174 'length': sourceFile.length}); | 2200 'length': sourceFile.length}); |
| 2175 } | 2201 } |
| 2176 return location; | 2202 return location; |
| 2177 } | 2203 } |
| 2178 | 2204 |
| 2179 void visit(Node node) { | 2205 void visit(Node node) { |
| (...skipping 3758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5938 new HSubGraphBlockInformation(elseBranch.graph)); | 5964 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5939 | 5965 |
| 5940 HBasicBlock conditionStartBlock = conditionBranch.block; | 5966 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5941 conditionStartBlock.setBlockFlow(info, joinBlock); | 5967 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5942 SubGraph conditionGraph = conditionBranch.graph; | 5968 SubGraph conditionGraph = conditionBranch.graph; |
| 5943 HIf branch = conditionGraph.end.last; | 5969 HIf branch = conditionGraph.end.last; |
| 5944 assert(branch is HIf); | 5970 assert(branch is HIf); |
| 5945 branch.blockInformation = conditionStartBlock.blockFlow; | 5971 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5946 } | 5972 } |
| 5947 } | 5973 } |
| OLD | NEW |