| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
| 6 | 6 |
| 7 import '../closure.dart'; | 7 import '../closure.dart'; |
| 8 import '../common.dart'; | 8 import '../common.dart'; |
| 9 import '../common/codegen.dart' show CodegenRegistry; | 9 import '../common/codegen.dart' show CodegenRegistry; |
| 10 import '../common/names.dart'; | 10 import '../common/names.dart'; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 | 79 |
| 80 @override | 80 @override |
| 81 JavaScriptBackend get backend => compiler.backend; | 81 JavaScriptBackend get backend => compiler.backend; |
| 82 | 82 |
| 83 @override | 83 @override |
| 84 TreeElements get elements => astAdapter.elements; | 84 TreeElements get elements => astAdapter.elements; |
| 85 | 85 |
| 86 SourceInformationBuilder sourceInformationBuilder; | 86 SourceInformationBuilder sourceInformationBuilder; |
| 87 final KernelToElementMap _elementMap; | 87 final KernelToElementMap _elementMap; |
| 88 final KernelToTypeInferenceMap _typeInferenceMap; | 88 final KernelToTypeInferenceMap _typeInferenceMap; |
| 89 final KernelToLocalsMap _localsMap; |
| 89 LoopHandler<ir.Node> loopHandler; | 90 LoopHandler<ir.Node> loopHandler; |
| 90 TypeBuilder typeBuilder; | 91 TypeBuilder typeBuilder; |
| 91 | 92 |
| 92 final Map<ir.VariableDeclaration, HInstruction> letBindings = | 93 final Map<ir.VariableDeclaration, HInstruction> letBindings = |
| 93 <ir.VariableDeclaration, HInstruction>{}; | 94 <ir.VariableDeclaration, HInstruction>{}; |
| 94 | 95 |
| 95 /// True if we are visiting the expression of a throw statement; we assume | 96 /// True if we are visiting the expression of a throw statement; we assume |
| 96 /// this is a slow path. | 97 /// this is a slow path. |
| 97 bool _inExpressionOfThrow = false; | 98 bool _inExpressionOfThrow = false; |
| 98 | 99 |
| 99 KernelSsaBuilder( | 100 KernelSsaBuilder( |
| 100 this.targetElement, | 101 this.targetElement, |
| 101 ClassEntity contextClass, | 102 ClassEntity contextClass, |
| 102 this.target, | 103 this.target, |
| 103 this.compiler, | 104 this.compiler, |
| 104 this._elementMap, | 105 this._elementMap, |
| 105 this._typeInferenceMap, | 106 this._typeInferenceMap, |
| 107 this._localsMap, |
| 106 this.closedWorld, | 108 this.closedWorld, |
| 107 this.registry, | 109 this.registry, |
| 108 this.closureToClassMapper, | 110 this.closureToClassMapper, |
| 109 // TODO(het): Should sourceInformationBuilder be in GraphBuilder? | 111 // TODO(het): Should sourceInformationBuilder be in GraphBuilder? |
| 110 this.sourceInformationBuilder, | 112 this.sourceInformationBuilder, |
| 111 this.functionNode, | 113 this.functionNode, |
| 112 {bool targetIsConstructorBody: false}) | 114 {bool targetIsConstructorBody: false}) |
| 113 : this._targetIsConstructorBody = targetIsConstructorBody { | 115 : this._targetIsConstructorBody = targetIsConstructorBody { |
| 114 this.loopHandler = new KernelLoopHandler(this); | 116 this.loopHandler = new KernelLoopHandler(this); |
| 115 typeBuilder = new TypeBuilder(this); | 117 typeBuilder = new TypeBuilder(this); |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 | 314 |
| 313 for (ir.Constructor body in constructorChain.reversed) { | 315 for (ir.Constructor body in constructorChain.reversed) { |
| 314 if (_isEmptyStatement(body.function.body)) continue; | 316 if (_isEmptyStatement(body.function.body)) continue; |
| 315 | 317 |
| 316 List<HInstruction> bodyCallInputs = <HInstruction>[]; | 318 List<HInstruction> bodyCallInputs = <HInstruction>[]; |
| 317 bodyCallInputs.add(newObject); | 319 bodyCallInputs.add(newObject); |
| 318 | 320 |
| 319 // Pass uncaptured arguments first, captured arguments in a box, then type | 321 // Pass uncaptured arguments first, captured arguments in a box, then type |
| 320 // arguments. | 322 // arguments. |
| 321 | 323 |
| 322 ConstructorElement constructorElement = astAdapter.getConstructor(body); | 324 ConstructorElement constructorElement = _elementMap.getConstructor(body); |
| 323 ClosureClassMap parameterClosureData = | 325 ClosureClassMap parameterClosureData = |
| 324 closureToClassMapper.getMemberMap(constructorElement); | 326 closureToClassMapper.getMemberMap(constructorElement); |
| 325 | 327 |
| 326 var functionSignature = astAdapter.getFunctionSignature(body.function); | 328 var functionSignature = astAdapter.getFunctionSignature(body.function); |
| 327 // Provide the parameters to the generative constructor body. | 329 // Provide the parameters to the generative constructor body. |
| 328 functionSignature.orderedForEachParameter((ParameterElement parameter) { | 330 functionSignature.orderedForEachParameter((ParameterElement parameter) { |
| 329 // If [parameter] is boxed, it will be a field in the box passed as the | 331 // If [parameter] is boxed, it will be a field in the box passed as the |
| 330 // last parameter. So no need to directly pass it. | 332 // last parameter. So no need to directly pass it. |
| 331 if (!localsHandler.isBoxed(parameter)) { | 333 if (!localsHandler.isBoxed(parameter)) { |
| 332 bodyCallInputs.add(localsHandler.readLocal(parameter)); | 334 bodyCallInputs.add(localsHandler.readLocal(parameter)); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 /// Sets context for generating code that is the result of inlining | 380 /// Sets context for generating code that is the result of inlining |
| 379 /// [inlinedTarget]. | 381 /// [inlinedTarget]. |
| 380 inlinedFrom(MemberEntity inlinedTarget, f()) { | 382 inlinedFrom(MemberEntity inlinedTarget, f()) { |
| 381 reporter.withCurrentElement(inlinedTarget, () { | 383 reporter.withCurrentElement(inlinedTarget, () { |
| 382 SourceInformationBuilder oldSourceInformationBuilder = | 384 SourceInformationBuilder oldSourceInformationBuilder = |
| 383 sourceInformationBuilder; | 385 sourceInformationBuilder; |
| 384 // TODO(sra): Update sourceInformationBuilder to Kernel. | 386 // TODO(sra): Update sourceInformationBuilder to Kernel. |
| 385 // sourceInformationBuilder = | 387 // sourceInformationBuilder = |
| 386 // sourceInformationBuilder.forContext(resolvedAst); | 388 // sourceInformationBuilder.forContext(resolvedAst); |
| 387 | 389 |
| 388 _elementMap.enterInlinedMember(inlinedTarget); | 390 _localsMap.enterInlinedMember(inlinedTarget); |
| 389 _targetStack.add(inlinedTarget); | 391 _targetStack.add(inlinedTarget); |
| 390 var result = f(); | 392 var result = f(); |
| 391 sourceInformationBuilder = oldSourceInformationBuilder; | 393 sourceInformationBuilder = oldSourceInformationBuilder; |
| 392 _targetStack.removeLast(); | 394 _targetStack.removeLast(); |
| 393 _elementMap.leaveInlinedMember(inlinedTarget); | 395 _localsMap.leaveInlinedMember(inlinedTarget); |
| 394 return result; | 396 return result; |
| 395 }); | 397 }); |
| 396 } | 398 } |
| 397 | 399 |
| 398 /// Maps the instance fields of a class to their SSA values. | 400 /// Maps the instance fields of a class to their SSA values. |
| 399 Map<FieldEntity, HInstruction> _collectFieldValues(ir.Class clazz) { | 401 Map<FieldEntity, HInstruction> _collectFieldValues(ir.Class clazz) { |
| 400 Map<FieldEntity, HInstruction> fieldValues = <FieldEntity, HInstruction>{}; | 402 Map<FieldEntity, HInstruction> fieldValues = <FieldEntity, HInstruction>{}; |
| 401 | 403 |
| 402 for (ir.Field node in clazz.fields) { | 404 for (ir.Field node in clazz.fields) { |
| 403 if (node.isInstanceMember) { | 405 if (node.isInstanceMember) { |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 954 // Find a type for the element. Use the element type of the indexer of the | 956 // Find a type for the element. Use the element type of the indexer of the |
| 955 // array, as this is stronger than the iterator's `get current` type, for | 957 // array, as this is stronger than the iterator's `get current` type, for |
| 956 // example, `get current` includes null. | 958 // example, `get current` includes null. |
| 957 // TODO(sra): The element type of a container type mask might be better. | 959 // TODO(sra): The element type of a container type mask might be better. |
| 958 TypeMask type = _typeInferenceMap.inferredIndexType(forInStatement); | 960 TypeMask type = _typeInferenceMap.inferredIndexType(forInStatement); |
| 959 | 961 |
| 960 HInstruction index = localsHandler.readLocal(indexVariable); | 962 HInstruction index = localsHandler.readLocal(indexVariable); |
| 961 HInstruction value = new HIndex(array, index, null, type); | 963 HInstruction value = new HIndex(array, index, null, type); |
| 962 add(value); | 964 add(value); |
| 963 | 965 |
| 964 Local loopVariableLocal = astAdapter.getLocal(forInStatement.variable); | 966 Local loopVariableLocal = _localsMap.getLocal(forInStatement.variable); |
| 965 localsHandler.updateLocal(loopVariableLocal, value); | 967 localsHandler.updateLocal(loopVariableLocal, value); |
| 966 // Hint to name loop value after name of loop variable. | 968 // Hint to name loop value after name of loop variable. |
| 967 if (loopVariableLocal is! SyntheticLocal) { | 969 if (loopVariableLocal is! SyntheticLocal) { |
| 968 value.sourceElement ??= loopVariableLocal; | 970 value.sourceElement ??= loopVariableLocal; |
| 969 } | 971 } |
| 970 | 972 |
| 971 forInStatement.body.accept(this); | 973 forInStatement.body.accept(this); |
| 972 } | 974 } |
| 973 | 975 |
| 974 void buildUpdate() { | 976 void buildUpdate() { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1015 TypeMask mask = _typeInferenceMap.typeOfIteratorMoveNext(forInStatement); | 1017 TypeMask mask = _typeInferenceMap.typeOfIteratorMoveNext(forInStatement); |
| 1016 _pushDynamicInvocation(forInStatement, mask, <HInstruction>[iterator], | 1018 _pushDynamicInvocation(forInStatement, mask, <HInstruction>[iterator], |
| 1017 selector: Selectors.moveNext); | 1019 selector: Selectors.moveNext); |
| 1018 return popBoolified(); | 1020 return popBoolified(); |
| 1019 } | 1021 } |
| 1020 | 1022 |
| 1021 void buildBody() { | 1023 void buildBody() { |
| 1022 TypeMask mask = _typeInferenceMap.typeOfIteratorCurrent(forInStatement); | 1024 TypeMask mask = _typeInferenceMap.typeOfIteratorCurrent(forInStatement); |
| 1023 _pushDynamicInvocation(forInStatement, mask, [iterator], | 1025 _pushDynamicInvocation(forInStatement, mask, [iterator], |
| 1024 selector: Selectors.current); | 1026 selector: Selectors.current); |
| 1025 Local loopVariableLocal = astAdapter.getLocal(forInStatement.variable); | 1027 Local loopVariableLocal = _localsMap.getLocal(forInStatement.variable); |
| 1026 HInstruction value = pop(); | 1028 HInstruction value = pop(); |
| 1027 localsHandler.updateLocal(loopVariableLocal, value); | 1029 localsHandler.updateLocal(loopVariableLocal, value); |
| 1028 // Hint to name loop value after name of loop variable. | 1030 // Hint to name loop value after name of loop variable. |
| 1029 if (loopVariableLocal is! SyntheticLocal) { | 1031 if (loopVariableLocal is! SyntheticLocal) { |
| 1030 value.sourceElement ??= loopVariableLocal; | 1032 value.sourceElement ??= loopVariableLocal; |
| 1031 } | 1033 } |
| 1032 forInStatement.body.accept(this); | 1034 forInStatement.body.accept(this); |
| 1033 } | 1035 } |
| 1034 | 1036 |
| 1035 loopHandler.handleLoop( | 1037 loopHandler.handleLoop( |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1057 HInstruction future = pop(); | 1059 HInstruction future = pop(); |
| 1058 push(new HAwait(future, closedWorld.commonMasks.dynamicType)); | 1060 push(new HAwait(future, closedWorld.commonMasks.dynamicType)); |
| 1059 return popBoolified(); | 1061 return popBoolified(); |
| 1060 } | 1062 } |
| 1061 | 1063 |
| 1062 void buildBody() { | 1064 void buildBody() { |
| 1063 TypeMask mask = _typeInferenceMap.typeOfIteratorCurrent(forInStatement); | 1065 TypeMask mask = _typeInferenceMap.typeOfIteratorCurrent(forInStatement); |
| 1064 _pushDynamicInvocation(forInStatement, mask, [streamIterator], | 1066 _pushDynamicInvocation(forInStatement, mask, [streamIterator], |
| 1065 selector: Selectors.current); | 1067 selector: Selectors.current); |
| 1066 localsHandler.updateLocal( | 1068 localsHandler.updateLocal( |
| 1067 astAdapter.getLocal(forInStatement.variable), pop()); | 1069 _localsMap.getLocal(forInStatement.variable), pop()); |
| 1068 forInStatement.body.accept(this); | 1070 forInStatement.body.accept(this); |
| 1069 } | 1071 } |
| 1070 | 1072 |
| 1071 void buildUpdate() {} | 1073 void buildUpdate() {} |
| 1072 | 1074 |
| 1073 // Creates a synthetic try/finally block in case anything async goes amiss. | 1075 // Creates a synthetic try/finally block in case anything async goes amiss. |
| 1074 TryCatchFinallyBuilder tryBuilder = new TryCatchFinallyBuilder(this); | 1076 TryCatchFinallyBuilder tryBuilder = new TryCatchFinallyBuilder(this); |
| 1075 // Build fake try body: | 1077 // Build fake try body: |
| 1076 loopHandler.handleLoop(forInStatement, buildInitializer, buildCondition, | 1078 loopHandler.handleLoop(forInStatement, buildInitializer, buildCondition, |
| 1077 buildUpdate, buildBody); | 1079 buildUpdate, buildBody); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1124 @override | 1126 @override |
| 1125 visitDoStatement(ir.DoStatement doStatement) { | 1127 visitDoStatement(ir.DoStatement doStatement) { |
| 1126 // TODO(efortuna): I think this can be rewritten using | 1128 // TODO(efortuna): I think this can be rewritten using |
| 1127 // LoopHandler.handleLoop with some tricks about when the "update" happens. | 1129 // LoopHandler.handleLoop with some tricks about when the "update" happens. |
| 1128 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1130 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
| 1129 localsHandler.startLoop(astAdapter.getNode(doStatement)); | 1131 localsHandler.startLoop(astAdapter.getNode(doStatement)); |
| 1130 JumpHandler jumpHandler = loopHandler.beginLoopHeader(doStatement); | 1132 JumpHandler jumpHandler = loopHandler.beginLoopHeader(doStatement); |
| 1131 HLoopInformation loopInfo = current.loopInformation; | 1133 HLoopInformation loopInfo = current.loopInformation; |
| 1132 HBasicBlock loopEntryBlock = current; | 1134 HBasicBlock loopEntryBlock = current; |
| 1133 HBasicBlock bodyEntryBlock = current; | 1135 HBasicBlock bodyEntryBlock = current; |
| 1134 JumpTarget target = astAdapter.getJumpTarget(doStatement); | 1136 JumpTarget target = _localsMap.getJumpTarget(doStatement); |
| 1135 bool hasContinues = target != null && target.isContinueTarget; | 1137 bool hasContinues = target != null && target.isContinueTarget; |
| 1136 if (hasContinues) { | 1138 if (hasContinues) { |
| 1137 // Add extra block to hang labels on. | 1139 // Add extra block to hang labels on. |
| 1138 // It doesn't currently work if they are on the same block as the | 1140 // It doesn't currently work if they are on the same block as the |
| 1139 // HLoopInfo. The handling of HLabeledBlockInformation will visit a | 1141 // HLoopInfo. The handling of HLabeledBlockInformation will visit a |
| 1140 // SubGraph that starts at the same block again, so the HLoopInfo is | 1142 // SubGraph that starts at the same block again, so the HLoopInfo is |
| 1141 // either handled twice, or it's handled after the labeled block info, | 1143 // either handled twice, or it's handled after the labeled block info, |
| 1142 // both of which generate the wrong code. | 1144 // both of which generate the wrong code. |
| 1143 // Using a separate block is just a simple workaround. | 1145 // Using a separate block is just a simple workaround. |
| 1144 bodyEntryBlock = openNewBlock(); | 1146 bodyEntryBlock = openNewBlock(); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1236 loopEntryBlock.loopInformation = null; | 1238 loopEntryBlock.loopInformation = null; |
| 1237 | 1239 |
| 1238 if (jumpHandler.hasAnyBreak()) { | 1240 if (jumpHandler.hasAnyBreak()) { |
| 1239 // Null branchBlock because the body of the do-while loop always aborts, | 1241 // Null branchBlock because the body of the do-while loop always aborts, |
| 1240 // so we never get to the condition. | 1242 // so we never get to the condition. |
| 1241 loopHandler.endLoop(loopEntryBlock, null, jumpHandler, localsHandler); | 1243 loopHandler.endLoop(loopEntryBlock, null, jumpHandler, localsHandler); |
| 1242 | 1244 |
| 1243 // Since the body of the loop has a break, we attach a synthesized label | 1245 // Since the body of the loop has a break, we attach a synthesized label |
| 1244 // to the body. | 1246 // to the body. |
| 1245 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); | 1247 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
| 1246 JumpTarget target = astAdapter.getJumpTarget(doStatement); | 1248 JumpTarget target = _localsMap.getJumpTarget(doStatement); |
| 1247 LabelDefinition label = target.addLabel(null, 'loop'); | 1249 LabelDefinition label = target.addLabel(null, 'loop'); |
| 1248 label.setBreakTarget(); | 1250 label.setBreakTarget(); |
| 1249 HLabeledBlockInformation info = new HLabeledBlockInformation( | 1251 HLabeledBlockInformation info = new HLabeledBlockInformation( |
| 1250 new HSubGraphBlockInformation(bodyGraph), <LabelDefinition>[label]); | 1252 new HSubGraphBlockInformation(bodyGraph), <LabelDefinition>[label]); |
| 1251 loopEntryBlock.setBlockFlow(info, current); | 1253 loopEntryBlock.setBlockFlow(info, current); |
| 1252 jumpHandler.forEachBreak((HBreak breakInstruction, _) { | 1254 jumpHandler.forEachBreak((HBreak breakInstruction, _) { |
| 1253 HBasicBlock block = breakInstruction.block; | 1255 HBasicBlock block = breakInstruction.block; |
| 1254 block.addAtExit(new HBreak.toLabel(label)); | 1256 block.addAtExit(new HBreak.toLabel(label)); |
| 1255 block.remove(breakInstruction); | 1257 block.remove(breakInstruction); |
| 1256 }); | 1258 }); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1361 } | 1363 } |
| 1362 | 1364 |
| 1363 /// Creates a [JumpHandler] for a statement. The node must be a jump | 1365 /// Creates a [JumpHandler] for a statement. The node must be a jump |
| 1364 /// target. If there are no breaks or continues targeting the statement, | 1366 /// target. If there are no breaks or continues targeting the statement, |
| 1365 /// a special "null handler" is returned. | 1367 /// a special "null handler" is returned. |
| 1366 /// | 1368 /// |
| 1367 /// [isLoopJump] is true when the jump handler is for a loop. This is used | 1369 /// [isLoopJump] is true when the jump handler is for a loop. This is used |
| 1368 /// to distinguish the synthesized loop created for a switch statement with | 1370 /// to distinguish the synthesized loop created for a switch statement with |
| 1369 /// continue statements from simple switch statements. | 1371 /// continue statements from simple switch statements. |
| 1370 JumpHandler createJumpHandler(ir.TreeNode node, {bool isLoopJump: false}) { | 1372 JumpHandler createJumpHandler(ir.TreeNode node, {bool isLoopJump: false}) { |
| 1371 JumpTarget target = astAdapter.getJumpTarget(node); | 1373 JumpTarget target = _localsMap.getJumpTarget(node); |
| 1372 assert(target is KernelJumpTarget); | 1374 assert(target is KernelJumpTarget); |
| 1373 if (target == null) { | 1375 if (target == null) { |
| 1374 // No breaks or continues to this node. | 1376 // No breaks or continues to this node. |
| 1375 return new NullJumpHandler(reporter); | 1377 return new NullJumpHandler(reporter); |
| 1376 } | 1378 } |
| 1377 if (isLoopJump && node is ir.SwitchStatement) { | 1379 if (isLoopJump && node is ir.SwitchStatement) { |
| 1378 return new KernelSwitchCaseJumpHandler(this, target, node, astAdapter); | 1380 return new KernelSwitchCaseJumpHandler(this, target, node, _localsMap); |
| 1379 } | 1381 } |
| 1380 | 1382 |
| 1381 return new JumpHandler(this, target); | 1383 return new JumpHandler(this, target); |
| 1382 } | 1384 } |
| 1383 | 1385 |
| 1384 @override | 1386 @override |
| 1385 void visitBreakStatement(ir.BreakStatement breakStatement) { | 1387 void visitBreakStatement(ir.BreakStatement breakStatement) { |
| 1386 assert(!isAborted()); | 1388 assert(!isAborted()); |
| 1387 handleInTryStatement(); | 1389 handleInTryStatement(); |
| 1388 JumpTarget target = astAdapter.getJumpTarget(breakStatement.target); | 1390 JumpTarget target = _localsMap.getJumpTarget(breakStatement.target); |
| 1389 assert(target != null); | 1391 assert(target != null); |
| 1390 JumpHandler handler = jumpTargets[target]; | 1392 JumpHandler handler = jumpTargets[target]; |
| 1391 assert(handler != null); | 1393 assert(handler != null); |
| 1392 if (handler.labels.isNotEmpty) { | 1394 if (handler.labels.isNotEmpty) { |
| 1393 handler.generateBreak(handler.labels.first); | 1395 handler.generateBreak(handler.labels.first); |
| 1394 } else { | 1396 } else { |
| 1395 handler.generateBreak(); | 1397 handler.generateBreak(); |
| 1396 } | 1398 } |
| 1397 } | 1399 } |
| 1398 | 1400 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1451 constants[caseExpression] = constant; | 1453 constants[caseExpression] = constant; |
| 1452 } | 1454 } |
| 1453 } | 1455 } |
| 1454 return constants; | 1456 return constants; |
| 1455 } | 1457 } |
| 1456 | 1458 |
| 1457 @override | 1459 @override |
| 1458 void visitContinueSwitchStatement( | 1460 void visitContinueSwitchStatement( |
| 1459 ir.ContinueSwitchStatement switchStatement) { | 1461 ir.ContinueSwitchStatement switchStatement) { |
| 1460 handleInTryStatement(); | 1462 handleInTryStatement(); |
| 1461 JumpTarget target = astAdapter.getJumpTarget(switchStatement.target); | 1463 JumpTarget target = _localsMap.getJumpTarget(switchStatement.target); |
| 1462 assert(target != null); | 1464 assert(target != null); |
| 1463 JumpHandler handler = jumpTargets[target]; | 1465 JumpHandler handler = jumpTargets[target]; |
| 1464 assert(handler != null); | 1466 assert(handler != null); |
| 1465 assert(target.labels.isNotEmpty); | 1467 assert(target.labels.isNotEmpty); |
| 1466 handler.generateContinue(target.labels.first); | 1468 handler.generateContinue(target.labels.first); |
| 1467 } | 1469 } |
| 1468 | 1470 |
| 1469 @override | 1471 @override |
| 1470 void visitSwitchStatement(ir.SwitchStatement switchStatement) { | 1472 void visitSwitchStatement(ir.SwitchStatement switchStatement) { |
| 1471 // The switch case indices must match those computed in | 1473 // The switch case indices must match those computed in |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1571 // case 1: s_1; break l; | 1573 // case 1: s_1; break l; |
| 1572 // case 2: s_2; target = i; continue l; | 1574 // case 2: s_2; target = i; continue l; |
| 1573 // ... | 1575 // ... |
| 1574 // case n: s_n; target = j; continue l; | 1576 // case n: s_n; target = j; continue l; |
| 1575 // } | 1577 // } |
| 1576 // } | 1578 // } |
| 1577 // | 1579 // |
| 1578 // This is because JS does not have this same "continue label" semantics so | 1580 // This is because JS does not have this same "continue label" semantics so |
| 1579 // we encode it in the form of a state machine. | 1581 // we encode it in the form of a state machine. |
| 1580 | 1582 |
| 1581 JumpTarget switchTarget = astAdapter.getJumpTarget(switchStatement); | 1583 JumpTarget switchTarget = _localsMap.getJumpTarget(switchStatement); |
| 1582 localsHandler.updateLocal(switchTarget, graph.addConstantNull(closedWorld)); | 1584 localsHandler.updateLocal(switchTarget, graph.addConstantNull(closedWorld)); |
| 1583 | 1585 |
| 1584 var switchCases = switchStatement.cases; | 1586 var switchCases = switchStatement.cases; |
| 1585 if (!hasDefault) { | 1587 if (!hasDefault) { |
| 1586 // Use null as the marker for a synthetic default clause. | 1588 // Use null as the marker for a synthetic default clause. |
| 1587 // The synthetic default is added because otherwise there would be no | 1589 // The synthetic default is added because otherwise there would be no |
| 1588 // good place to give a default value to the local. | 1590 // good place to give a default value to the local. |
| 1589 switchCases = new List<ir.SwitchCase>.from(switchCases); | 1591 switchCases = new List<ir.SwitchCase>.from(switchCases); |
| 1590 switchCases.add(null); | 1592 switchCases.add(null); |
| 1591 } | 1593 } |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2044 | 2046 |
| 2045 @override | 2047 @override |
| 2046 void visitVariableGet(ir.VariableGet variableGet) { | 2048 void visitVariableGet(ir.VariableGet variableGet) { |
| 2047 ir.VariableDeclaration variable = variableGet.variable; | 2049 ir.VariableDeclaration variable = variableGet.variable; |
| 2048 HInstruction letBinding = letBindings[variable]; | 2050 HInstruction letBinding = letBindings[variable]; |
| 2049 if (letBinding != null) { | 2051 if (letBinding != null) { |
| 2050 stack.add(letBinding); | 2052 stack.add(letBinding); |
| 2051 return; | 2053 return; |
| 2052 } | 2054 } |
| 2053 | 2055 |
| 2054 Local local = astAdapter.getLocal(variableGet.variable); | 2056 Local local = _localsMap.getLocal(variableGet.variable); |
| 2055 stack.add(localsHandler.readLocal(local)); | 2057 stack.add(localsHandler.readLocal(local)); |
| 2056 } | 2058 } |
| 2057 | 2059 |
| 2058 @override | 2060 @override |
| 2059 void visitPropertySet(ir.PropertySet propertySet) { | 2061 void visitPropertySet(ir.PropertySet propertySet) { |
| 2060 propertySet.receiver.accept(this); | 2062 propertySet.receiver.accept(this); |
| 2061 HInstruction receiver = pop(); | 2063 HInstruction receiver = pop(); |
| 2062 propertySet.value.accept(this); | 2064 propertySet.value.accept(this); |
| 2063 HInstruction value = pop(); | 2065 HInstruction value = pop(); |
| 2064 | 2066 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2092 | 2094 |
| 2093 @override | 2095 @override |
| 2094 void visitVariableSet(ir.VariableSet variableSet) { | 2096 void visitVariableSet(ir.VariableSet variableSet) { |
| 2095 variableSet.value.accept(this); | 2097 variableSet.value.accept(this); |
| 2096 HInstruction value = pop(); | 2098 HInstruction value = pop(); |
| 2097 _visitLocalSetter(variableSet.variable, value); | 2099 _visitLocalSetter(variableSet.variable, value); |
| 2098 } | 2100 } |
| 2099 | 2101 |
| 2100 @override | 2102 @override |
| 2101 void visitVariableDeclaration(ir.VariableDeclaration declaration) { | 2103 void visitVariableDeclaration(ir.VariableDeclaration declaration) { |
| 2102 Local local = astAdapter.getLocal(declaration); | 2104 Local local = _localsMap.getLocal(declaration); |
| 2103 if (declaration.initializer == null) { | 2105 if (declaration.initializer == null) { |
| 2104 HInstruction initialValue = graph.addConstantNull(closedWorld); | 2106 HInstruction initialValue = graph.addConstantNull(closedWorld); |
| 2105 localsHandler.updateLocal(local, initialValue); | 2107 localsHandler.updateLocal(local, initialValue); |
| 2106 } else { | 2108 } else { |
| 2107 declaration.initializer.accept(this); | 2109 declaration.initializer.accept(this); |
| 2108 HInstruction initialValue = pop(); | 2110 HInstruction initialValue = pop(); |
| 2109 | 2111 |
| 2110 _visitLocalSetter(declaration, initialValue); | 2112 _visitLocalSetter(declaration, initialValue); |
| 2111 | 2113 |
| 2112 // Ignore value | 2114 // Ignore value |
| 2113 pop(); | 2115 pop(); |
| 2114 } | 2116 } |
| 2115 } | 2117 } |
| 2116 | 2118 |
| 2117 void _visitLocalSetter(ir.VariableDeclaration variable, HInstruction value) { | 2119 void _visitLocalSetter(ir.VariableDeclaration variable, HInstruction value) { |
| 2118 LocalElement local = astAdapter.getLocal(variable); | 2120 LocalElement local = _localsMap.getLocal(variable); |
| 2119 | 2121 |
| 2120 // Give the value a name if it doesn't have one already. | 2122 // Give the value a name if it doesn't have one already. |
| 2121 if (value.sourceElement == null) { | 2123 if (value.sourceElement == null) { |
| 2122 value.sourceElement = local; | 2124 value.sourceElement = local; |
| 2123 } | 2125 } |
| 2124 | 2126 |
| 2125 stack.add(value); | 2127 stack.add(value); |
| 2126 localsHandler.updateLocal( | 2128 localsHandler.updateLocal( |
| 2127 local, | 2129 local, |
| 2128 typeBuilder.potentiallyCheckOrTrustType( | 2130 typeBuilder.potentiallyCheckOrTrustType( |
| (...skipping 1203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3332 // `guard` is often `dynamic`, which generates `true`. | 3334 // `guard` is often `dynamic`, which generates `true`. |
| 3333 kernelBuilder.pushIsTest( | 3335 kernelBuilder.pushIsTest( |
| 3334 catchBlock.exception, catchBlock.guard, unwrappedException); | 3336 catchBlock.exception, catchBlock.guard, unwrappedException); |
| 3335 } | 3337 } |
| 3336 | 3338 |
| 3337 void visitThen() { | 3339 void visitThen() { |
| 3338 ir.Catch catchBlock = tryCatch.catches[catchesIndex]; | 3340 ir.Catch catchBlock = tryCatch.catches[catchesIndex]; |
| 3339 catchesIndex++; | 3341 catchesIndex++; |
| 3340 if (catchBlock.exception != null) { | 3342 if (catchBlock.exception != null) { |
| 3341 LocalVariableElement exceptionVariable = | 3343 LocalVariableElement exceptionVariable = |
| 3342 kernelBuilder.astAdapter.getLocal(catchBlock.exception); | 3344 kernelBuilder._localsMap.getLocal(catchBlock.exception); |
| 3343 kernelBuilder.localsHandler | 3345 kernelBuilder.localsHandler |
| 3344 .updateLocal(exceptionVariable, unwrappedException); | 3346 .updateLocal(exceptionVariable, unwrappedException); |
| 3345 } | 3347 } |
| 3346 if (catchBlock.stackTrace != null) { | 3348 if (catchBlock.stackTrace != null) { |
| 3347 kernelBuilder._pushStaticInvocation( | 3349 kernelBuilder._pushStaticInvocation( |
| 3348 kernelBuilder._commonElements.traceFromException, | 3350 kernelBuilder._commonElements.traceFromException, |
| 3349 [exception], | 3351 [exception], |
| 3350 kernelBuilder._typeInferenceMap.getReturnTypeOf( | 3352 kernelBuilder._typeInferenceMap.getReturnTypeOf( |
| 3351 kernelBuilder._commonElements.traceFromException)); | 3353 kernelBuilder._commonElements.traceFromException)); |
| 3352 HInstruction traceInstruction = kernelBuilder.pop(); | 3354 HInstruction traceInstruction = kernelBuilder.pop(); |
| 3353 LocalVariableElement traceVariable = | 3355 LocalVariableElement traceVariable = |
| 3354 kernelBuilder.astAdapter.getLocal(catchBlock.stackTrace); | 3356 kernelBuilder._localsMap.getLocal(catchBlock.stackTrace); |
| 3355 kernelBuilder.localsHandler | 3357 kernelBuilder.localsHandler |
| 3356 .updateLocal(traceVariable, traceInstruction); | 3358 .updateLocal(traceVariable, traceInstruction); |
| 3357 } | 3359 } |
| 3358 catchBlock.body.accept(kernelBuilder); | 3360 catchBlock.body.accept(kernelBuilder); |
| 3359 } | 3361 } |
| 3360 | 3362 |
| 3361 void visitElse() { | 3363 void visitElse() { |
| 3362 if (catchesIndex >= tryCatch.catches.length) { | 3364 if (catchesIndex >= tryCatch.catches.length) { |
| 3363 kernelBuilder.closeAndGotoExit(new HThrow( | 3365 kernelBuilder.closeAndGotoExit(new HThrow( |
| 3364 exception, exception.sourceInformation, | 3366 exception, exception.sourceInformation, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3404 enterBlock.setBlockFlow( | 3406 enterBlock.setBlockFlow( |
| 3405 new HTryBlockInformation( | 3407 new HTryBlockInformation( |
| 3406 kernelBuilder.wrapStatementGraph(bodyGraph), | 3408 kernelBuilder.wrapStatementGraph(bodyGraph), |
| 3407 exception, | 3409 exception, |
| 3408 kernelBuilder.wrapStatementGraph(catchGraph), | 3410 kernelBuilder.wrapStatementGraph(catchGraph), |
| 3409 kernelBuilder.wrapStatementGraph(finallyGraph)), | 3411 kernelBuilder.wrapStatementGraph(finallyGraph)), |
| 3410 exitBlock); | 3412 exitBlock); |
| 3411 kernelBuilder.inTryStatement = previouslyInTryStatement; | 3413 kernelBuilder.inTryStatement = previouslyInTryStatement; |
| 3412 } | 3414 } |
| 3413 } | 3415 } |
| OLD | NEW |