| 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 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
| 8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
| 9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
| 10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
| 11 | 11 |
| 12 SsaFunctionCompiler(JavaScriptBackend backend, | 12 SsaFunctionCompiler(JavaScriptBackend backend, |
| 13 SourceInformationFactory sourceInformationFactory) | 13 SourceInformationStrategy sourceInformationFactory) |
| 14 : generator = new SsaCodeGeneratorTask(backend, sourceInformationFactory), | 14 : generator = new SsaCodeGeneratorTask(backend, sourceInformationFactory), |
| 15 builder = new SsaBuilderTask(backend, sourceInformationFactory), | 15 builder = new SsaBuilderTask(backend, sourceInformationFactory), |
| 16 optimizer = new SsaOptimizerTask(backend); | 16 optimizer = new SsaOptimizerTask(backend); |
| 17 | 17 |
| 18 /// Generates JavaScript code for `work.element`. | 18 /// Generates JavaScript code for `work.element`. |
| 19 /// Using the ssa builder, optimizer and codegenerator. | 19 /// Using the ssa builder, optimizer and codegenerator. |
| 20 js.Fun compile(CodegenWorkItem work) { | 20 js.Fun compile(CodegenWorkItem work) { |
| 21 HGraph graph = builder.build(work); | 21 HGraph graph = builder.build(work); |
| 22 optimizer.optimize(work, graph); | 22 optimizer.optimize(work, graph); |
| 23 Element element = work.element; | 23 Element element = work.element; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 final ExecutableElement executableContext; | 90 final ExecutableElement executableContext; |
| 91 | 91 |
| 92 SyntheticLocal(this.name, this.executableContext); | 92 SyntheticLocal(this.name, this.executableContext); |
| 93 | 93 |
| 94 toString() => 'SyntheticLocal($name)'; | 94 toString() => 'SyntheticLocal($name)'; |
| 95 } | 95 } |
| 96 | 96 |
| 97 class SsaBuilderTask extends CompilerTask { | 97 class SsaBuilderTask extends CompilerTask { |
| 98 final CodeEmitterTask emitter; | 98 final CodeEmitterTask emitter; |
| 99 final JavaScriptBackend backend; | 99 final JavaScriptBackend backend; |
| 100 final SourceInformationFactory sourceInformationFactory; | 100 final SourceInformationStrategy sourceInformationFactory; |
| 101 | 101 |
| 102 String get name => 'SSA builder'; | 102 String get name => 'SSA builder'; |
| 103 | 103 |
| 104 SsaBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory) | 104 SsaBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory) |
| 105 : emitter = backend.emitter, | 105 : emitter = backend.emitter, |
| 106 backend = backend, | 106 backend = backend, |
| 107 super(backend.compiler); | 107 super(backend.compiler); |
| 108 | 108 |
| 109 HGraph build(CodegenWorkItem work) { | 109 HGraph build(CodegenWorkItem work) { |
| 110 return measure(() { | 110 return measure(() { |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 | 473 |
| 474 bool isUsedInTryOrGenerator(Local local) { | 474 bool isUsedInTryOrGenerator(Local local) { |
| 475 return closureData.variablesUsedInTryOrGenerator.contains(local); | 475 return closureData.variablesUsedInTryOrGenerator.contains(local); |
| 476 } | 476 } |
| 477 | 477 |
| 478 /** | 478 /** |
| 479 * Returns an [HInstruction] for the given element. If the element is | 479 * Returns an [HInstruction] for the given element. If the element is |
| 480 * boxed or stored in a closure then the method generates code to retrieve | 480 * boxed or stored in a closure then the method generates code to retrieve |
| 481 * the value. | 481 * the value. |
| 482 */ | 482 */ |
| 483 HInstruction readLocal(Local local) { | 483 HInstruction readLocal(Local local, |
| 484 {SourceInformation sourceInformation}) { |
| 484 if (isAccessedDirectly(local)) { | 485 if (isAccessedDirectly(local)) { |
| 485 if (directLocals[local] == null) { | 486 if (directLocals[local] == null) { |
| 486 if (local is TypeVariableElement) { | 487 if (local is TypeVariableElement) { |
| 487 builder.compiler.internalError(builder.compiler.currentElement, | 488 builder.compiler.internalError(builder.compiler.currentElement, |
| 488 "Runtime type information not available for $local."); | 489 "Runtime type information not available for $local."); |
| 489 } else { | 490 } else { |
| 490 builder.compiler.internalError(local, | 491 builder.compiler.internalError(local, |
| 491 "Cannot find value $local."); | 492 "Cannot find value $local."); |
| 492 } | 493 } |
| 493 } | 494 } |
| 494 return directLocals[local]; | 495 return directLocals[local]; |
| 495 } else if (isStoredInClosureField(local)) { | 496 } else if (isStoredInClosureField(local)) { |
| 496 ClosureFieldElement redirect = redirectionMapping[local]; | 497 ClosureFieldElement redirect = redirectionMapping[local]; |
| 497 HInstruction receiver = readLocal(closureData.closureElement); | 498 HInstruction receiver = readLocal(closureData.closureElement); |
| 498 TypeMask type = local is BoxLocal | 499 TypeMask type = local is BoxLocal |
| 499 ? builder.backend.nonNullType | 500 ? builder.backend.nonNullType |
| 500 : builder.getTypeOfCapturedVariable(redirect); | 501 : builder.getTypeOfCapturedVariable(redirect); |
| 501 HInstruction fieldGet = new HFieldGet(redirect, receiver, type); | 502 HInstruction fieldGet = new HFieldGet(redirect, receiver, type); |
| 502 builder.add(fieldGet); | 503 builder.add(fieldGet); |
| 503 return fieldGet; | 504 return fieldGet..sourceInformation = sourceInformation; |
| 504 } else if (isBoxed(local)) { | 505 } else if (isBoxed(local)) { |
| 505 BoxFieldElement redirect = redirectionMapping[local]; | 506 BoxFieldElement redirect = redirectionMapping[local]; |
| 506 // In the function that declares the captured variable the box is | 507 // In the function that declares the captured variable the box is |
| 507 // accessed as direct local. Inside the nested closure the box is | 508 // accessed as direct local. Inside the nested closure the box is |
| 508 // accessed through a closure-field. | 509 // accessed through a closure-field. |
| 509 // Calling [readLocal] makes sure we generate the correct code to get | 510 // Calling [readLocal] makes sure we generate the correct code to get |
| 510 // the box. | 511 // the box. |
| 511 HInstruction box = readLocal(redirect.box); | 512 HInstruction box = readLocal(redirect.box); |
| 512 HInstruction lookup = new HFieldGet( | 513 HInstruction lookup = new HFieldGet( |
| 513 redirect, box, builder.getTypeOfCapturedVariable(redirect)); | 514 redirect, box, builder.getTypeOfCapturedVariable(redirect)); |
| 514 builder.add(lookup); | 515 builder.add(lookup); |
| 515 return lookup; | 516 return lookup..sourceInformation = sourceInformation; |
| 516 } else { | 517 } else { |
| 517 assert(isUsedInTryOrGenerator(local)); | 518 assert(isUsedInTryOrGenerator(local)); |
| 518 HLocalValue localValue = getLocal(local); | 519 HLocalValue localValue = getLocal(local); |
| 519 HInstruction instruction = new HLocalGet( | 520 HInstruction instruction = new HLocalGet( |
| 520 local, localValue, builder.backend.dynamicType); | 521 local, localValue, builder.backend.dynamicType); |
| 521 builder.add(instruction); | 522 builder.add(instruction); |
| 522 return instruction; | 523 return instruction..sourceInformation = sourceInformation; |
| 523 } | 524 } |
| 524 } | 525 } |
| 525 | 526 |
| 526 HInstruction readThis() { | 527 HInstruction readThis() { |
| 527 HInstruction res = readLocal(closureData.thisLocal); | 528 HInstruction res = readLocal(closureData.thisLocal); |
| 528 if (res.instructionType == null) { | 529 if (res.instructionType == null) { |
| 529 res.instructionType = builder.getTypeOfThis(); | 530 res.instructionType = builder.getTypeOfThis(); |
| 530 } | 531 } |
| 531 return res; | 532 return res; |
| 532 } | 533 } |
| 533 | 534 |
| 534 HLocalValue getLocal(Local local) { | 535 HLocalValue getLocal(Local local, |
| 536 {SourceInformation sourceInformation}) { |
| 535 // If the element is a parameter, we already have a | 537 // If the element is a parameter, we already have a |
| 536 // HParameterValue for it. We cannot create another one because | 538 // HParameterValue for it. We cannot create another one because |
| 537 // it could then have another name than the real parameter. And | 539 // it could then have another name than the real parameter. And |
| 538 // the other one would not know it is just a copy of the real | 540 // the other one would not know it is just a copy of the real |
| 539 // parameter. | 541 // parameter. |
| 540 if (local is ParameterElement) return builder.parameters[local]; | 542 if (local is ParameterElement) return builder.parameters[local]; |
| 541 | 543 |
| 542 return builder.activationVariables.putIfAbsent(local, () { | 544 return builder.activationVariables.putIfAbsent(local, () { |
| 543 JavaScriptBackend backend = builder.backend; | 545 JavaScriptBackend backend = builder.backend; |
| 544 HLocalValue localValue = new HLocalValue(local, backend.nonNullType); | 546 HLocalValue localValue = new HLocalValue(local, backend.nonNullType) |
| 547 ..sourceInformation = sourceInformation; |
| 545 builder.graph.entry.addAtExit(localValue); | 548 builder.graph.entry.addAtExit(localValue); |
| 546 return localValue; | 549 return localValue; |
| 547 }); | 550 }); |
| 548 } | 551 } |
| 549 | 552 |
| 550 Local getTypeVariableAsLocal(TypeVariableType type) { | 553 Local getTypeVariableAsLocal(TypeVariableType type) { |
| 551 return typeVariableLocals.putIfAbsent(type, () { | 554 return typeVariableLocals.putIfAbsent(type, () { |
| 552 return new TypeVariableLocal(type, executableContext); | 555 return new TypeVariableLocal(type, executableContext); |
| 553 }); | 556 }); |
| 554 } | 557 } |
| 555 | 558 |
| 556 /** | 559 /** |
| 557 * Sets the [element] to [value]. If the element is boxed or stored in a | 560 * Sets the [element] to [value]. If the element is boxed or stored in a |
| 558 * closure then the method generates code to set the value. | 561 * closure then the method generates code to set the value. |
| 559 */ | 562 */ |
| 560 void updateLocal(Local local, HInstruction value) { | 563 void updateLocal(Local local, HInstruction value, |
| 564 {SourceInformation sourceInformation}) { |
| 561 assert(!isStoredInClosureField(local)); | 565 assert(!isStoredInClosureField(local)); |
| 562 if (isAccessedDirectly(local)) { | 566 if (isAccessedDirectly(local)) { |
| 563 directLocals[local] = value; | 567 directLocals[local] = value; |
| 564 } else if (isBoxed(local)) { | 568 } else if (isBoxed(local)) { |
| 565 BoxFieldElement redirect = redirectionMapping[local]; | 569 BoxFieldElement redirect = redirectionMapping[local]; |
| 566 // The box itself could be captured, or be local. A local variable that | 570 // The box itself could be captured, or be local. A local variable that |
| 567 // is captured will be boxed, but the box itself will be a local. | 571 // is captured will be boxed, but the box itself will be a local. |
| 568 // Inside the closure the box is stored in a closure-field and cannot | 572 // Inside the closure the box is stored in a closure-field and cannot |
| 569 // be accessed directly. | 573 // be accessed directly. |
| 570 HInstruction box = readLocal(redirect.box); | 574 HInstruction box = readLocal(redirect.box); |
| 571 builder.add(new HFieldSet(redirect, box, value)); | 575 builder.add(new HFieldSet(redirect, box, value) |
| 576 ..sourceInformation = sourceInformation); |
| 572 } else { | 577 } else { |
| 573 assert(isUsedInTryOrGenerator(local)); | 578 assert(isUsedInTryOrGenerator(local)); |
| 574 HLocalValue localValue = getLocal(local); | 579 HLocalValue localValue = getLocal(local); |
| 575 builder.add(new HLocalSet(local, localValue, value)); | 580 builder.add(new HLocalSet(local, localValue, value) |
| 581 ..sourceInformation = sourceInformation); |
| 576 } | 582 } |
| 577 } | 583 } |
| 578 | 584 |
| 579 /** | 585 /** |
| 580 * This function, startLoop, must be called before visiting any children of | 586 * This function, startLoop, must be called before visiting any children of |
| 581 * the loop. In particular it needs to be called before executing the | 587 * the loop. In particular it needs to be called before executing the |
| 582 * initializers. | 588 * initializers. |
| 583 * | 589 * |
| 584 * The [LocalsHandler] will make the boxes and updates at the right moment. | 590 * The [LocalsHandler] will make the boxes and updates at the right moment. |
| 585 * The builder just needs to call [enterLoopBody] and [enterLoopUpdates] | 591 * The builder just needs to call [enterLoopBody] and [enterLoopUpdates] |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 /// Returns `true` if the current element is an `async` function. | 1118 /// Returns `true` if the current element is an `async` function. |
| 1113 bool get isBuildingAsyncFunction { | 1119 bool get isBuildingAsyncFunction { |
| 1114 Element element = sourceElement; | 1120 Element element = sourceElement; |
| 1115 return (element is FunctionElement && | 1121 return (element is FunctionElement && |
| 1116 element.asyncMarker == AsyncMarker.ASYNC); | 1122 element.asyncMarker == AsyncMarker.ASYNC); |
| 1117 } | 1123 } |
| 1118 | 1124 |
| 1119 SsaBuilder(JavaScriptBackend backend, | 1125 SsaBuilder(JavaScriptBackend backend, |
| 1120 CodegenWorkItem work, | 1126 CodegenWorkItem work, |
| 1121 this.nativeEmitter, | 1127 this.nativeEmitter, |
| 1122 SourceInformationFactory sourceInformationFactory) | 1128 SourceInformationStrategy sourceInformationFactory) |
| 1123 : this.compiler = backend.compiler, | 1129 : this.compiler = backend.compiler, |
| 1124 this.backend = backend, | 1130 this.backend = backend, |
| 1125 this.constantSystem = backend.constantSystem, | 1131 this.constantSystem = backend.constantSystem, |
| 1126 this.work = work, | 1132 this.work = work, |
| 1127 this.rti = backend.rti, | 1133 this.rti = backend.rti, |
| 1128 this.elements = work.resolutionTree { | 1134 this.elements = work.resolutionTree { |
| 1129 localsHandler = new LocalsHandler(this, work.element, null); | 1135 localsHandler = new LocalsHandler(this, work.element, null); |
| 1130 sourceElementStack.add(work.element); | 1136 sourceElementStack.add(work.element); |
| 1131 sourceInformationBuilder = | 1137 sourceInformationBuilder = |
| 1132 sourceInformationFactory.forContext(work.element.implementation); | 1138 sourceInformationFactory.createBuilderForContext( |
| 1139 work.element.implementation); |
| 1133 } | 1140 } |
| 1134 | 1141 |
| 1135 @override | 1142 @override |
| 1136 SemanticSendVisitor get sendVisitor => this; | 1143 SemanticSendVisitor get sendVisitor => this; |
| 1137 | 1144 |
| 1138 @override | 1145 @override |
| 1139 void visitNode(ast.Node node) { | 1146 void visitNode(ast.Node node) { |
| 1140 internalError(node, "Unhandled node: $node"); | 1147 internalError(node, "Unhandled node: $node"); |
| 1141 } | 1148 } |
| 1142 | 1149 |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1628 assert(elements.getFunctionDefinition(function) != null); | 1635 assert(elements.getFunctionDefinition(function) != null); |
| 1629 openFunction(functionElement, function); | 1636 openFunction(functionElement, function); |
| 1630 String name = functionElement.name; | 1637 String name = functionElement.name; |
| 1631 // If [functionElement] is `operator==` we explicitely add a null check at | 1638 // If [functionElement] is `operator==` we explicitely add a null check at |
| 1632 // the beginning of the method. This is to avoid having call sites do the | 1639 // the beginning of the method. This is to avoid having call sites do the |
| 1633 // null check. | 1640 // null check. |
| 1634 if (name == '==') { | 1641 if (name == '==') { |
| 1635 if (!backend.operatorEqHandlesNullArgument(functionElement)) { | 1642 if (!backend.operatorEqHandlesNullArgument(functionElement)) { |
| 1636 handleIf( | 1643 handleIf( |
| 1637 function, | 1644 function, |
| 1638 () { | 1645 visitCondition: () { |
| 1639 HParameterValue parameter = parameters.values.first; | 1646 HParameterValue parameter = parameters.values.first; |
| 1640 push(new HIdentity( | 1647 push(new HIdentity( |
| 1641 parameter, graph.addConstantNull(compiler), null, | 1648 parameter, graph.addConstantNull(compiler), null, |
| 1642 backend.boolType)); | 1649 backend.boolType)); |
| 1643 }, | 1650 }, |
| 1644 () { | 1651 visitThen: () { |
| 1652 // TODO(johnniwinther): Add source information. |
| 1645 closeAndGotoExit(new HReturn( | 1653 closeAndGotoExit(new HReturn( |
| 1646 graph.addConstantBool(false, compiler))); | 1654 graph.addConstantBool(false, compiler), |
| 1655 null)); |
| 1647 }, | 1656 }, |
| 1648 null); | 1657 visitElse: null); |
| 1649 } | 1658 } |
| 1650 } | 1659 } |
| 1651 function.body.accept(this); | 1660 function.body.accept(this); |
| 1652 return closeFunction(); | 1661 return closeFunction(); |
| 1653 } | 1662 } |
| 1654 | 1663 |
| 1655 HGraph buildCheckedSetter(VariableElement field) { | 1664 HGraph buildCheckedSetter(VariableElement field) { |
| 1656 openFunction(field, field.node); | 1665 openFunction(field, field.node); |
| 1657 HInstruction thisInstruction = localsHandler.readThis(); | 1666 HInstruction thisInstruction = localsHandler.readThis(); |
| 1658 // Use dynamic type because the type computed by the inferrer is | 1667 // Use dynamic type because the type computed by the inferrer is |
| 1659 // narrowed to the type annotation. | 1668 // narrowed to the type annotation. |
| 1660 HInstruction parameter = new HParameterValue(field, backend.dynamicType); | 1669 HInstruction parameter = new HParameterValue(field, backend.dynamicType); |
| 1661 // Add the parameter as the last instruction of the entry block. | 1670 // Add the parameter as the last instruction of the entry block. |
| 1662 // If the method is intercepted, we want the actual receiver | 1671 // If the method is intercepted, we want the actual receiver |
| 1663 // to be the first parameter. | 1672 // to be the first parameter. |
| 1664 graph.entry.addBefore(graph.entry.last, parameter); | 1673 graph.entry.addBefore(graph.entry.last, parameter); |
| 1665 HInstruction value = potentiallyCheckOrTrustType(parameter, field.type); | 1674 HInstruction value = potentiallyCheckOrTrustType(parameter, field.type); |
| 1666 add(new HFieldSet(field, thisInstruction, value)); | 1675 add(new HFieldSet(field, thisInstruction, value)); |
| 1667 return closeFunction(); | 1676 return closeFunction(); |
| 1668 } | 1677 } |
| 1669 | 1678 |
| 1670 HGraph buildLazyInitializer(VariableElement variable) { | 1679 HGraph buildLazyInitializer(VariableElement variable) { |
| 1671 inLazyInitializerExpression = true; | 1680 inLazyInitializerExpression = true; |
| 1672 ast.Node node = variable.node; | 1681 ast.VariableDefinitions node = variable.node; |
| 1673 openFunction(variable, node); | 1682 openFunction(variable, node); |
| 1674 assert(invariant(variable, variable.initializer != null, | 1683 assert(invariant(variable, variable.initializer != null, |
| 1675 message: "Non-constant variable $variable has no initializer.")); | 1684 message: "Non-constant variable $variable has no initializer.")); |
| 1676 visit(variable.initializer); | 1685 visit(variable.initializer); |
| 1677 HInstruction value = pop(); | 1686 HInstruction value = pop(); |
| 1678 value = potentiallyCheckOrTrustType(value, variable.type); | 1687 value = potentiallyCheckOrTrustType(value, variable.type); |
| 1679 closeAndGotoExit(new HReturn(value)); | 1688 ast.SendSet sendSet = node.definitions.nodes.head; |
| 1689 closeAndGotoExit(new HReturn(value, |
| 1690 sourceInformationBuilder.buildReturn(sendSet.assignmentOperator))); |
| 1680 return closeFunction(); | 1691 return closeFunction(); |
| 1681 } | 1692 } |
| 1682 | 1693 |
| 1683 /** | 1694 /** |
| 1684 * Returns the constructor body associated with the given constructor or | 1695 * Returns the constructor body associated with the given constructor or |
| 1685 * creates a new constructor body, if none can be found. | 1696 * creates a new constructor body, if none can be found. |
| 1686 * | 1697 * |
| 1687 * Returns [:null:] if the constructor does not have a body. | 1698 * Returns [:null:] if the constructor does not have a body. |
| 1688 */ | 1699 */ |
| 1689 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { | 1700 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2172 if (!currentInlinedInstantiations.isEmpty) { | 2183 if (!currentInlinedInstantiations.isEmpty) { |
| 2173 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations); | 2184 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations); |
| 2174 } | 2185 } |
| 2175 | 2186 |
| 2176 HInstruction newObject; | 2187 HInstruction newObject; |
| 2177 if (!isNativeUpgradeFactory) { | 2188 if (!isNativeUpgradeFactory) { |
| 2178 newObject = new HForeignNew(classElement, | 2189 newObject = new HForeignNew(classElement, |
| 2179 ssaType, | 2190 ssaType, |
| 2180 constructorArguments, | 2191 constructorArguments, |
| 2181 instantiatedTypes); | 2192 instantiatedTypes); |
| 2193 if (function != null) { |
| 2194 newObject.sourceInformation = |
| 2195 sourceInformationBuilder.buildGeneric(function); |
| 2196 } |
| 2182 add(newObject); | 2197 add(newObject); |
| 2183 } else { | 2198 } else { |
| 2184 // Bulk assign to the initialized fields. | 2199 // Bulk assign to the initialized fields. |
| 2185 newObject = graph.explicitReceiverParameter; | 2200 newObject = graph.explicitReceiverParameter; |
| 2186 // Null guard ensures an error if we are being called from an explicit | 2201 // Null guard ensures an error if we are being called from an explicit |
| 2187 // 'new' of the constructor instead of via an upgrade. It is optimized out | 2202 // 'new' of the constructor instead of via an upgrade. It is optimized out |
| 2188 // if there are field initializers. | 2203 // if there are field initializers. |
| 2189 add(new HFieldGet( | 2204 add(new HFieldGet( |
| 2190 null, newObject, backend.dynamicType, isAssignable: false)); | 2205 null, newObject, backend.dynamicType, isAssignable: false)); |
| 2191 for (int i = 0; i < fields.length; i++) { | 2206 for (int i = 0; i < fields.length; i++) { |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2325 pop(); | 2340 pop(); |
| 2326 } else { | 2341 } else { |
| 2327 HInvokeConstructorBody invoke = new HInvokeConstructorBody( | 2342 HInvokeConstructorBody invoke = new HInvokeConstructorBody( |
| 2328 body.declaration, bodyCallInputs, backend.nonNullType); | 2343 body.declaration, bodyCallInputs, backend.nonNullType); |
| 2329 invoke.sideEffects = | 2344 invoke.sideEffects = |
| 2330 compiler.world.getSideEffectsOfElement(constructor); | 2345 compiler.world.getSideEffectsOfElement(constructor); |
| 2331 add(invoke); | 2346 add(invoke); |
| 2332 } | 2347 } |
| 2333 } | 2348 } |
| 2334 if (inliningStack.isEmpty) { | 2349 if (inliningStack.isEmpty) { |
| 2335 closeAndGotoExit(new HReturn(newObject)); | 2350 closeAndGotoExit(new HReturn(newObject, |
| 2351 sourceInformationBuilder.buildImplicitReturn(functionElement))); |
| 2336 return closeFunction(); | 2352 return closeFunction(); |
| 2337 } else { | 2353 } else { |
| 2338 localsHandler.updateLocal(returnLocal, newObject); | 2354 localsHandler.updateLocal(returnLocal, newObject); |
| 2339 return null; | 2355 return null; |
| 2340 } | 2356 } |
| 2341 } | 2357 } |
| 2342 | 2358 |
| 2343 /** | 2359 /** |
| 2344 * Documentation wanted -- johnniwinther | 2360 * Documentation wanted -- johnniwinther |
| 2345 * | 2361 * |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2627 inExpressionOfThrow = old; | 2643 inExpressionOfThrow = old; |
| 2628 } | 2644 } |
| 2629 } | 2645 } |
| 2630 | 2646 |
| 2631 visitExpressionStatement(ast.ExpressionStatement node) { | 2647 visitExpressionStatement(ast.ExpressionStatement node) { |
| 2632 if (!isReachable) return; | 2648 if (!isReachable) return; |
| 2633 ast.Throw throwExpression = node.expression.asThrow(); | 2649 ast.Throw throwExpression = node.expression.asThrow(); |
| 2634 if (throwExpression != null && inliningStack.isEmpty) { | 2650 if (throwExpression != null && inliningStack.isEmpty) { |
| 2635 visitThrowExpression(throwExpression.expression); | 2651 visitThrowExpression(throwExpression.expression); |
| 2636 handleInTryStatement(); | 2652 handleInTryStatement(); |
| 2637 closeAndGotoExit(new HThrow(pop())); | 2653 closeAndGotoExit( |
| 2654 new HThrow(pop(), sourceInformationBuilder.buildThrow(node))); |
| 2638 } else { | 2655 } else { |
| 2639 visit(node.expression); | 2656 visit(node.expression); |
| 2640 pop(); | 2657 pop(); |
| 2641 } | 2658 } |
| 2642 } | 2659 } |
| 2643 | 2660 |
| 2644 /** | 2661 /** |
| 2645 * Creates a new loop-header block. The previous [current] block | 2662 * Creates a new loop-header block. The previous [current] block |
| 2646 * is closed with an [HGoto] and replaced by the newly created block. | 2663 * is closed with an [HGoto] and replaced by the newly created block. |
| 2647 * Also notifies the locals handler that we're entering a loop. | 2664 * Also notifies the locals handler that we're entering a loop. |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3122 List<HInstruction> capturedVariables = <HInstruction>[]; | 3139 List<HInstruction> capturedVariables = <HInstruction>[]; |
| 3123 closureClassElement.closureFields.forEach((ClosureFieldElement field) { | 3140 closureClassElement.closureFields.forEach((ClosureFieldElement field) { |
| 3124 Local capturedLocal = | 3141 Local capturedLocal = |
| 3125 nestedClosureData.getLocalVariableForClosureField(field); | 3142 nestedClosureData.getLocalVariableForClosureField(field); |
| 3126 assert(capturedLocal != null); | 3143 assert(capturedLocal != null); |
| 3127 capturedVariables.add(localsHandler.readLocal(capturedLocal)); | 3144 capturedVariables.add(localsHandler.readLocal(capturedLocal)); |
| 3128 }); | 3145 }); |
| 3129 | 3146 |
| 3130 TypeMask type = | 3147 TypeMask type = |
| 3131 new TypeMask.nonNullExact(compiler.functionClass, compiler.world); | 3148 new TypeMask.nonNullExact(compiler.functionClass, compiler.world); |
| 3132 push(new HForeignNew(closureClassElement, type, capturedVariables)); | 3149 push(new HForeignNew(closureClassElement, type, capturedVariables) |
| 3150 ..sourceInformation = sourceInformationBuilder.buildGeneric(node)); |
| 3133 | 3151 |
| 3134 Element methodElement = nestedClosureData.closureElement; | 3152 Element methodElement = nestedClosureData.closureElement; |
| 3135 registry.registerInstantiatedClosure(methodElement); | 3153 registry.registerInstantiatedClosure(methodElement); |
| 3136 } | 3154 } |
| 3137 | 3155 |
| 3138 visitFunctionDeclaration(ast.FunctionDeclaration node) { | 3156 visitFunctionDeclaration(ast.FunctionDeclaration node) { |
| 3139 assert(isReachable); | 3157 assert(isReachable); |
| 3140 visit(node.function); | 3158 visit(node.function); |
| 3141 LocalFunctionElement localFunction = | 3159 LocalFunctionElement localFunction = |
| 3142 elements.getFunctionDefinition(node.function); | 3160 elements.getFunctionDefinition(node.function); |
| 3143 localsHandler.updateLocal(localFunction, pop()); | 3161 localsHandler.updateLocal(localFunction, pop()); |
| 3144 } | 3162 } |
| 3145 | 3163 |
| 3146 @override | 3164 @override |
| 3147 void visitThisGet(ast.Identifier node, [_]) { | 3165 void visitThisGet(ast.Identifier node, [_]) { |
| 3148 stack.add(localsHandler.readThis()); | 3166 stack.add(localsHandler.readThis()); |
| 3149 } | 3167 } |
| 3150 | 3168 |
| 3151 visitIdentifier(ast.Identifier node) { | 3169 visitIdentifier(ast.Identifier node) { |
| 3152 if (node.isThis()) { | 3170 if (node.isThis()) { |
| 3153 visitThisGet(node); | 3171 visitThisGet(node); |
| 3154 } else { | 3172 } else { |
| 3155 compiler.internalError(node, | 3173 compiler.internalError(node, |
| 3156 "SsaFromAstMixin.visitIdentifier on non-this."); | 3174 "SsaFromAstMixin.visitIdentifier on non-this."); |
| 3157 } | 3175 } |
| 3158 } | 3176 } |
| 3159 | 3177 |
| 3160 visitIf(ast.If node) { | 3178 visitIf(ast.If node) { |
| 3161 assert(isReachable); | 3179 assert(isReachable); |
| 3162 handleIf(node, | 3180 handleIf( |
| 3163 () => visit(node.condition), | 3181 node, |
| 3164 () => visit(node.thenPart), | 3182 visitCondition: () => visit(node.condition), |
| 3165 node.elsePart != null ? () => visit(node.elsePart) : null); | 3183 visitThen: () => visit(node.thenPart), |
| 3184 visitElse: node.elsePart != null ? () => visit(node.elsePart) : null, |
| 3185 sourceInformation: sourceInformationBuilder.buildIf(node)); |
| 3166 } | 3186 } |
| 3167 | 3187 |
| 3168 void handleIf(ast.Node diagnosticNode, | 3188 void handleIf(ast.Node diagnosticNode, |
| 3169 void visitCondition(), void visitThen(), void visitElse()) { | 3189 {void visitCondition(), |
| 3190 void visitThen(), |
| 3191 void visitElse(), |
| 3192 SourceInformation sourceInformation}) { |
| 3170 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode); | 3193 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode); |
| 3171 branchBuilder.handleIf(visitCondition, visitThen, visitElse); | 3194 branchBuilder.handleIf( |
| 3195 visitCondition, visitThen, visitElse, |
| 3196 sourceInformation: sourceInformation); |
| 3172 } | 3197 } |
| 3173 | 3198 |
| 3174 @override | 3199 @override |
| 3175 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) { | 3200 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) { |
| 3176 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 3201 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 3177 brancher.handleIfNull(() => visit(left), () => visit(right)); | 3202 brancher.handleIfNull(() => visit(left), () => visit(right)); |
| 3178 } | 3203 } |
| 3179 | 3204 |
| 3180 @override | 3205 @override |
| 3181 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) { | 3206 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3192 branchBuilder.handleLogicalAndOrWithLeftNode( | 3217 branchBuilder.handleLogicalAndOrWithLeftNode( |
| 3193 left, | 3218 left, |
| 3194 () { visit(right); }, | 3219 () { visit(right); }, |
| 3195 isAnd: false); | 3220 isAnd: false); |
| 3196 } | 3221 } |
| 3197 | 3222 |
| 3198 @override | 3223 @override |
| 3199 void visitNot(ast.Send node, ast.Node expression, _) { | 3224 void visitNot(ast.Send node, ast.Node expression, _) { |
| 3200 assert(node.argumentsNode is ast.Prefix); | 3225 assert(node.argumentsNode is ast.Prefix); |
| 3201 visit(expression); | 3226 visit(expression); |
| 3202 HNot not = new HNot(popBoolified(), backend.boolType); | 3227 SourceInformation sourceInformation = |
| 3203 pushWithPosition(not, node); | 3228 sourceInformationBuilder.buildGeneric(node); |
| 3229 push(new HNot(popBoolified(), backend.boolType) |
| 3230 ..sourceInformation = sourceInformation); |
| 3204 } | 3231 } |
| 3205 | 3232 |
| 3206 @override | 3233 @override |
| 3207 void visitUnary(ast.Send node, | 3234 void visitUnary(ast.Send node, |
| 3208 UnaryOperator operator, | 3235 UnaryOperator operator, |
| 3209 ast.Node expression,_) { | 3236 ast.Node expression,_) { |
| 3210 assert(node.argumentsNode is ast.Prefix); | 3237 assert(node.argumentsNode is ast.Prefix); |
| 3211 HInstruction operand = visitAndPop(expression); | 3238 HInstruction operand = visitAndPop(expression); |
| 3212 | 3239 |
| 3213 // See if we can constant-fold right away. This avoids rewrites later on. | 3240 // See if we can constant-fold right away. This avoids rewrites later on. |
| 3214 if (operand is HConstant) { | 3241 if (operand is HConstant) { |
| 3215 UnaryOperation operation = constantSystem.lookupUnary(operator); | 3242 UnaryOperation operation = constantSystem.lookupUnary(operator); |
| 3216 HConstant constant = operand; | 3243 HConstant constant = operand; |
| 3217 ConstantValue folded = operation.fold(constant.constant); | 3244 ConstantValue folded = operation.fold(constant.constant); |
| 3218 if (folded != null) { | 3245 if (folded != null) { |
| 3219 stack.add(graph.addConstant(folded, compiler)); | 3246 stack.add(graph.addConstant(folded, compiler)); |
| 3220 return; | 3247 return; |
| 3221 } | 3248 } |
| 3222 } | 3249 } |
| 3223 | 3250 |
| 3224 pushInvokeDynamic( | 3251 pushInvokeDynamic( |
| 3225 node, | 3252 node, |
| 3226 elements.getSelector(node), | 3253 elements.getSelector(node), |
| 3227 elements.getTypeMask(node), | 3254 elements.getTypeMask(node), |
| 3228 [operand]); | 3255 [operand], |
| 3256 sourceInformation: sourceInformationBuilder.buildGeneric(node)); |
| 3229 } | 3257 } |
| 3230 | 3258 |
| 3231 @override | 3259 @override |
| 3232 void visitBinary(ast.Send node, | 3260 void visitBinary(ast.Send node, |
| 3233 ast.Node left, | 3261 ast.Node left, |
| 3234 BinaryOperator operator, | 3262 BinaryOperator operator, |
| 3235 ast.Node right, _) { | 3263 ast.Node right, _) { |
| 3236 handleBinary(node, left, right); | 3264 handleBinary(node, left, right); |
| 3237 } | 3265 } |
| 3238 | 3266 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3252 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); | 3280 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); |
| 3253 } | 3281 } |
| 3254 | 3282 |
| 3255 void handleBinary(ast.Send node, ast.Node left, ast.Node right) { | 3283 void handleBinary(ast.Send node, ast.Node left, ast.Node right) { |
| 3256 visitBinarySend( | 3284 visitBinarySend( |
| 3257 visitAndPop(left), | 3285 visitAndPop(left), |
| 3258 visitAndPop(right), | 3286 visitAndPop(right), |
| 3259 elements.getSelector(node), | 3287 elements.getSelector(node), |
| 3260 elements.getTypeMask(node), | 3288 elements.getTypeMask(node), |
| 3261 node, | 3289 node, |
| 3262 location: node.selector); | 3290 sourceInformation: |
| 3291 sourceInformationBuilder.buildGeneric(node.selector)); |
| 3263 } | 3292 } |
| 3264 | 3293 |
| 3265 /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and | 3294 /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and |
| 3266 /// remove use of [location] for source information. | 3295 /// remove use of [location] for source information. |
| 3267 void visitBinarySend(HInstruction left, | 3296 void visitBinarySend(HInstruction left, |
| 3268 HInstruction right, | 3297 HInstruction right, |
| 3269 Selector selector, | 3298 Selector selector, |
| 3270 TypeMask mask, | 3299 TypeMask mask, |
| 3271 ast.Send send, | 3300 ast.Send send, |
| 3272 {ast.Node location}) { | 3301 {SourceInformation sourceInformation}) { |
| 3273 pushInvokeDynamic(send, selector, mask, [left, right], location: location); | 3302 pushInvokeDynamic(send, selector, mask, [left, right], |
| 3303 sourceInformation: sourceInformation); |
| 3274 } | 3304 } |
| 3275 | 3305 |
| 3276 HInstruction generateInstanceSendReceiver(ast.Send send) { | 3306 HInstruction generateInstanceSendReceiver(ast.Send send) { |
| 3277 assert(Elements.isInstanceSend(send, elements)); | 3307 assert(Elements.isInstanceSend(send, elements)); |
| 3278 if (send.receiver == null) { | 3308 if (send.receiver == null) { |
| 3279 return localsHandler.readThis(); | 3309 return localsHandler.readThis(); |
| 3280 } | 3310 } |
| 3281 visit(send.receiver); | 3311 visit(send.receiver); |
| 3282 return pop(); | 3312 return pop(); |
| 3283 } | 3313 } |
| 3284 | 3314 |
| 3285 String noSuchMethodTargetSymbolString(Element error, [String prefix]) { | 3315 String noSuchMethodTargetSymbolString(Element error, [String prefix]) { |
| 3286 String result = error.name; | 3316 String result = error.name; |
| 3287 if (prefix == "set") return "$result="; | 3317 if (prefix == "set") return "$result="; |
| 3288 return result; | 3318 return result; |
| 3289 } | 3319 } |
| 3290 | 3320 |
| 3291 /** | 3321 /** |
| 3292 * Returns a set of interceptor classes that contain the given | 3322 * Returns a set of interceptor classes that contain the given |
| 3293 * [selector]. | 3323 * [selector]. |
| 3294 */ | 3324 */ |
| 3295 void generateInstanceGetterWithCompiledReceiver( | 3325 void generateInstanceGetterWithCompiledReceiver( |
| 3296 ast.Send send, | 3326 ast.Send send, |
| 3297 Selector selector, | 3327 Selector selector, |
| 3298 TypeMask mask, | 3328 TypeMask mask, |
| 3299 HInstruction receiver) { | 3329 HInstruction receiver) { |
| 3300 assert(Elements.isInstanceSend(send, elements)); | 3330 assert(Elements.isInstanceSend(send, elements)); |
| 3301 assert(selector.isGetter); | 3331 assert(selector.isGetter); |
| 3302 pushInvokeDynamic(send, selector, mask, [receiver]); | 3332 pushInvokeDynamic(send, selector, mask, [receiver], |
| 3333 sourceInformation: sourceInformationBuilder.buildGet(send)); |
| 3303 } | 3334 } |
| 3304 | 3335 |
| 3305 /// Inserts a call to checkDeferredIsLoaded for [prefixElement]. | 3336 /// Inserts a call to checkDeferredIsLoaded for [prefixElement]. |
| 3306 /// If [prefixElement] is [null] ndo nothing. | 3337 /// If [prefixElement] is [null] ndo nothing. |
| 3307 void generateIsDeferredLoadedCheckIfNeeded(PrefixElement prefixElement, | 3338 void generateIsDeferredLoadedCheckIfNeeded(PrefixElement prefixElement, |
| 3308 ast.Node location) { | 3339 ast.Node location) { |
| 3309 if (prefixElement == null) return; | 3340 if (prefixElement == null) return; |
| 3310 String loadId = | 3341 String loadId = |
| 3311 compiler.deferredLoadTask.importDeferName[prefixElement.deferredImport]; | 3342 compiler.deferredLoadTask.importDeferName[prefixElement.deferredImport]; |
| 3312 HInstruction loadIdConstant = addConstantString(loadId); | 3343 HInstruction loadIdConstant = addConstantString(loadId); |
| 3313 String uri = prefixElement.deferredImport.uri.dartString.slowToString(); | 3344 String uri = prefixElement.deferredImport.uri.dartString.slowToString(); |
| 3314 HInstruction uriConstant = addConstantString(uri); | 3345 HInstruction uriConstant = addConstantString(uri); |
| 3315 Element helper = backend.getCheckDeferredIsLoaded(); | 3346 Element helper = backend.getCheckDeferredIsLoaded(); |
| 3316 pushInvokeStatic(location, helper, [loadIdConstant, uriConstant]); | 3347 pushInvokeStatic(location, helper, [loadIdConstant, uriConstant]); |
| 3317 pop(); | 3348 pop(); |
| 3318 } | 3349 } |
| 3319 | 3350 |
| 3320 /// Inserts a call to checkDeferredIsLoaded if the send has a prefix that | 3351 /// Inserts a call to checkDeferredIsLoaded if the send has a prefix that |
| 3321 /// resolves to a deferred library. | 3352 /// resolves to a deferred library. |
| 3322 void generateIsDeferredLoadedCheckOfSend(ast.Send node) { | 3353 void generateIsDeferredLoadedCheckOfSend(ast.Send node) { |
| 3323 generateIsDeferredLoadedCheckIfNeeded( | 3354 generateIsDeferredLoadedCheckIfNeeded( |
| 3324 compiler.deferredLoadTask.deferredPrefixElement(node, elements), | 3355 compiler.deferredLoadTask.deferredPrefixElement(node, elements), |
| 3325 node); | 3356 node); |
| 3326 } | 3357 } |
| 3327 | 3358 |
| 3328 void handleInvalidStaticGet(ast.Send node, Element element) { | 3359 void handleInvalidStaticGet(ast.Send node, Element element) { |
| 3360 SourceInformation sourceInformation = |
| 3361 sourceInformationBuilder.buildGet(node); |
| 3329 generateThrowNoSuchMethod( | 3362 generateThrowNoSuchMethod( |
| 3330 node, | 3363 node, |
| 3331 noSuchMethodTargetSymbolString(element, 'get'), | 3364 noSuchMethodTargetSymbolString(element, 'get'), |
| 3332 argumentNodes: const Link<ast.Node>()); | 3365 argumentNodes: const Link<ast.Node>(), |
| 3366 sourceInformation: sourceInformation); |
| 3333 } | 3367 } |
| 3334 | 3368 |
| 3335 /// Generate read access of an unresolved static or top level entity. | 3369 /// Generate read access of an unresolved static or top level entity. |
| 3336 void generateStaticUnresolvedGet(ast.Send node, Element element) { | 3370 void generateStaticUnresolvedGet(ast.Send node, Element element) { |
| 3337 if (element is ErroneousElement) { | 3371 if (element is ErroneousElement) { |
| 3372 SourceInformation sourceInformation = |
| 3373 sourceInformationBuilder.buildGet(node); |
| 3338 // An erroneous element indicates an unresolved static getter. | 3374 // An erroneous element indicates an unresolved static getter. |
| 3339 handleInvalidStaticGet(node, element); | 3375 handleInvalidStaticGet(node, element); |
| 3340 } else { | 3376 } else { |
| 3341 // This happens when [element] has parse errors. | 3377 // This happens when [element] has parse errors. |
| 3342 assert(invariant(node, element == null || element.isErroneous)); | 3378 assert(invariant(node, element == null || element.isErroneous)); |
| 3343 // TODO(ahe): Do something like the above, that is, emit a runtime | 3379 // TODO(ahe): Do something like the above, that is, emit a runtime |
| 3344 // error. | 3380 // error. |
| 3345 stack.add(graph.addConstantNull(compiler)); | 3381 stack.add(graph.addConstantNull(compiler)); |
| 3346 } | 3382 } |
| 3347 } | 3383 } |
| 3348 | 3384 |
| 3349 /// Read a static or top level [field] of constant value. | 3385 /// Read a static or top level [field] of constant value. |
| 3350 void generateStaticConstGet( | 3386 void generateStaticConstGet( |
| 3351 ast.Send node, | 3387 ast.Send node, |
| 3352 FieldElement field, | 3388 FieldElement field, |
| 3353 ConstantExpression constant) { | 3389 ConstantExpression constant, |
| 3390 SourceInformation sourceInformation) { |
| 3354 ConstantValue value = backend.constants.getConstantValue(constant); | 3391 ConstantValue value = backend.constants.getConstantValue(constant); |
| 3355 HConstant instruction; | 3392 HConstant instruction; |
| 3356 // Constants that are referred via a deferred prefix should be referred | 3393 // Constants that are referred via a deferred prefix should be referred |
| 3357 // by reference. | 3394 // by reference. |
| 3358 PrefixElement prefix = compiler.deferredLoadTask | 3395 PrefixElement prefix = compiler.deferredLoadTask |
| 3359 .deferredPrefixElement(node, elements); | 3396 .deferredPrefixElement(node, elements); |
| 3360 if (prefix != null) { | 3397 if (prefix != null) { |
| 3361 instruction = graph.addDeferredConstant(value, prefix, compiler); | 3398 instruction = |
| 3399 graph.addDeferredConstant(value, prefix, sourceInformation, compiler); |
| 3362 } else { | 3400 } else { |
| 3363 instruction = graph.addConstant(value, compiler); | 3401 instruction = graph.addConstant( |
| 3402 value, compiler, sourceInformation: sourceInformation); |
| 3364 } | 3403 } |
| 3365 stack.add(instruction); | 3404 stack.add(instruction); |
| 3366 // The inferrer may have found a better type than the constant | 3405 // The inferrer may have found a better type than the constant |
| 3367 // handler in the case of lists, because the constant handler | 3406 // handler in the case of lists, because the constant handler |
| 3368 // does not look at elements in the list. | 3407 // does not look at elements in the list. |
| 3369 TypeMask type = | 3408 TypeMask type = |
| 3370 TypeMaskFactory.inferredTypeForElement(field, compiler); | 3409 TypeMaskFactory.inferredTypeForElement(field, compiler); |
| 3371 if (!type.containsAll(compiler.world) && | 3410 if (!type.containsAll(compiler.world) && |
| 3372 !instruction.isConstantNull()) { | 3411 !instruction.isConstantNull()) { |
| 3373 // TODO(13429): The inferrer should know that an element | 3412 // TODO(13429): The inferrer should know that an element |
| 3374 // cannot be null. | 3413 // cannot be null. |
| 3375 instruction.instructionType = type.nonNullable(); | 3414 instruction.instructionType = type.nonNullable(); |
| 3376 } | 3415 } |
| 3377 } | 3416 } |
| 3378 | 3417 |
| 3379 /// Read a static or top level [field]. | 3418 /// Read a static or top level [field]. |
| 3380 void generateStaticFieldGet(ast.Send node, FieldElement field) { | 3419 void generateStaticFieldGet(ast.Send node, FieldElement field) { |
| 3381 generateIsDeferredLoadedCheckOfSend(node); | 3420 generateIsDeferredLoadedCheckOfSend(node); |
| 3382 | 3421 |
| 3383 ConstantExpression constant = | 3422 ConstantExpression constant = |
| 3384 backend.constants.getConstantForVariable(field); | 3423 backend.constants.getConstantForVariable(field); |
| 3424 SourceInformation sourceInformation = |
| 3425 sourceInformationBuilder.buildGet(node); |
| 3385 if (constant != null) { | 3426 if (constant != null) { |
| 3386 if (!field.isAssignable) { | 3427 if (!field.isAssignable) { |
| 3387 // A static final or const. Get its constant value and inline it if | 3428 // A static final or const. Get its constant value and inline it if |
| 3388 // the value can be compiled eagerly. | 3429 // the value can be compiled eagerly. |
| 3389 generateStaticConstGet(node, field, constant); | 3430 generateStaticConstGet(node, field, constant, sourceInformation); |
| 3390 } else { | 3431 } else { |
| 3391 // TODO(5346): Try to avoid the need for calling [declaration] before | 3432 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 3392 // creating an [HStatic]. | 3433 // creating an [HStatic]. |
| 3393 HInstruction instruction = new HStatic( | 3434 HInstruction instruction = new HStatic( |
| 3394 field.declaration, | 3435 field.declaration, |
| 3395 TypeMaskFactory.inferredTypeForElement(field, compiler)); | 3436 TypeMaskFactory.inferredTypeForElement(field, compiler)) |
| 3437 ..sourceInformation = sourceInformation; |
| 3396 push(instruction); | 3438 push(instruction); |
| 3397 } | 3439 } |
| 3398 } else { | 3440 } else { |
| 3399 HInstruction instruction = new HLazyStatic( | 3441 HInstruction instruction = new HLazyStatic( |
| 3400 field, | 3442 field, |
| 3401 TypeMaskFactory.inferredTypeForElement(field, compiler)); | 3443 TypeMaskFactory.inferredTypeForElement(field, compiler)) |
| 3444 ..sourceInformation = sourceInformation; |
| 3402 push(instruction); | 3445 push(instruction); |
| 3403 } | 3446 } |
| 3404 } | 3447 } |
| 3405 | 3448 |
| 3406 /// Generate a getter invocation of the static or top level [getter]. | 3449 /// Generate a getter invocation of the static or top level [getter]. |
| 3407 void generateStaticGetterGet(ast.Send node, MethodElement getter) { | 3450 void generateStaticGetterGet(ast.Send node, MethodElement getter) { |
| 3451 SourceInformation sourceInformation = |
| 3452 sourceInformationBuilder.buildGet(node); |
| 3408 if (getter.isDeferredLoaderGetter) { | 3453 if (getter.isDeferredLoaderGetter) { |
| 3409 generateDeferredLoaderGet(node, getter); | 3454 generateDeferredLoaderGet(node, getter, sourceInformation); |
| 3410 } else { | 3455 } else { |
| 3411 generateIsDeferredLoadedCheckOfSend(node); | 3456 generateIsDeferredLoadedCheckOfSend(node); |
| 3412 pushInvokeStatic(node, getter, <HInstruction>[]); | 3457 pushInvokeStatic(node, getter, <HInstruction>[], |
| 3458 sourceInformation: sourceInformation); |
| 3413 } | 3459 } |
| 3414 } | 3460 } |
| 3415 | 3461 |
| 3416 /// Generate a dynamic getter invocation. | 3462 /// Generate a dynamic getter invocation. |
| 3417 void generateDynamicGet(ast.Send node) { | 3463 void generateDynamicGet(ast.Send node) { |
| 3418 HInstruction receiver = generateInstanceSendReceiver(node); | 3464 HInstruction receiver = generateInstanceSendReceiver(node); |
| 3419 generateInstanceGetterWithCompiledReceiver( | 3465 generateInstanceGetterWithCompiledReceiver( |
| 3420 node, elements.getSelector(node), elements.getTypeMask(node), receiver); | 3466 node, elements.getSelector(node), elements.getTypeMask(node), receiver); |
| 3421 } | 3467 } |
| 3422 | 3468 |
| 3423 /// Generate a closurization of the static or top level [function]. | 3469 /// Generate a closurization of the static or top level [function]. |
| 3424 void generateStaticFunctionGet(ast.Send node, MethodElement function) { | 3470 void generateStaticFunctionGet(ast.Send node, MethodElement function) { |
| 3425 generateIsDeferredLoadedCheckOfSend(node); | 3471 generateIsDeferredLoadedCheckOfSend(node); |
| 3426 // TODO(5346): Try to avoid the need for calling [declaration] before | 3472 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 3427 // creating an [HStatic]. | 3473 // creating an [HStatic]. |
| 3428 push(new HStatic(function.declaration, backend.nonNullType)); | 3474 SourceInformation sourceInformation = |
| 3475 sourceInformationBuilder.buildGet(node); |
| 3476 push(new HStatic(function.declaration, backend.nonNullType) |
| 3477 ..sourceInformation = sourceInformation); |
| 3429 } | 3478 } |
| 3430 | 3479 |
| 3431 /// Read a local variable, function or parameter. | 3480 /// Read a local variable, function or parameter. |
| 3432 void handleLocalGet(LocalElement local) { | 3481 void buildLocalGet(LocalElement local, SourceInformation sourceInformation) { |
| 3433 stack.add(localsHandler.readLocal(local)); | 3482 stack.add(localsHandler.readLocal( |
| 3483 local, sourceInformation: sourceInformation)); |
| 3484 } |
| 3485 |
| 3486 void handleLocalGet(ast.Send node, LocalElement local) { |
| 3487 buildLocalGet(local, sourceInformationBuilder.buildGet(node)); |
| 3434 } | 3488 } |
| 3435 | 3489 |
| 3436 @override | 3490 @override |
| 3437 void visitDynamicPropertyGet( | 3491 void visitDynamicPropertyGet( |
| 3438 ast.Send node, | 3492 ast.Send node, |
| 3439 ast.Node receiver, | 3493 ast.Node receiver, |
| 3440 Selector selector, | 3494 Selector selector, |
| 3441 _) { | 3495 _) { |
| 3442 generateDynamicGet(node); | 3496 generateDynamicGet(node); |
| 3443 } | 3497 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 3472 } | 3526 } |
| 3473 | 3527 |
| 3474 /// Pushes a boolean checking [expression] against null. | 3528 /// Pushes a boolean checking [expression] against null. |
| 3475 pushCheckNull(HInstruction expression) { | 3529 pushCheckNull(HInstruction expression) { |
| 3476 push(new HIdentity(expression, graph.addConstantNull(compiler), | 3530 push(new HIdentity(expression, graph.addConstantNull(compiler), |
| 3477 null, backend.boolType)); | 3531 null, backend.boolType)); |
| 3478 } | 3532 } |
| 3479 | 3533 |
| 3480 @override | 3534 @override |
| 3481 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { | 3535 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { |
| 3482 handleLocalGet(variable); | 3536 handleLocalGet(node, variable); |
| 3483 } | 3537 } |
| 3484 | 3538 |
| 3485 @override | 3539 @override |
| 3486 void visitParameterGet(ast.Send node, ParameterElement parameter, _) { | 3540 void visitParameterGet(ast.Send node, ParameterElement parameter, _) { |
| 3487 handleLocalGet(parameter); | 3541 handleLocalGet(node, parameter); |
| 3488 } | 3542 } |
| 3489 | 3543 |
| 3490 @override | 3544 @override |
| 3491 void visitLocalFunctionGet(ast.Send node, LocalFunctionElement function, _) { | 3545 void visitLocalFunctionGet(ast.Send node, LocalFunctionElement function, _) { |
| 3492 handleLocalGet(function); | 3546 handleLocalGet(node, function); |
| 3493 } | 3547 } |
| 3494 | 3548 |
| 3495 @override | 3549 @override |
| 3496 void visitStaticFieldGet( | 3550 void visitStaticFieldGet( |
| 3497 ast.Send node, | 3551 ast.Send node, |
| 3498 FieldElement field, | 3552 FieldElement field, |
| 3499 _) { | 3553 _) { |
| 3500 generateStaticFieldGet(node, field); | 3554 generateStaticFieldGet(node, field); |
| 3501 } | 3555 } |
| 3502 | 3556 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3560 selector = elements.getSelector(send); | 3614 selector = elements.getSelector(send); |
| 3561 if (mask == null) { | 3615 if (mask == null) { |
| 3562 mask = elements.getTypeMask(send); | 3616 mask = elements.getTypeMask(send); |
| 3563 } | 3617 } |
| 3564 } | 3618 } |
| 3565 if (location == null) { | 3619 if (location == null) { |
| 3566 assert(send != null); | 3620 assert(send != null); |
| 3567 location = send; | 3621 location = send; |
| 3568 } | 3622 } |
| 3569 assert(selector.isSetter); | 3623 assert(selector.isSetter); |
| 3570 pushInvokeDynamic(location, selector, mask, [receiver, value]); | 3624 pushInvokeDynamic(location, selector, mask, [receiver, value], |
| 3625 sourceInformation: sourceInformationBuilder.buildAssignment(location)); |
| 3571 pop(); | 3626 pop(); |
| 3572 stack.add(value); | 3627 stack.add(value); |
| 3573 } | 3628 } |
| 3574 | 3629 |
| 3575 void generateNonInstanceSetter(ast.SendSet send, | 3630 void generateNonInstanceSetter(ast.SendSet send, |
| 3576 Element element, | 3631 Element element, |
| 3577 HInstruction value, | 3632 HInstruction value, |
| 3578 {ast.Node location}) { | 3633 {ast.Node location}) { |
| 3579 assert(send == null || !Elements.isInstanceSend(send, elements)); | 3634 assert(send == null || !Elements.isInstanceSend(send, elements)); |
| 3580 if (location == null) { | 3635 if (location == null) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 3610 if (value.sourceElement == null) { | 3665 if (value.sourceElement == null) { |
| 3611 value.sourceElement = local; | 3666 value.sourceElement = local; |
| 3612 } | 3667 } |
| 3613 HInstruction checkedOrTrusted = | 3668 HInstruction checkedOrTrusted = |
| 3614 potentiallyCheckOrTrustType(value, local.type); | 3669 potentiallyCheckOrTrustType(value, local.type); |
| 3615 if (!identical(checkedOrTrusted, value)) { | 3670 if (!identical(checkedOrTrusted, value)) { |
| 3616 pop(); | 3671 pop(); |
| 3617 stack.add(checkedOrTrusted); | 3672 stack.add(checkedOrTrusted); |
| 3618 } | 3673 } |
| 3619 | 3674 |
| 3620 localsHandler.updateLocal(local, checkedOrTrusted); | 3675 localsHandler.updateLocal(local, checkedOrTrusted, |
| 3676 sourceInformation: |
| 3677 sourceInformationBuilder.buildAssignment(location)); |
| 3621 } | 3678 } |
| 3622 } | 3679 } |
| 3623 | 3680 |
| 3624 HInstruction invokeInterceptor(HInstruction receiver) { | 3681 HInstruction invokeInterceptor(HInstruction receiver) { |
| 3625 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); | 3682 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); |
| 3626 add(interceptor); | 3683 add(interceptor); |
| 3627 return interceptor; | 3684 return interceptor; |
| 3628 } | 3685 } |
| 3629 | 3686 |
| 3630 HLiteralList buildLiteralList(List<HInstruction> inputs) { | 3687 HLiteralList buildLiteralList(List<HInstruction> inputs) { |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3820 | 3877 |
| 3821 /// Generate a dynamic method, getter or setter invocation. | 3878 /// Generate a dynamic method, getter or setter invocation. |
| 3822 void generateDynamicSend(ast.Send node) { | 3879 void generateDynamicSend(ast.Send node) { |
| 3823 HInstruction receiver = generateInstanceSendReceiver(node); | 3880 HInstruction receiver = generateInstanceSendReceiver(node); |
| 3824 _generateDynamicSend(node, receiver); | 3881 _generateDynamicSend(node, receiver); |
| 3825 } | 3882 } |
| 3826 | 3883 |
| 3827 void _generateDynamicSend(ast.Send node, HInstruction receiver) { | 3884 void _generateDynamicSend(ast.Send node, HInstruction receiver) { |
| 3828 Selector selector = elements.getSelector(node); | 3885 Selector selector = elements.getSelector(node); |
| 3829 TypeMask mask = elements.getTypeMask(node); | 3886 TypeMask mask = elements.getTypeMask(node); |
| 3887 SourceInformation sourceInformation = |
| 3888 sourceInformationBuilder.buildCall(node, node.selector); |
| 3830 | 3889 |
| 3831 List<HInstruction> inputs = <HInstruction>[]; | 3890 List<HInstruction> inputs = <HInstruction>[]; |
| 3832 inputs.add(receiver); | 3891 inputs.add(receiver); |
| 3833 addDynamicSendArgumentsToList(node, inputs); | 3892 addDynamicSendArgumentsToList(node, inputs); |
| 3834 | 3893 |
| 3835 pushInvokeDynamic(node, selector, mask, inputs); | 3894 pushInvokeDynamic(node, selector, mask, inputs, |
| 3895 sourceInformation: sourceInformation); |
| 3836 if (selector.isSetter || selector.isIndexSet) { | 3896 if (selector.isSetter || selector.isIndexSet) { |
| 3837 pop(); | 3897 pop(); |
| 3838 stack.add(inputs.last); | 3898 stack.add(inputs.last); |
| 3839 } | 3899 } |
| 3840 } | 3900 } |
| 3841 | 3901 |
| 3842 @override | 3902 @override |
| 3843 visitDynamicPropertyInvoke( | 3903 visitDynamicPropertyInvoke( |
| 3844 ast.Send node, | 3904 ast.Send node, |
| 3845 ast.Node receiver, | 3905 ast.Node receiver, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3877 generateDynamicSend(node); | 3937 generateDynamicSend(node); |
| 3878 } | 3938 } |
| 3879 | 3939 |
| 3880 @override | 3940 @override |
| 3881 visitExpressionInvoke( | 3941 visitExpressionInvoke( |
| 3882 ast.Send node, | 3942 ast.Send node, |
| 3883 ast.Node expression, | 3943 ast.Node expression, |
| 3884 ast.NodeList arguments, | 3944 ast.NodeList arguments, |
| 3885 Selector selector, | 3945 Selector selector, |
| 3886 _) { | 3946 _) { |
| 3887 generateCallInvoke(node, visitAndPop(expression)); | 3947 generateCallInvoke( |
| 3948 node, |
| 3949 visitAndPop(expression), |
| 3950 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 3888 } | 3951 } |
| 3889 | 3952 |
| 3890 @override | 3953 @override |
| 3891 visitThisInvoke( | 3954 visitThisInvoke( |
| 3892 ast.Send node, | 3955 ast.Send node, |
| 3893 ast.NodeList arguments, | 3956 ast.NodeList arguments, |
| 3894 CallStructure callStructure, | 3957 CallStructure callStructure, |
| 3895 _) { | 3958 _) { |
| 3896 generateCallInvoke(node, localsHandler.readThis()); | 3959 generateCallInvoke( |
| 3960 node, |
| 3961 localsHandler.readThis(), |
| 3962 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 3897 } | 3963 } |
| 3898 | 3964 |
| 3899 @override | 3965 @override |
| 3900 visitParameterInvoke( | 3966 visitParameterInvoke( |
| 3901 ast.Send node, | 3967 ast.Send node, |
| 3902 ParameterElement parameter, | 3968 ParameterElement parameter, |
| 3903 ast.NodeList arguments, | 3969 ast.NodeList arguments, |
| 3904 CallStructure callStructure, | 3970 CallStructure callStructure, |
| 3905 _) { | 3971 _) { |
| 3906 generateCallInvoke(node, localsHandler.readLocal(parameter)); | 3972 generateCallInvoke( |
| 3973 node, |
| 3974 localsHandler.readLocal(parameter), |
| 3975 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 3907 } | 3976 } |
| 3908 | 3977 |
| 3909 @override | 3978 @override |
| 3910 visitLocalVariableInvoke( | 3979 visitLocalVariableInvoke( |
| 3911 ast.Send node, | 3980 ast.Send node, |
| 3912 LocalVariableElement variable, | 3981 LocalVariableElement variable, |
| 3913 ast.NodeList arguments, | 3982 ast.NodeList arguments, |
| 3914 CallStructure callStructure, | 3983 CallStructure callStructure, |
| 3915 _) { | 3984 _) { |
| 3916 generateCallInvoke(node, localsHandler.readLocal(variable)); | 3985 generateCallInvoke( |
| 3986 node, |
| 3987 localsHandler.readLocal(variable), |
| 3988 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 3917 } | 3989 } |
| 3918 | 3990 |
| 3919 @override | 3991 @override |
| 3920 visitLocalFunctionInvoke( | 3992 visitLocalFunctionInvoke( |
| 3921 ast.Send node, | 3993 ast.Send node, |
| 3922 LocalFunctionElement function, | 3994 LocalFunctionElement function, |
| 3923 ast.NodeList arguments, | 3995 ast.NodeList arguments, |
| 3924 CallStructure callStructure, | 3996 CallStructure callStructure, |
| 3925 _) { | 3997 _) { |
| 3926 generateCallInvoke(node, localsHandler.readLocal(function)); | 3998 generateCallInvoke( |
| 3999 node, |
| 4000 localsHandler.readLocal(function), |
| 4001 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 3927 } | 4002 } |
| 3928 | 4003 |
| 3929 @override | 4004 @override |
| 3930 visitLocalFunctionIncompatibleInvoke( | 4005 visitLocalFunctionIncompatibleInvoke( |
| 3931 ast.Send node, | 4006 ast.Send node, |
| 3932 LocalFunctionElement function, | 4007 LocalFunctionElement function, |
| 3933 ast.NodeList arguments, | 4008 ast.NodeList arguments, |
| 3934 CallStructure callStructure, | 4009 CallStructure callStructure, |
| 3935 _) { | 4010 _) { |
| 3936 generateCallInvoke(node, localsHandler.readLocal(function)); | 4011 generateCallInvoke(node, localsHandler.readLocal(function), |
| 4012 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 3937 } | 4013 } |
| 3938 | 4014 |
| 3939 void handleForeignJs(ast.Send node) { | 4015 void handleForeignJs(ast.Send node) { |
| 3940 Link<ast.Node> link = node.arguments; | 4016 Link<ast.Node> link = node.arguments; |
| 3941 // Don't visit the first argument, which is the type, and the second | 4017 // Don't visit the first argument, which is the type, and the second |
| 3942 // argument, which is the foreign code. | 4018 // argument, which is the foreign code. |
| 3943 if (link.isEmpty || link.tail.isEmpty) { | 4019 if (link.isEmpty || link.tail.isEmpty) { |
| 3944 compiler.internalError(node.argumentsNode, | 4020 compiler.internalError(node.argumentsNode, |
| 3945 'At least two arguments expected.'); | 4021 'At least two arguments expected.'); |
| 3946 } | 4022 } |
| 3947 native.NativeBehavior nativeBehavior = | 4023 native.NativeBehavior nativeBehavior = |
| 3948 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); | 4024 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); |
| 3949 | 4025 |
| 3950 List<HInstruction> inputs = <HInstruction>[]; | 4026 List<HInstruction> inputs = <HInstruction>[]; |
| 3951 addGenericSendArgumentsToList(link.tail.tail, inputs); | 4027 addGenericSendArgumentsToList(link.tail.tail, inputs); |
| 3952 | 4028 |
| 3953 TypeMask ssaType = | 4029 TypeMask ssaType = |
| 3954 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); | 4030 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); |
| 3955 | 4031 |
| 4032 SourceInformation sourceInformation = |
| 4033 sourceInformationBuilder.buildCall(node, node.argumentsNode); |
| 3956 if (nativeBehavior.codeTemplate.isExpression) { | 4034 if (nativeBehavior.codeTemplate.isExpression) { |
| 3957 push(new HForeignCode( | 4035 push(new HForeignCode( |
| 3958 nativeBehavior.codeTemplate, ssaType, inputs, | 4036 nativeBehavior.codeTemplate, ssaType, inputs, |
| 3959 effects: nativeBehavior.sideEffects, | 4037 effects: nativeBehavior.sideEffects, |
| 3960 nativeBehavior: nativeBehavior)); | 4038 nativeBehavior: nativeBehavior) |
| 4039 ..sourceInformation = sourceInformation); |
| 3961 } else { | 4040 } else { |
| 3962 push(new HForeignCode( | 4041 push(new HForeignCode( |
| 3963 nativeBehavior.codeTemplate, ssaType, inputs, | 4042 nativeBehavior.codeTemplate, ssaType, inputs, |
| 3964 isStatement: true, | 4043 isStatement: true, |
| 3965 effects: nativeBehavior.sideEffects, | 4044 effects: nativeBehavior.sideEffects, |
| 3966 nativeBehavior: nativeBehavior)); | 4045 nativeBehavior: nativeBehavior) |
| 4046 ..sourceInformation = sourceInformation); |
| 3967 } | 4047 } |
| 3968 } | 4048 } |
| 3969 | 4049 |
| 3970 void handleJsStringConcat(ast.Send node) { | 4050 void handleJsStringConcat(ast.Send node) { |
| 3971 List<HInstruction> inputs = <HInstruction>[]; | 4051 List<HInstruction> inputs = <HInstruction>[]; |
| 3972 addGenericSendArgumentsToList(node.arguments, inputs); | 4052 addGenericSendArgumentsToList(node.arguments, inputs); |
| 3973 if (inputs.length != 2) { | 4053 if (inputs.length != 2) { |
| 3974 compiler.internalError(node.argumentsNode, 'Two arguments expected.'); | 4054 compiler.internalError(node.argumentsNode, 'Two arguments expected.'); |
| 3975 } | 4055 } |
| 3976 push(new HStringConcat(inputs[0], inputs[1], node, backend.stringType)); | 4056 push(new HStringConcat(inputs[0], inputs[1], node, backend.stringType)); |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4305 stack.add(graph.addConstantNull(compiler)); | 4385 stack.add(graph.addConstantNull(compiler)); |
| 4306 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { | 4386 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { |
| 4307 handleJsInterceptorConstant(node); | 4387 handleJsInterceptorConstant(node); |
| 4308 } else if (name == 'JS_STRING_CONCAT') { | 4388 } else if (name == 'JS_STRING_CONCAT') { |
| 4309 handleJsStringConcat(node); | 4389 handleJsStringConcat(node); |
| 4310 } else { | 4390 } else { |
| 4311 compiler.internalError(node, "Unknown foreign: ${element}"); | 4391 compiler.internalError(node, "Unknown foreign: ${element}"); |
| 4312 } | 4392 } |
| 4313 } | 4393 } |
| 4314 | 4394 |
| 4315 generateDeferredLoaderGet(ast.Send node, FunctionElement deferredLoader) { | 4395 generateDeferredLoaderGet(ast.Send node, |
| 4396 FunctionElement deferredLoader, |
| 4397 SourceInformation sourceInformation) { |
| 4316 // Until now we only handle these as getters. | 4398 // Until now we only handle these as getters. |
| 4317 invariant(node, deferredLoader.isDeferredLoaderGetter); | 4399 invariant(node, deferredLoader.isDeferredLoaderGetter); |
| 4318 Element loadFunction = compiler.loadLibraryFunction; | 4400 Element loadFunction = compiler.loadLibraryFunction; |
| 4319 PrefixElement prefixElement = deferredLoader.enclosingElement; | 4401 PrefixElement prefixElement = deferredLoader.enclosingElement; |
| 4320 String loadId = compiler.deferredLoadTask | 4402 String loadId = compiler.deferredLoadTask |
| 4321 .importDeferName[prefixElement.deferredImport]; | 4403 .importDeferName[prefixElement.deferredImport]; |
| 4322 var inputs = [graph.addConstantString( | 4404 var inputs = [graph.addConstantString( |
| 4323 new ast.DartString.literal(loadId), compiler)]; | 4405 new ast.DartString.literal(loadId), compiler)]; |
| 4324 push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType, | 4406 push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType, |
| 4325 targetCanThrow: false)); | 4407 targetCanThrow: false) |
| 4408 ..sourceInformation = sourceInformation); |
| 4326 } | 4409 } |
| 4327 | 4410 |
| 4328 generateSuperNoSuchMethodSend(ast.Send node, | 4411 generateSuperNoSuchMethodSend(ast.Send node, |
| 4329 Selector selector, | 4412 Selector selector, |
| 4330 List<HInstruction> arguments) { | 4413 List<HInstruction> arguments) { |
| 4331 String name = selector.name; | 4414 String name = selector.name; |
| 4332 | 4415 |
| 4333 ClassElement cls = currentNonClosureClass; | 4416 ClassElement cls = currentNonClosureClass; |
| 4334 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); | 4417 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); |
| 4335 if (compiler.enabledInvokeOn | 4418 if (compiler.enabledInvokeOn |
| (...skipping 28 matching lines...) Expand all Loading... |
| 4364 ConstantValue kindConstant = | 4447 ConstantValue kindConstant = |
| 4365 constantSystem.createInt(selector.invocationMirrorKind); | 4448 constantSystem.createInt(selector.invocationMirrorKind); |
| 4366 | 4449 |
| 4367 pushInvokeStatic(null, | 4450 pushInvokeStatic(null, |
| 4368 createInvocationMirror, | 4451 createInvocationMirror, |
| 4369 [graph.addConstant(nameConstant, compiler), | 4452 [graph.addConstant(nameConstant, compiler), |
| 4370 graph.addConstantStringFromName(internalName, compiler), | 4453 graph.addConstantStringFromName(internalName, compiler), |
| 4371 graph.addConstant(kindConstant, compiler), | 4454 graph.addConstant(kindConstant, compiler), |
| 4372 argumentsInstruction, | 4455 argumentsInstruction, |
| 4373 argumentNamesInstruction], | 4456 argumentNamesInstruction], |
| 4374 typeMask: backend.dynamicType); | 4457 typeMask: backend.dynamicType); |
| 4375 | 4458 |
| 4376 var inputs = <HInstruction>[pop()]; | 4459 var inputs = <HInstruction>[pop()]; |
| 4377 push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs)); | 4460 push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs)); |
| 4378 } | 4461 } |
| 4379 | 4462 |
| 4380 /// Generate a call to a super method or constructor. | 4463 /// Generate a call to a super method or constructor. |
| 4381 void generateSuperInvoke(ast.Send node, FunctionElement function) { | 4464 void generateSuperInvoke(ast.Send node, |
| 4465 FunctionElement function, |
| 4466 SourceInformation sourceInformation) { |
| 4382 // TODO(5347): Try to avoid the need for calling [implementation] before | 4467 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 4383 // calling [makeStaticArgumentList]. | 4468 // calling [makeStaticArgumentList]. |
| 4384 Selector selector = elements.getSelector(node); | 4469 Selector selector = elements.getSelector(node); |
| 4385 assert(invariant(node, | 4470 assert(invariant(node, |
| 4386 selector.applies(function.implementation, compiler.world), | 4471 selector.applies(function.implementation, compiler.world), |
| 4387 message: "$selector does not apply to ${function.implementation}")); | 4472 message: "$selector does not apply to ${function.implementation}")); |
| 4388 List<HInstruction> inputs = | 4473 List<HInstruction> inputs = |
| 4389 makeStaticArgumentList(selector.callStructure, | 4474 makeStaticArgumentList(selector.callStructure, |
| 4390 node.arguments, | 4475 node.arguments, |
| 4391 function.implementation); | 4476 function.implementation); |
| 4392 push(buildInvokeSuper(selector, function, inputs)); | 4477 push(buildInvokeSuper(selector, function, inputs, sourceInformation)); |
| 4393 } | 4478 } |
| 4394 | 4479 |
| 4395 /// Access the value from the super [element]. | 4480 /// Access the value from the super [element]. |
| 4396 void handleSuperGet(ast.Send node, Element element) { | 4481 void handleSuperGet(ast.Send node, Element element) { |
| 4397 Selector selector = elements.getSelector(node); | 4482 Selector selector = elements.getSelector(node); |
| 4398 push(buildInvokeSuper(selector, element, const <HInstruction>[])); | 4483 SourceInformation sourceInformation = |
| 4484 sourceInformationBuilder.buildGet(node); |
| 4485 push(buildInvokeSuper( |
| 4486 selector, element, const <HInstruction>[], sourceInformation)); |
| 4399 } | 4487 } |
| 4400 | 4488 |
| 4401 /// Invoke .call on the value retrieved from the super [element]. | 4489 /// Invoke .call on the value retrieved from the super [element]. |
| 4402 void handleSuperCallInvoke(ast.Send node, Element element) { | 4490 void handleSuperCallInvoke(ast.Send node, Element element) { |
| 4403 Selector selector = elements.getSelector(node); | 4491 Selector selector = elements.getSelector(node); |
| 4404 HInstruction target = | 4492 HInstruction target = buildInvokeSuper( |
| 4405 buildInvokeSuper(selector, element, const <HInstruction>[]); | 4493 selector, element, const <HInstruction>[], |
| 4494 sourceInformationBuilder.buildGet(node)); |
| 4406 add(target); | 4495 add(target); |
| 4407 generateCallInvoke(node, target); | 4496 generateCallInvoke( |
| 4497 node, |
| 4498 target, |
| 4499 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 4408 } | 4500 } |
| 4409 | 4501 |
| 4410 /// Invoke super [method]. | 4502 /// Invoke super [method]. |
| 4411 void handleSuperMethodInvoke( | 4503 void handleSuperMethodInvoke( |
| 4412 ast.Send node, | 4504 ast.Send node, |
| 4413 MethodElement method) { | 4505 MethodElement method) { |
| 4414 generateSuperInvoke(node, method); | 4506 generateSuperInvoke(node, method, |
| 4507 sourceInformationBuilder.buildCall(node, node.selector)); |
| 4415 } | 4508 } |
| 4416 | 4509 |
| 4417 /// Access an unresolved super property. | 4510 /// Access an unresolved super property. |
| 4418 void handleUnresolvedSuperInvoke(ast.Send node) { | 4511 void handleUnresolvedSuperInvoke(ast.Send node) { |
| 4419 Selector selector = elements.getSelector(node); | 4512 Selector selector = elements.getSelector(node); |
| 4420 List<HInstruction> arguments = <HInstruction>[]; | 4513 List<HInstruction> arguments = <HInstruction>[]; |
| 4421 if (!node.isPropertyAccess) { | 4514 if (!node.isPropertyAccess) { |
| 4422 addGenericSendArgumentsToList(node.arguments, arguments); | 4515 addGenericSendArgumentsToList(node.arguments, arguments); |
| 4423 } | 4516 } |
| 4424 generateSuperNoSuchMethodSend(node, selector, arguments); | 4517 generateSuperNoSuchMethodSend(node, selector, arguments); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4615 return !rti.isTrivialSubstitution(subclass, cls); | 4708 return !rti.isTrivialSubstitution(subclass, cls); |
| 4616 }); | 4709 }); |
| 4617 } | 4710 } |
| 4618 | 4711 |
| 4619 /** | 4712 /** |
| 4620 * Generate code to extract the type arguments from the object, substitute | 4713 * Generate code to extract the type arguments from the object, substitute |
| 4621 * them as an instance of the type we are testing against (if necessary), and | 4714 * them as an instance of the type we are testing against (if necessary), and |
| 4622 * extract the type argument by the index of the variable in the list of type | 4715 * extract the type argument by the index of the variable in the list of type |
| 4623 * variables for that class. | 4716 * variables for that class. |
| 4624 */ | 4717 */ |
| 4625 HInstruction readTypeVariable(ClassElement cls, | 4718 HInstruction readTypeVariable( |
| 4626 TypeVariableElement variable) { | 4719 ClassElement cls, |
| 4720 TypeVariableElement variable, |
| 4721 {SourceInformation sourceInformation}) { |
| 4627 assert(sourceElement.isInstanceMember); | 4722 assert(sourceElement.isInstanceMember); |
| 4628 | 4723 |
| 4629 HInstruction target = localsHandler.readThis(); | 4724 HInstruction target = localsHandler.readThis(); |
| 4630 HConstant index = graph.addConstantInt( | 4725 HConstant index = graph.addConstantInt( |
| 4631 RuntimeTypes.getTypeVariableIndex(variable), | 4726 RuntimeTypes.getTypeVariableIndex(variable), |
| 4632 compiler); | 4727 compiler); |
| 4633 | 4728 |
| 4634 if (needsSubstitutionForTypeVariableAccess(cls)) { | 4729 if (needsSubstitutionForTypeVariableAccess(cls)) { |
| 4635 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to | 4730 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to |
| 4636 // string concatenation in the implementation), and may prevent | 4731 // string concatenation in the implementation), and may prevent |
| 4637 // segmentation of '$'. | 4732 // segmentation of '$'. |
| 4638 js.Name substitutionName = backend.namer.runtimeTypeName(cls); | 4733 js.Name substitutionName = backend.namer.runtimeTypeName(cls); |
| 4639 HInstruction substitutionNameInstr = graph.addConstantStringFromName( | 4734 HInstruction substitutionNameInstr = graph.addConstantStringFromName( |
| 4640 substitutionName, compiler); | 4735 substitutionName, compiler); |
| 4641 pushInvokeStatic(null, | 4736 pushInvokeStatic(null, |
| 4642 backend.getGetRuntimeTypeArgument(), | 4737 backend.getGetRuntimeTypeArgument(), |
| 4643 [target, substitutionNameInstr, index], | 4738 [target, substitutionNameInstr, index], |
| 4644 typeMask: backend.dynamicType); | 4739 typeMask: backend.dynamicType, |
| 4740 sourceInformation: sourceInformation); |
| 4645 } else { | 4741 } else { |
| 4646 pushInvokeStatic(null, backend.getGetTypeArgumentByIndex(), | 4742 pushInvokeStatic( |
| 4743 null, |
| 4744 backend.getGetTypeArgumentByIndex(), |
| 4647 [target, index], | 4745 [target, index], |
| 4648 typeMask: backend.dynamicType); | 4746 typeMask: backend.dynamicType, |
| 4747 sourceInformation: sourceInformation); |
| 4649 } | 4748 } |
| 4650 return pop(); | 4749 return pop(); |
| 4651 } | 4750 } |
| 4652 | 4751 |
| 4653 // TODO(karlklose): this is needed to avoid a bug where the resolved type is | 4752 // TODO(karlklose): this is needed to avoid a bug where the resolved type is |
| 4654 // not stored on a type annotation in the closure translator. Remove when | 4753 // not stored on a type annotation in the closure translator. Remove when |
| 4655 // fixed. | 4754 // fixed. |
| 4656 bool hasDirectLocal(Local local) { | 4755 bool hasDirectLocal(Local local) { |
| 4657 return !localsHandler.isAccessedDirectly(local) || | 4756 return !localsHandler.isAccessedDirectly(local) || |
| 4658 localsHandler.directLocals[local] != null; | 4757 localsHandler.directLocals[local] != null; |
| 4659 } | 4758 } |
| 4660 | 4759 |
| 4661 /** | 4760 /** |
| 4662 * Helper to create an instruction that gets the value of a type variable. | 4761 * Helper to create an instruction that gets the value of a type variable. |
| 4663 */ | 4762 */ |
| 4664 HInstruction addTypeVariableReference(TypeVariableType type) { | 4763 HInstruction addTypeVariableReference( |
| 4764 TypeVariableType type, |
| 4765 {SourceInformation sourceInformation}) { |
| 4766 |
| 4665 assert(assertTypeInContext(type)); | 4767 assert(assertTypeInContext(type)); |
| 4666 Element member = sourceElement; | 4768 Element member = sourceElement; |
| 4667 bool isClosure = member.enclosingElement.isClosure; | 4769 bool isClosure = member.enclosingElement.isClosure; |
| 4668 if (isClosure) { | 4770 if (isClosure) { |
| 4669 ClosureClassElement closureClass = member.enclosingElement; | 4771 ClosureClassElement closureClass = member.enclosingElement; |
| 4670 member = closureClass.methodElement; | 4772 member = closureClass.methodElement; |
| 4671 member = member.outermostEnclosingMemberOrTopLevel; | 4773 member = member.outermostEnclosingMemberOrTopLevel; |
| 4672 } | 4774 } |
| 4673 bool isInConstructorContext = member.isConstructor || | 4775 bool isInConstructorContext = member.isConstructor || |
| 4674 member.isGenerativeConstructorBody; | 4776 member.isGenerativeConstructorBody; |
| 4675 Local typeVariableLocal = localsHandler.getTypeVariableAsLocal(type); | 4777 Local typeVariableLocal = localsHandler.getTypeVariableAsLocal(type); |
| 4676 if (isClosure) { | 4778 if (isClosure) { |
| 4677 if (member.isFactoryConstructor || | 4779 if (member.isFactoryConstructor || |
| 4678 (isInConstructorContext && hasDirectLocal(typeVariableLocal))) { | 4780 (isInConstructorContext && hasDirectLocal(typeVariableLocal))) { |
| 4679 // The type variable is used from a closure in a factory constructor. | 4781 // The type variable is used from a closure in a factory constructor. |
| 4680 // The value of the type argument is stored as a local on the closure | 4782 // The value of the type argument is stored as a local on the closure |
| 4681 // itself. | 4783 // itself. |
| 4682 return localsHandler.readLocal(typeVariableLocal); | 4784 return localsHandler.readLocal( |
| 4785 typeVariableLocal, sourceInformation: sourceInformation); |
| 4683 } else if (member.isFunction || | 4786 } else if (member.isFunction || |
| 4684 member.isGetter || | 4787 member.isGetter || |
| 4685 member.isSetter || | 4788 member.isSetter || |
| 4686 isInConstructorContext) { | 4789 isInConstructorContext) { |
| 4687 // The type variable is stored on the "enclosing object" and needs to be | 4790 // The type variable is stored on the "enclosing object" and needs to be |
| 4688 // accessed using the this-reference in the closure. | 4791 // accessed using the this-reference in the closure. |
| 4689 return readTypeVariable(member.enclosingClass, type.element); | 4792 return readTypeVariable( |
| 4793 member.enclosingClass, |
| 4794 type.element, |
| 4795 sourceInformation: sourceInformation); |
| 4690 } else { | 4796 } else { |
| 4691 assert(member.isField); | 4797 assert(member.isField); |
| 4692 // The type variable is stored in a parameter of the method. | 4798 // The type variable is stored in a parameter of the method. |
| 4693 return localsHandler.readLocal(typeVariableLocal); | 4799 return localsHandler.readLocal(typeVariableLocal); |
| 4694 } | 4800 } |
| 4695 } else if (isInConstructorContext || | 4801 } else if (isInConstructorContext || |
| 4696 // When [member] is a field, we can be either | 4802 // When [member] is a field, we can be either |
| 4697 // generating a checked setter or inlining its | 4803 // generating a checked setter or inlining its |
| 4698 // initializer in a constructor. An initializer is | 4804 // initializer in a constructor. An initializer is |
| 4699 // never built standalone, so [isBuildingFor] will | 4805 // never built standalone, so [isBuildingFor] will |
| 4700 // always return true when seeing one. | 4806 // always return true when seeing one. |
| 4701 (member.isField && !isBuildingFor(member))) { | 4807 (member.isField && !isBuildingFor(member))) { |
| 4702 // The type variable is stored in a parameter of the method. | 4808 // The type variable is stored in a parameter of the method. |
| 4703 return localsHandler.readLocal(typeVariableLocal); | 4809 return localsHandler.readLocal( |
| 4810 typeVariableLocal, sourceInformation: sourceInformation); |
| 4704 } else if (member.isInstanceMember) { | 4811 } else if (member.isInstanceMember) { |
| 4705 // The type variable is stored on the object. | 4812 // The type variable is stored on the object. |
| 4706 return readTypeVariable(member.enclosingClass, | 4813 return readTypeVariable( |
| 4707 type.element); | 4814 member.enclosingClass, |
| 4815 type.element, |
| 4816 sourceInformation: sourceInformation); |
| 4708 } else { | 4817 } else { |
| 4709 compiler.internalError(type.element, | 4818 compiler.internalError(type.element, |
| 4710 'Unexpected type variable in static context.'); | 4819 'Unexpected type variable in static context.'); |
| 4711 return null; | 4820 return null; |
| 4712 } | 4821 } |
| 4713 } | 4822 } |
| 4714 | 4823 |
| 4715 HInstruction analyzeTypeArgument(DartType argument) { | 4824 HInstruction analyzeTypeArgument( |
| 4825 DartType argument, |
| 4826 {SourceInformation sourceInformation}) { |
| 4827 |
| 4716 assert(assertTypeInContext(argument)); | 4828 assert(assertTypeInContext(argument)); |
| 4717 if (argument.treatAsDynamic) { | 4829 if (argument.treatAsDynamic) { |
| 4718 // Represent [dynamic] as [null]. | 4830 // Represent [dynamic] as [null]. |
| 4719 return graph.addConstantNull(compiler); | 4831 return graph.addConstantNull(compiler); |
| 4720 } | 4832 } |
| 4721 | 4833 |
| 4722 if (argument.isTypeVariable) { | 4834 if (argument.isTypeVariable) { |
| 4723 return addTypeVariableReference(argument); | 4835 return addTypeVariableReference( |
| 4836 argument, sourceInformation: sourceInformation); |
| 4724 } | 4837 } |
| 4725 | 4838 |
| 4726 List<HInstruction> inputs = <HInstruction>[]; | 4839 List<HInstruction> inputs = <HInstruction>[]; |
| 4727 | 4840 |
| 4728 js.Expression template = | 4841 js.Expression template = |
| 4729 rti.getTypeRepresentationWithPlaceholders(argument, (variable) { | 4842 rti.getTypeRepresentationWithPlaceholders(argument, (variable) { |
| 4730 inputs.add(addTypeVariableReference(variable)); | 4843 inputs.add(addTypeVariableReference(variable)); |
| 4731 }); | 4844 }); |
| 4732 | 4845 |
| 4733 js.Template code = new js.Template(null, template); | 4846 js.Template code = new js.Template(null, template); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4748 type.typeArguments.forEach((DartType argument) { | 4861 type.typeArguments.forEach((DartType argument) { |
| 4749 inputs.add(analyzeTypeArgument(argument)); | 4862 inputs.add(analyzeTypeArgument(argument)); |
| 4750 }); | 4863 }); |
| 4751 // TODO(15489): Register at codegen. | 4864 // TODO(15489): Register at codegen. |
| 4752 registry.registerInstantiatedType(type); | 4865 registry.registerInstantiatedType(type); |
| 4753 return callSetRuntimeTypeInfo(type.element, inputs, newObject); | 4866 return callSetRuntimeTypeInfo(type.element, inputs, newObject); |
| 4754 } | 4867 } |
| 4755 | 4868 |
| 4756 void copyRuntimeTypeInfo(HInstruction source, HInstruction target) { | 4869 void copyRuntimeTypeInfo(HInstruction source, HInstruction target) { |
| 4757 Element copyHelper = backend.getCopyTypeArguments(); | 4870 Element copyHelper = backend.getCopyTypeArguments(); |
| 4758 pushInvokeStatic(null, copyHelper, [source, target]); | 4871 pushInvokeStatic(null, copyHelper, [source, target], |
| 4872 sourceInformation: target.sourceInformation); |
| 4759 pop(); | 4873 pop(); |
| 4760 } | 4874 } |
| 4761 | 4875 |
| 4762 HInstruction callSetRuntimeTypeInfo(ClassElement element, | 4876 HInstruction callSetRuntimeTypeInfo(ClassElement element, |
| 4763 List<HInstruction> rtiInputs, | 4877 List<HInstruction> rtiInputs, |
| 4764 HInstruction newObject) { | 4878 HInstruction newObject) { |
| 4765 if (!backend.classNeedsRti(element) || element.typeVariables.isEmpty) { | 4879 if (!backend.classNeedsRti(element) || element.typeVariables.isEmpty) { |
| 4766 return newObject; | 4880 return newObject; |
| 4767 } | 4881 } |
| 4768 | 4882 |
| 4769 HInstruction typeInfo = buildLiteralList(rtiInputs); | 4883 HInstruction typeInfo = buildLiteralList(rtiInputs); |
| 4770 add(typeInfo); | 4884 add(typeInfo); |
| 4771 | 4885 |
| 4772 // Set the runtime type information on the object. | 4886 // Set the runtime type information on the object. |
| 4773 Element typeInfoSetterElement = backend.getSetRuntimeTypeInfo(); | 4887 Element typeInfoSetterElement = backend.getSetRuntimeTypeInfo(); |
| 4774 pushInvokeStatic( | 4888 pushInvokeStatic( |
| 4775 null, | 4889 null, |
| 4776 typeInfoSetterElement, | 4890 typeInfoSetterElement, |
| 4777 <HInstruction>[newObject, typeInfo], | 4891 <HInstruction>[newObject, typeInfo], |
| 4778 typeMask: backend.dynamicType); | 4892 typeMask: backend.dynamicType, |
| 4893 sourceInformation: newObject.sourceInformation); |
| 4779 | 4894 |
| 4780 // The new object will now be referenced through the | 4895 // The new object will now be referenced through the |
| 4781 // `setRuntimeTypeInfo` call. We therefore set the type of that | 4896 // `setRuntimeTypeInfo` call. We therefore set the type of that |
| 4782 // instruction to be of the object's type. | 4897 // instruction to be of the object's type. |
| 4783 assert(stack.last is HInvokeStatic || stack.last == newObject); | 4898 assert(stack.last is HInvokeStatic || stack.last == newObject); |
| 4784 stack.last.instructionType = newObject.instructionType; | 4899 stack.last.instructionType = newObject.instructionType; |
| 4785 return pop(); | 4900 return pop(); |
| 4786 } | 4901 } |
| 4787 | 4902 |
| 4788 void handleNewSend(ast.NewExpression node) { | 4903 void handleNewSend(ast.NewExpression node) { |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4926 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); | 5041 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); |
| 4927 // We set the instruction as [canThrow] to avoid it being dead code. | 5042 // We set the instruction as [canThrow] to avoid it being dead code. |
| 4928 // We need a finer grained side effect. | 5043 // We need a finer grained side effect. |
| 4929 add(new HForeignCode(code, backend.nullType, [stack.last], | 5044 add(new HForeignCode(code, backend.nullType, [stack.last], |
| 4930 throwBehavior: native.NativeThrowBehavior.MAY)); | 5045 throwBehavior: native.NativeThrowBehavior.MAY)); |
| 4931 } | 5046 } |
| 4932 } else if (isGrowableListConstructorCall) { | 5047 } else if (isGrowableListConstructorCall) { |
| 4933 push(buildLiteralList(<HInstruction>[])); | 5048 push(buildLiteralList(<HInstruction>[])); |
| 4934 stack.last.instructionType = elementType; | 5049 stack.last.instructionType = elementType; |
| 4935 } else { | 5050 } else { |
| 5051 SourceInformation sourceInformation = |
| 5052 sourceInformationBuilder.buildNew(send); |
| 4936 ClassElement cls = constructor.enclosingClass; | 5053 ClassElement cls = constructor.enclosingClass; |
| 4937 if (cls.isAbstract && constructor.isGenerativeConstructor) { | 5054 if (cls.isAbstract && constructor.isGenerativeConstructor) { |
| 4938 generateAbstractClassInstantiationError(send, cls.name); | 5055 generateAbstractClassInstantiationError(send, cls.name); |
| 4939 return; | 5056 return; |
| 4940 } | 5057 } |
| 4941 potentiallyAddTypeArguments(inputs, cls, expectedType); | 5058 potentiallyAddTypeArguments(inputs, cls, expectedType); |
| 4942 | 5059 |
| 4943 addInlinedInstantiation(expectedType); | 5060 addInlinedInstantiation(expectedType); |
| 4944 pushInvokeStatic(node, constructor, inputs, | 5061 pushInvokeStatic(node, constructor, inputs, |
| 4945 typeMask: elementType, instanceType: expectedType); | 5062 typeMask: elementType, |
| 5063 instanceType: expectedType, |
| 5064 sourceInformation: sourceInformation); |
| 4946 removeInlinedInstantiation(expectedType); | 5065 removeInlinedInstantiation(expectedType); |
| 4947 } | 5066 } |
| 4948 HInstruction newInstance = stack.last; | 5067 HInstruction newInstance = stack.last; |
| 4949 if (isFixedList) { | 5068 if (isFixedList) { |
| 4950 // Overwrite the element type, in case the allocation site has | 5069 // Overwrite the element type, in case the allocation site has |
| 4951 // been inlined. | 5070 // been inlined. |
| 4952 newInstance.instructionType = elementType; | 5071 newInstance.instructionType = elementType; |
| 4953 JavaScriptItemCompilationContext context = work.compilationContext; | 5072 JavaScriptItemCompilationContext context = work.compilationContext; |
| 4954 context.allocatedFixedLists.add(newInstance); | 5073 context.allocatedFixedLists.add(newInstance); |
| 4955 } | 5074 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4969 if (isRedirected) { | 5088 if (isRedirected) { |
| 4970 HInstruction checked = potentiallyCheckOrTrustType(newInstance, type); | 5089 HInstruction checked = potentiallyCheckOrTrustType(newInstance, type); |
| 4971 if (checked != newInstance) { | 5090 if (checked != newInstance) { |
| 4972 pop(); | 5091 pop(); |
| 4973 stack.add(checked); | 5092 stack.add(checked); |
| 4974 } | 5093 } |
| 4975 } | 5094 } |
| 4976 } | 5095 } |
| 4977 | 5096 |
| 4978 void potentiallyAddTypeArguments(List<HInstruction> inputs, ClassElement cls, | 5097 void potentiallyAddTypeArguments(List<HInstruction> inputs, ClassElement cls, |
| 4979 InterfaceType expectedType) { | 5098 InterfaceType expectedType, |
| 5099 {SourceInformation sourceInformation}) { |
| 4980 if (!backend.classNeedsRti(cls)) return; | 5100 if (!backend.classNeedsRti(cls)) return; |
| 4981 assert(expectedType.typeArguments.isEmpty || | 5101 assert(expectedType.typeArguments.isEmpty || |
| 4982 cls.typeVariables.length == expectedType.typeArguments.length); | 5102 cls.typeVariables.length == expectedType.typeArguments.length); |
| 4983 expectedType.typeArguments.forEach((DartType argument) { | 5103 expectedType.typeArguments.forEach((DartType argument) { |
| 4984 inputs.add(analyzeTypeArgument(argument)); | 5104 inputs.add(analyzeTypeArgument( |
| 5105 argument, sourceInformation: sourceInformation)); |
| 4985 }); | 5106 }); |
| 4986 } | 5107 } |
| 4987 | 5108 |
| 4988 /// In checked mode checks the [type] of [node] to be well-bounded. The method | 5109 /// In checked mode checks the [type] of [node] to be well-bounded. The method |
| 4989 /// returns [:true:] if an error can be statically determined. | 5110 /// returns [:true:] if an error can be statically determined. |
| 4990 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { | 5111 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { |
| 4991 if (!compiler.enableTypeAssertions) return false; | 5112 if (!compiler.enableTypeAssertions) return false; |
| 4992 | 5113 |
| 4993 Map<DartType, Set<DartType>> seenChecksMap = | 5114 Map<DartType, Set<DartType>> seenChecksMap = |
| 4994 new Map<DartType, Set<DartType>>(); | 5115 new Map<DartType, Set<DartType>>(); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5067 List<HInstruction> inputs = makeStaticArgumentList( | 5188 List<HInstruction> inputs = makeStaticArgumentList( |
| 5068 callStructure, | 5189 callStructure, |
| 5069 node.arguments, | 5190 node.arguments, |
| 5070 function.implementation); | 5191 function.implementation); |
| 5071 | 5192 |
| 5072 if (function == compiler.identicalFunction) { | 5193 if (function == compiler.identicalFunction) { |
| 5073 pushWithPosition( | 5194 pushWithPosition( |
| 5074 new HIdentity(inputs[0], inputs[1], null, backend.boolType), node); | 5195 new HIdentity(inputs[0], inputs[1], null, backend.boolType), node); |
| 5075 return; | 5196 return; |
| 5076 } else { | 5197 } else { |
| 5077 pushInvokeStatic(node, function, inputs); | 5198 pushInvokeStatic(node, function, inputs, |
| 5199 sourceInformation: sourceInformationBuilder.buildCall( |
| 5200 node, node.selector)); |
| 5078 } | 5201 } |
| 5079 } | 5202 } |
| 5080 | 5203 |
| 5081 /// Generate an invocation to a static or top level function with the wrong | 5204 /// Generate an invocation to a static or top level function with the wrong |
| 5082 /// number of arguments. | 5205 /// number of arguments. |
| 5083 void generateStaticFunctionIncompatibleInvoke(ast.Send node, | 5206 void generateStaticFunctionIncompatibleInvoke(ast.Send node, |
| 5084 Element element) { | 5207 Element element) { |
| 5085 generateWrongArgumentCountError(node, element, node.arguments); | 5208 generateWrongArgumentCountError(node, element, node.arguments); |
| 5086 } | 5209 } |
| 5087 | 5210 |
| 5088 @override | 5211 @override |
| 5089 void visitStaticFieldInvoke( | 5212 void visitStaticFieldInvoke( |
| 5090 ast.Send node, | 5213 ast.Send node, |
| 5091 FieldElement field, | 5214 FieldElement field, |
| 5092 ast.NodeList arguments, | 5215 ast.NodeList arguments, |
| 5093 CallStructure callStructure, | 5216 CallStructure callStructure, |
| 5094 _) { | 5217 _) { |
| 5095 generateStaticFieldGet(node, field); | 5218 generateStaticFieldGet(node, field); |
| 5096 generateCallInvoke(node, pop()); | 5219 generateCallInvoke( |
| 5220 node, |
| 5221 pop(), |
| 5222 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 5097 } | 5223 } |
| 5098 | 5224 |
| 5099 @override | 5225 @override |
| 5100 void visitStaticFunctionInvoke( | 5226 void visitStaticFunctionInvoke( |
| 5101 ast.Send node, | 5227 ast.Send node, |
| 5102 MethodElement function, | 5228 MethodElement function, |
| 5103 ast.NodeList arguments, | 5229 ast.NodeList arguments, |
| 5104 CallStructure callStructure, | 5230 CallStructure callStructure, |
| 5105 _) { | 5231 _) { |
| 5106 generateStaticFunctionInvoke(node, function, callStructure); | 5232 generateStaticFunctionInvoke(node, function, callStructure); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5117 } | 5243 } |
| 5118 | 5244 |
| 5119 @override | 5245 @override |
| 5120 void visitStaticGetterInvoke( | 5246 void visitStaticGetterInvoke( |
| 5121 ast.Send node, | 5247 ast.Send node, |
| 5122 FunctionElement getter, | 5248 FunctionElement getter, |
| 5123 ast.NodeList arguments, | 5249 ast.NodeList arguments, |
| 5124 CallStructure callStructure, | 5250 CallStructure callStructure, |
| 5125 _) { | 5251 _) { |
| 5126 generateStaticGetterGet(node, getter); | 5252 generateStaticGetterGet(node, getter); |
| 5127 generateCallInvoke(node, pop()); | 5253 generateCallInvoke( |
| 5254 node, |
| 5255 pop(), |
| 5256 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 5128 } | 5257 } |
| 5129 | 5258 |
| 5130 @override | 5259 @override |
| 5131 void visitTopLevelFieldInvoke( | 5260 void visitTopLevelFieldInvoke( |
| 5132 ast.Send node, | 5261 ast.Send node, |
| 5133 FieldElement field, | 5262 FieldElement field, |
| 5134 ast.NodeList arguments, | 5263 ast.NodeList arguments, |
| 5135 CallStructure callStructure, | 5264 CallStructure callStructure, |
| 5136 _) { | 5265 _) { |
| 5137 generateStaticFieldGet(node, field); | 5266 generateStaticFieldGet(node, field); |
| 5138 generateCallInvoke(node, pop()); | 5267 generateCallInvoke( |
| 5268 node, |
| 5269 pop(), |
| 5270 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 5139 } | 5271 } |
| 5140 | 5272 |
| 5141 @override | 5273 @override |
| 5142 void visitTopLevelFunctionInvoke( | 5274 void visitTopLevelFunctionInvoke( |
| 5143 ast.Send node, | 5275 ast.Send node, |
| 5144 MethodElement function, | 5276 MethodElement function, |
| 5145 ast.NodeList arguments, | 5277 ast.NodeList arguments, |
| 5146 CallStructure callStructure, | 5278 CallStructure callStructure, |
| 5147 _) { | 5279 _) { |
| 5148 if (backend.isForeign(function)) { | 5280 if (backend.isForeign(function)) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5163 } | 5295 } |
| 5164 | 5296 |
| 5165 @override | 5297 @override |
| 5166 void visitTopLevelGetterInvoke( | 5298 void visitTopLevelGetterInvoke( |
| 5167 ast.Send node, | 5299 ast.Send node, |
| 5168 FunctionElement getter, | 5300 FunctionElement getter, |
| 5169 ast.NodeList arguments, | 5301 ast.NodeList arguments, |
| 5170 CallStructure callStructure, | 5302 CallStructure callStructure, |
| 5171 _) { | 5303 _) { |
| 5172 generateStaticGetterGet(node, getter); | 5304 generateStaticGetterGet(node, getter); |
| 5173 generateCallInvoke(node, pop()); | 5305 generateCallInvoke( |
| 5306 node, |
| 5307 pop(), |
| 5308 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 5174 } | 5309 } |
| 5175 | 5310 |
| 5176 @override | 5311 @override |
| 5177 void visitTopLevelSetterGet( | 5312 void visitTopLevelSetterGet( |
| 5178 ast.Send node, | 5313 ast.Send node, |
| 5179 MethodElement setter, | 5314 MethodElement setter, |
| 5180 _) { | 5315 _) { |
| 5181 handleInvalidStaticGet(node, setter); | 5316 handleInvalidStaticGet(node, setter); |
| 5182 } | 5317 } |
| 5183 | 5318 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5328 stack.add(addConstant(node.selector)); | 5463 stack.add(addConstant(node.selector)); |
| 5329 } else { | 5464 } else { |
| 5330 stack.add(addConstant(node)); | 5465 stack.add(addConstant(node)); |
| 5331 } | 5466 } |
| 5332 } | 5467 } |
| 5333 | 5468 |
| 5334 /// Generate the literal for [typeVariable] in the current context. | 5469 /// Generate the literal for [typeVariable] in the current context. |
| 5335 void generateTypeVariableLiteral(ast.Send node, | 5470 void generateTypeVariableLiteral(ast.Send node, |
| 5336 TypeVariableType typeVariable) { | 5471 TypeVariableType typeVariable) { |
| 5337 DartType type = localsHandler.substInContext(typeVariable); | 5472 DartType type = localsHandler.substInContext(typeVariable); |
| 5338 HInstruction value = analyzeTypeArgument(type); | 5473 HInstruction value = analyzeTypeArgument(type, |
| 5474 sourceInformation: sourceInformationBuilder.buildGet(node)); |
| 5339 pushInvokeStatic(node, | 5475 pushInvokeStatic(node, |
| 5340 backend.getRuntimeTypeToString(), | 5476 backend.getRuntimeTypeToString(), |
| 5341 [value], | 5477 [value], |
| 5342 typeMask: backend.stringType); | 5478 typeMask: backend.stringType); |
| 5343 pushInvokeStatic(node, | 5479 pushInvokeStatic(node, |
| 5344 backend.getCreateRuntimeType(), | 5480 backend.getCreateRuntimeType(), |
| 5345 [pop()]); | 5481 [pop()]); |
| 5346 } | 5482 } |
| 5347 | 5483 |
| 5348 /// Generate a call to a type literal. | 5484 /// Generate a call to a type literal. |
| 5349 void generateTypeLiteralCall(ast.Send node) { | 5485 void generateTypeLiteralCall(ast.Send node) { |
| 5350 // This send is of the form 'e(...)', where e is resolved to a type | 5486 // This send is of the form 'e(...)', where e is resolved to a type |
| 5351 // reference. We create a regular closure call on the result of the type | 5487 // reference. We create a regular closure call on the result of the type |
| 5352 // reference instead of creating a NoSuchMethodError to avoid pulling it | 5488 // reference instead of creating a NoSuchMethodError to avoid pulling it |
| 5353 // in if it is not used (e.g., in a try/catch). | 5489 // in if it is not used (e.g., in a try/catch). |
| 5354 HInstruction target = pop(); | 5490 HInstruction target = pop(); |
| 5355 generateCallInvoke(node, target); | 5491 generateCallInvoke(node, target, |
| 5492 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 5356 } | 5493 } |
| 5357 | 5494 |
| 5358 /// Generate a '.call' invocation on [target]. | 5495 /// Generate a '.call' invocation on [target]. |
| 5359 void generateCallInvoke(ast.Send node, HInstruction target) { | 5496 void generateCallInvoke(ast.Send node, |
| 5497 HInstruction target, |
| 5498 SourceInformation sourceInformation) { |
| 5360 Selector selector = elements.getSelector(node); | 5499 Selector selector = elements.getSelector(node); |
| 5361 List<HInstruction> inputs = <HInstruction>[target]; | 5500 List<HInstruction> inputs = <HInstruction>[target]; |
| 5362 addDynamicSendArgumentsToList(node, inputs); | 5501 addDynamicSendArgumentsToList(node, inputs); |
| 5363 pushWithPosition( | 5502 push(new HInvokeClosure( |
| 5364 new HInvokeClosure( | |
| 5365 new Selector.callClosureFrom(selector), | 5503 new Selector.callClosureFrom(selector), |
| 5366 inputs, backend.dynamicType), | 5504 inputs, backend.dynamicType) |
| 5367 node); | 5505 ..sourceInformation = sourceInformation); |
| 5368 } | 5506 } |
| 5369 | 5507 |
| 5370 visitGetterSend(ast.Send node) { | 5508 visitGetterSend(ast.Send node) { |
| 5371 internalError(node, "Unexpected visitGetterSend"); | 5509 internalError(node, "Unexpected visitGetterSend"); |
| 5372 } | 5510 } |
| 5373 | 5511 |
| 5374 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. | 5512 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. |
| 5375 internalError(Spannable node, String reason) { | 5513 internalError(Spannable node, String reason) { |
| 5376 compiler.internalError(node, reason); | 5514 compiler.internalError(node, reason); |
| 5377 } | 5515 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5392 void generateAbstractClassInstantiationError(ast.Node node, String message) { | 5530 void generateAbstractClassInstantiationError(ast.Node node, String message) { |
| 5393 generateError(node, | 5531 generateError(node, |
| 5394 message, | 5532 message, |
| 5395 backend.getThrowAbstractClassInstantiationError()); | 5533 backend.getThrowAbstractClassInstantiationError()); |
| 5396 } | 5534 } |
| 5397 | 5535 |
| 5398 void generateThrowNoSuchMethod(ast.Node diagnosticNode, | 5536 void generateThrowNoSuchMethod(ast.Node diagnosticNode, |
| 5399 String methodName, | 5537 String methodName, |
| 5400 {Link<ast.Node> argumentNodes, | 5538 {Link<ast.Node> argumentNodes, |
| 5401 List<HInstruction> argumentValues, | 5539 List<HInstruction> argumentValues, |
| 5402 List<String> existingArguments}) { | 5540 List<String> existingArguments, |
| 5541 SourceInformation sourceInformation}) { |
| 5403 Element helper = backend.getThrowNoSuchMethod(); | 5542 Element helper = backend.getThrowNoSuchMethod(); |
| 5404 ConstantValue receiverConstant = | 5543 ConstantValue receiverConstant = |
| 5405 constantSystem.createString(new ast.DartString.empty()); | 5544 constantSystem.createString(new ast.DartString.empty()); |
| 5406 HInstruction receiver = graph.addConstant(receiverConstant, compiler); | 5545 HInstruction receiver = graph.addConstant(receiverConstant, compiler); |
| 5407 ast.DartString dartString = new ast.DartString.literal(methodName); | 5546 ast.DartString dartString = new ast.DartString.literal(methodName); |
| 5408 ConstantValue nameConstant = constantSystem.createString(dartString); | 5547 ConstantValue nameConstant = constantSystem.createString(dartString); |
| 5409 HInstruction name = graph.addConstant(nameConstant, compiler); | 5548 HInstruction name = graph.addConstant(nameConstant, compiler); |
| 5410 if (argumentValues == null) { | 5549 if (argumentValues == null) { |
| 5411 argumentValues = <HInstruction>[]; | 5550 argumentValues = <HInstruction>[]; |
| 5412 argumentNodes.forEach((argumentNode) { | 5551 argumentNodes.forEach((argumentNode) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5425 graph.addConstantString(new ast.DartString.literal(name), compiler); | 5564 graph.addConstantString(new ast.DartString.literal(name), compiler); |
| 5426 existingNames.add(nameConstant); | 5565 existingNames.add(nameConstant); |
| 5427 } | 5566 } |
| 5428 existingNamesList = buildLiteralList(existingNames); | 5567 existingNamesList = buildLiteralList(existingNames); |
| 5429 add(existingNamesList); | 5568 add(existingNamesList); |
| 5430 } else { | 5569 } else { |
| 5431 existingNamesList = graph.addConstantNull(compiler); | 5570 existingNamesList = graph.addConstantNull(compiler); |
| 5432 } | 5571 } |
| 5433 pushInvokeStatic(diagnosticNode, | 5572 pushInvokeStatic(diagnosticNode, |
| 5434 helper, | 5573 helper, |
| 5435 [receiver, name, arguments, existingNamesList]); | 5574 [receiver, name, arguments, existingNamesList], |
| 5575 sourceInformation: sourceInformation); |
| 5436 } | 5576 } |
| 5437 | 5577 |
| 5438 /** | 5578 /** |
| 5439 * Generate code to throw a [NoSuchMethodError] exception for calling a | 5579 * Generate code to throw a [NoSuchMethodError] exception for calling a |
| 5440 * method with a wrong number of arguments or mismatching named optional | 5580 * method with a wrong number of arguments or mismatching named optional |
| 5441 * arguments. | 5581 * arguments. |
| 5442 */ | 5582 */ |
| 5443 void generateWrongArgumentCountError(ast.Node diagnosticNode, | 5583 void generateWrongArgumentCountError(ast.Node diagnosticNode, |
| 5444 FunctionElement function, | 5584 FunctionElement function, |
| 5445 Link<ast.Node> argumentNodes) { | 5585 Link<ast.Node> argumentNodes) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5504 ast.NodeList arguments, | 5644 ast.NodeList arguments, |
| 5505 CallStructure callStructure, | 5645 CallStructure callStructure, |
| 5506 _) { | 5646 _) { |
| 5507 bulkHandleNew(node); | 5647 bulkHandleNew(node); |
| 5508 } | 5648 } |
| 5509 | 5649 |
| 5510 void pushInvokeDynamic(ast.Node node, | 5650 void pushInvokeDynamic(ast.Node node, |
| 5511 Selector selector, | 5651 Selector selector, |
| 5512 TypeMask mask, | 5652 TypeMask mask, |
| 5513 List<HInstruction> arguments, | 5653 List<HInstruction> arguments, |
| 5514 {ast.Node location}) { | 5654 {SourceInformation sourceInformation}) { |
| 5515 if (location == null) location = node; | |
| 5516 | 5655 |
| 5517 // We prefer to not inline certain operations on indexables, | 5656 // We prefer to not inline certain operations on indexables, |
| 5518 // because the constant folder will handle them better and turn | 5657 // because the constant folder will handle them better and turn |
| 5519 // them into simpler instructions that allow further | 5658 // them into simpler instructions that allow further |
| 5520 // optimizations. | 5659 // optimizations. |
| 5521 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { | 5660 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { |
| 5522 bool isLength = selector.isGetter | 5661 bool isLength = selector.isGetter |
| 5523 && selector.name == "length"; | 5662 && selector.name == "length"; |
| 5524 if (isLength || selector.isIndex) { | 5663 if (isLength || selector.isIndex) { |
| 5525 TypeMask type = new TypeMask.nonNullExact( | 5664 TypeMask type = new TypeMask.nonNullExact( |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5564 HInstruction receiver = arguments[0]; | 5703 HInstruction receiver = arguments[0]; |
| 5565 List<HInstruction> inputs = <HInstruction>[]; | 5704 List<HInstruction> inputs = <HInstruction>[]; |
| 5566 bool isIntercepted = backend.isInterceptedSelector(selector); | 5705 bool isIntercepted = backend.isInterceptedSelector(selector); |
| 5567 if (isIntercepted) { | 5706 if (isIntercepted) { |
| 5568 inputs.add(invokeInterceptor(receiver)); | 5707 inputs.add(invokeInterceptor(receiver)); |
| 5569 } | 5708 } |
| 5570 inputs.addAll(arguments); | 5709 inputs.addAll(arguments); |
| 5571 TypeMask type = | 5710 TypeMask type = |
| 5572 TypeMaskFactory.inferredTypeForSelector(selector, mask, compiler); | 5711 TypeMaskFactory.inferredTypeForSelector(selector, mask, compiler); |
| 5573 if (selector.isGetter) { | 5712 if (selector.isGetter) { |
| 5574 pushWithPosition( | 5713 push( |
| 5575 new HInvokeDynamicGetter(selector, mask, null, inputs, type), | 5714 new HInvokeDynamicGetter(selector, mask, null, inputs, type) |
| 5576 location); | 5715 ..sourceInformation = sourceInformation); |
| 5577 } else if (selector.isSetter) { | 5716 } else if (selector.isSetter) { |
| 5578 pushWithPosition( | 5717 push( |
| 5579 new HInvokeDynamicSetter(selector, mask, null, inputs, type), | 5718 new HInvokeDynamicSetter(selector, mask, null, inputs, type) |
| 5580 location); | 5719 ..sourceInformation = sourceInformation); |
| 5581 } else { | 5720 } else { |
| 5582 pushWithPosition( | 5721 push( |
| 5583 new HInvokeDynamicMethod(selector, mask, inputs, type, isIntercepted), | 5722 new HInvokeDynamicMethod(selector, mask, inputs, type, isIntercepted) |
| 5584 location); | 5723 ..sourceInformation = sourceInformation); |
| 5585 } | 5724 } |
| 5586 } | 5725 } |
| 5587 | 5726 |
| 5588 void pushInvokeStatic(ast.Node location, | 5727 void pushInvokeStatic(ast.Node location, |
| 5589 Element element, | 5728 Element element, |
| 5590 List<HInstruction> arguments, | 5729 List<HInstruction> arguments, |
| 5591 {TypeMask typeMask, | 5730 {TypeMask typeMask, |
| 5592 InterfaceType instanceType}) { | 5731 InterfaceType instanceType, |
| 5732 SourceInformation sourceInformation}) { |
| 5733 // TODO(johnniwinther): Use [sourceInformation] instead of [location]. |
| 5593 if (tryInlineMethod(element, null, null, arguments, location, | 5734 if (tryInlineMethod(element, null, null, arguments, location, |
| 5594 instanceType: instanceType)) { | 5735 instanceType: instanceType)) { |
| 5595 return; | 5736 return; |
| 5596 } | 5737 } |
| 5597 | 5738 |
| 5598 if (typeMask == null) { | 5739 if (typeMask == null) { |
| 5599 typeMask = | 5740 typeMask = |
| 5600 TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 5741 TypeMaskFactory.inferredReturnTypeForElement(element, compiler); |
| 5601 } | 5742 } |
| 5602 bool targetCanThrow = !compiler.world.getCannotThrow(element); | 5743 bool targetCanThrow = !compiler.world.getCannotThrow(element); |
| 5603 // TODO(5346): Try to avoid the need for calling [declaration] before | 5744 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 5604 // creating an [HInvokeStatic]. | 5745 // creating an [HInvokeStatic]. |
| 5605 HInvokeStatic instruction = new HInvokeStatic( | 5746 HInvokeStatic instruction = new HInvokeStatic( |
| 5606 element.declaration, arguments, typeMask, | 5747 element.declaration, arguments, typeMask, |
| 5607 targetCanThrow: targetCanThrow); | 5748 targetCanThrow: targetCanThrow) |
| 5749 ..sourceInformation = sourceInformation; |
| 5608 if (!currentInlinedInstantiations.isEmpty) { | 5750 if (!currentInlinedInstantiations.isEmpty) { |
| 5609 instruction.instantiatedTypes = new List<DartType>.from( | 5751 instruction.instantiatedTypes = new List<DartType>.from( |
| 5610 currentInlinedInstantiations); | 5752 currentInlinedInstantiations); |
| 5611 } | 5753 } |
| 5612 instruction.sideEffects = compiler.world.getSideEffectsOfElement(element); | 5754 instruction.sideEffects = compiler.world.getSideEffectsOfElement(element); |
| 5613 if (location == null) { | 5755 if (location == null) { |
| 5614 push(instruction); | 5756 push(instruction); |
| 5615 } else { | 5757 } else { |
| 5616 pushWithPosition(instruction, location); | 5758 pushWithPosition(instruction, location); |
| 5617 } | 5759 } |
| 5618 } | 5760 } |
| 5619 | 5761 |
| 5620 HInstruction buildInvokeSuper(Selector selector, | 5762 HInstruction buildInvokeSuper(Selector selector, |
| 5621 Element element, | 5763 Element element, |
| 5622 List<HInstruction> arguments) { | 5764 List<HInstruction> arguments, |
| 5765 [SourceInformation sourceInformation]) { |
| 5623 HInstruction receiver = localsHandler.readThis(); | 5766 HInstruction receiver = localsHandler.readThis(); |
| 5624 // TODO(5346): Try to avoid the need for calling [declaration] before | 5767 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 5625 // creating an [HStatic]. | 5768 // creating an [HStatic]. |
| 5626 List<HInstruction> inputs = <HInstruction>[]; | 5769 List<HInstruction> inputs = <HInstruction>[]; |
| 5627 if (backend.isInterceptedSelector(selector) && | 5770 if (backend.isInterceptedSelector(selector) && |
| 5628 // Fields don't need an interceptor; consider generating HFieldGet/Set | 5771 // Fields don't need an interceptor; consider generating HFieldGet/Set |
| 5629 // instead. | 5772 // instead. |
| 5630 element.kind != ElementKind.FIELD) { | 5773 element.kind != ElementKind.FIELD) { |
| 5631 inputs.add(invokeInterceptor(receiver)); | 5774 inputs.add(invokeInterceptor(receiver)); |
| 5632 } | 5775 } |
| 5633 inputs.add(receiver); | 5776 inputs.add(receiver); |
| 5634 inputs.addAll(arguments); | 5777 inputs.addAll(arguments); |
| 5635 TypeMask type; | 5778 TypeMask type; |
| 5636 if (!element.isGetter && selector.isGetter) { | 5779 if (!element.isGetter && selector.isGetter) { |
| 5637 type = TypeMaskFactory.inferredTypeForElement(element, compiler); | 5780 type = TypeMaskFactory.inferredTypeForElement(element, compiler); |
| 5638 } else { | 5781 } else { |
| 5639 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 5782 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); |
| 5640 } | 5783 } |
| 5641 HInstruction instruction = new HInvokeSuper( | 5784 HInstruction instruction = new HInvokeSuper( |
| 5642 element, | 5785 element, |
| 5643 currentNonClosureClass, | 5786 currentNonClosureClass, |
| 5644 selector, | 5787 selector, |
| 5645 inputs, | 5788 inputs, |
| 5646 type, | 5789 type, |
| 5790 sourceInformation, |
| 5647 isSetter: selector.isSetter || selector.isIndexSet); | 5791 isSetter: selector.isSetter || selector.isIndexSet); |
| 5648 instruction.sideEffects = | 5792 instruction.sideEffects = |
| 5649 compiler.world.getSideEffectsOfSelector(selector, null); | 5793 compiler.world.getSideEffectsOfSelector(selector, null); |
| 5650 return instruction; | 5794 return instruction; |
| 5651 } | 5795 } |
| 5652 | 5796 |
| 5653 void handleComplexOperatorSend(ast.SendSet node, | 5797 void handleComplexOperatorSend(ast.SendSet node, |
| 5654 HInstruction receiver, | 5798 HInstruction receiver, |
| 5655 Link<ast.Node> arguments) { | 5799 Link<ast.Node> arguments) { |
| 5656 HInstruction rhs; | 5800 HInstruction rhs; |
| 5657 if (node.isPrefix || node.isPostfix) { | 5801 if (node.isPrefix || node.isPostfix) { |
| 5658 rhs = graph.addConstantInt(1, compiler); | 5802 rhs = graph.addConstantInt(1, compiler); |
| 5659 } else { | 5803 } else { |
| 5660 visit(arguments.head); | 5804 visit(arguments.head); |
| 5661 assert(arguments.tail.isEmpty); | 5805 assert(arguments.tail.isEmpty); |
| 5662 rhs = pop(); | 5806 rhs = pop(); |
| 5663 } | 5807 } |
| 5664 visitBinarySend(receiver, rhs, | 5808 visitBinarySend( |
| 5665 elements.getOperatorSelectorInComplexSendSet(node), | 5809 receiver, |
| 5666 elements.getOperatorTypeMaskInComplexSendSet(node), | 5810 rhs, |
| 5667 node, | 5811 elements.getOperatorSelectorInComplexSendSet(node), |
| 5668 location: node.assignmentOperator); | 5812 elements.getOperatorTypeMaskInComplexSendSet(node), |
| 5813 node, |
| 5814 sourceInformation: |
| 5815 sourceInformationBuilder.buildGeneric(node.assignmentOperator)); |
| 5669 } | 5816 } |
| 5670 | 5817 |
| 5671 void handleSuperSendSet(ast.SendSet node) { | 5818 void handleSuperSendSet(ast.SendSet node) { |
| 5672 Element element = elements[node]; | 5819 Element element = elements[node]; |
| 5673 List<HInstruction> setterInputs = <HInstruction>[]; | 5820 List<HInstruction> setterInputs = <HInstruction>[]; |
| 5674 void generateSuperSendSet() { | 5821 void generateSuperSendSet() { |
| 5675 Selector setterSelector = elements.getSelector(node); | 5822 Selector setterSelector = elements.getSelector(node); |
| 5676 if (Elements.isUnresolved(element) | 5823 if (Elements.isUnresolved(element) |
| 5677 || !setterSelector.applies(element, compiler.world)) { | 5824 || !setterSelector.applies(element, compiler.world)) { |
| 5678 generateSuperNoSuchMethodSend( | 5825 generateSuperNoSuchMethodSend( |
| (...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6518 | 6665 |
| 6519 if (getter.isErroneous) { | 6666 if (getter.isErroneous) { |
| 6520 generateStaticUnresolvedGet(node, getter); | 6667 generateStaticUnresolvedGet(node, getter); |
| 6521 } else if (getter.isField) { | 6668 } else if (getter.isField) { |
| 6522 generateStaticFieldGet(node, getter); | 6669 generateStaticFieldGet(node, getter); |
| 6523 } else if (getter.isGetter) { | 6670 } else if (getter.isGetter) { |
| 6524 generateStaticGetterGet(node, getter); | 6671 generateStaticGetterGet(node, getter); |
| 6525 } else if (getter.isFunction) { | 6672 } else if (getter.isFunction) { |
| 6526 generateStaticFunctionGet(node, getter); | 6673 generateStaticFunctionGet(node, getter); |
| 6527 } else if (getter.isLocal) { | 6674 } else if (getter.isLocal) { |
| 6528 handleLocalGet(getter); | 6675 handleLocalGet(node, getter); |
| 6529 } else { | 6676 } else { |
| 6530 internalError(node, "Unexpected getter: $getter"); | 6677 internalError(node, "Unexpected getter: $getter"); |
| 6531 } | 6678 } |
| 6532 HInstruction getterInstruction = pop(); | 6679 HInstruction getterInstruction = pop(); |
| 6533 if (node.isIfNullAssignment) { | 6680 if (node.isIfNullAssignment) { |
| 6534 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 6681 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 6535 brancher.handleIfNull(() => stack.add(getterInstruction), | 6682 brancher.handleIfNull(() => stack.add(getterInstruction), |
| 6536 () { | 6683 () { |
| 6537 visit(node.arguments.head); | 6684 visit(node.arguments.head); |
| 6538 generateNonInstanceSetter(node, element, pop()); | 6685 generateNonInstanceSetter(node, element, pop()); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6658 } | 6805 } |
| 6659 | 6806 |
| 6660 visitRethrow(ast.Rethrow node) { | 6807 visitRethrow(ast.Rethrow node) { |
| 6661 HInstruction exception = rethrowableException; | 6808 HInstruction exception = rethrowableException; |
| 6662 if (exception == null) { | 6809 if (exception == null) { |
| 6663 exception = graph.addConstantNull(compiler); | 6810 exception = graph.addConstantNull(compiler); |
| 6664 compiler.internalError(node, | 6811 compiler.internalError(node, |
| 6665 'rethrowableException should not be null.'); | 6812 'rethrowableException should not be null.'); |
| 6666 } | 6813 } |
| 6667 handleInTryStatement(); | 6814 handleInTryStatement(); |
| 6668 closeAndGotoExit(new HThrow(exception, isRethrow: true)); | 6815 closeAndGotoExit( |
| 6816 new HThrow(exception, |
| 6817 sourceInformationBuilder.buildThrow(node), |
| 6818 isRethrow: true)); |
| 6669 } | 6819 } |
| 6670 | 6820 |
| 6671 visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { | 6821 visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { |
| 6672 ConstructorElement targetConstructor = | 6822 ConstructorElement targetConstructor = |
| 6673 elements.getRedirectingTargetConstructor(node).implementation; | 6823 elements.getRedirectingTargetConstructor(node).implementation; |
| 6674 ConstructorElement redirectingConstructor = sourceElement.implementation; | 6824 ConstructorElement redirectingConstructor = sourceElement.implementation; |
| 6675 List<HInstruction> inputs = <HInstruction>[]; | 6825 List<HInstruction> inputs = <HInstruction>[]; |
| 6676 FunctionSignature targetSignature = targetConstructor.functionSignature; | 6826 FunctionSignature targetSignature = targetConstructor.functionSignature; |
| 6677 FunctionSignature redirectingSignature = | 6827 FunctionSignature redirectingSignature = |
| 6678 redirectingConstructor.functionSignature; | 6828 redirectingConstructor.functionSignature; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6755 } | 6905 } |
| 6756 | 6906 |
| 6757 handleInTryStatement(); | 6907 handleInTryStatement(); |
| 6758 emitReturn(value, node); | 6908 emitReturn(value, node); |
| 6759 } | 6909 } |
| 6760 | 6910 |
| 6761 visitThrow(ast.Throw node) { | 6911 visitThrow(ast.Throw node) { |
| 6762 visitThrowExpression(node.expression); | 6912 visitThrowExpression(node.expression); |
| 6763 if (isReachable) { | 6913 if (isReachable) { |
| 6764 handleInTryStatement(); | 6914 handleInTryStatement(); |
| 6765 push(new HThrowExpression(pop())); | 6915 push(new HThrowExpression( |
| 6916 pop(), sourceInformationBuilder.buildThrow(node))); |
| 6766 isReachable = false; | 6917 isReachable = false; |
| 6767 } | 6918 } |
| 6768 } | 6919 } |
| 6769 | 6920 |
| 6770 visitYield(ast.Yield node) { | 6921 visitYield(ast.Yield node) { |
| 6771 visit(node.expression); | 6922 visit(node.expression); |
| 6772 HInstruction yielded = pop(); | 6923 HInstruction yielded = pop(); |
| 6773 add(new HYield(yielded, node.hasStar)); | 6924 add(new HYield(yielded, node.hasStar)); |
| 6774 } | 6925 } |
| 6775 | 6926 |
| (...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7529 // If the switch statement has no default case, surround the loop with | 7680 // If the switch statement has no default case, surround the loop with |
| 7530 // a test of the target. | 7681 // a test of the target. |
| 7531 void buildCondition() { | 7682 void buildCondition() { |
| 7532 js.Template code = js.js.parseForeignJS('#'); | 7683 js.Template code = js.js.parseForeignJS('#'); |
| 7533 push(new HForeignCode( | 7684 push(new HForeignCode( |
| 7534 code, | 7685 code, |
| 7535 backend.boolType, | 7686 backend.boolType, |
| 7536 [localsHandler.readLocal(switchTarget)], | 7687 [localsHandler.readLocal(switchTarget)], |
| 7537 nativeBehavior: native.NativeBehavior.PURE)); | 7688 nativeBehavior: native.NativeBehavior.PURE)); |
| 7538 } | 7689 } |
| 7539 handleIf(node, buildCondition, buildLoop, () => {}); | 7690 handleIf(node, |
| 7691 visitCondition: buildCondition, |
| 7692 visitThen: buildLoop, |
| 7693 visitElse: () => {}); |
| 7540 } | 7694 } |
| 7541 } | 7695 } |
| 7542 | 7696 |
| 7543 /** | 7697 /** |
| 7544 * Creates a switch statement. | 7698 * Creates a switch statement. |
| 7545 * | 7699 * |
| 7546 * [jumpHandler] is the [JumpHandler] for the created switch statement. | 7700 * [jumpHandler] is the [JumpHandler] for the created switch statement. |
| 7547 * [buildExpression] creates the switch expression. | 7701 * [buildExpression] creates the switch expression. |
| 7548 * [switchCases] must be either an [Iterable] of [ast.SwitchCase] nodes or | 7702 * [switchCases] must be either an [Iterable] of [ast.SwitchCase] nodes or |
| 7549 * a [Link] or a [ast.NodeList] of [ast.SwitchCase] nodes. | 7703 * a [Link] or a [ast.NodeList] of [ast.SwitchCase] nodes. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7592 expressionEnd.addSuccessor(block); | 7746 expressionEnd.addSuccessor(block); |
| 7593 hasDefault = true; | 7747 hasDefault = true; |
| 7594 } | 7748 } |
| 7595 open(block); | 7749 open(block); |
| 7596 localsHandler = new LocalsHandler.from(savedLocals); | 7750 localsHandler = new LocalsHandler.from(savedLocals); |
| 7597 buildSwitchCase(switchCase); | 7751 buildSwitchCase(switchCase); |
| 7598 if (!isAborted()) { | 7752 if (!isAborted()) { |
| 7599 if (caseIterator.hasNext) { | 7753 if (caseIterator.hasNext) { |
| 7600 pushInvokeStatic(switchCase, getFallThroughErrorElement, []); | 7754 pushInvokeStatic(switchCase, getFallThroughErrorElement, []); |
| 7601 HInstruction error = pop(); | 7755 HInstruction error = pop(); |
| 7602 closeAndGotoExit(new HThrow(error)); | 7756 closeAndGotoExit(new HThrow(error, error.sourceInformation)); |
| 7603 } else if (!isDefaultCase(switchCase)) { | 7757 } else if (!isDefaultCase(switchCase)) { |
| 7604 // If there is no default, we will add one later to avoid | 7758 // If there is no default, we will add one later to avoid |
| 7605 // the critical edge. So we generate a break statement to make | 7759 // the critical edge. So we generate a break statement to make |
| 7606 // sure the last case does not fall through to the default case. | 7760 // sure the last case does not fall through to the default case. |
| 7607 jumpHandler.generateBreak(); | 7761 jumpHandler.generateBreak(); |
| 7608 } | 7762 } |
| 7609 } | 7763 } |
| 7610 statements.add( | 7764 statements.add( |
| 7611 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock))); | 7765 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock))); |
| 7612 } | 7766 } |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7868 pushInvokeStatic(trace, backend.getTraceFromException(), [exception]); | 8022 pushInvokeStatic(trace, backend.getTraceFromException(), [exception]); |
| 7869 HInstruction traceInstruction = pop(); | 8023 HInstruction traceInstruction = pop(); |
| 7870 LocalVariableElement traceVariable = elements[trace]; | 8024 LocalVariableElement traceVariable = elements[trace]; |
| 7871 localsHandler.updateLocal(traceVariable, traceInstruction); | 8025 localsHandler.updateLocal(traceVariable, traceInstruction); |
| 7872 } | 8026 } |
| 7873 visit(catchBlock); | 8027 visit(catchBlock); |
| 7874 } | 8028 } |
| 7875 | 8029 |
| 7876 void visitElse() { | 8030 void visitElse() { |
| 7877 if (link.isEmpty) { | 8031 if (link.isEmpty) { |
| 7878 closeAndGotoExit(new HThrow(exception, isRethrow: true)); | 8032 closeAndGotoExit( |
| 8033 new HThrow(exception, |
| 8034 exception.sourceInformation, |
| 8035 isRethrow: true)); |
| 7879 } else { | 8036 } else { |
| 7880 ast.CatchBlock newBlock = link.head; | 8037 ast.CatchBlock newBlock = link.head; |
| 7881 handleIf(node, | 8038 handleIf(node, |
| 7882 () { pushCondition(newBlock); }, | 8039 visitCondition: () { pushCondition(newBlock); }, |
| 7883 visitThen, visitElse); | 8040 visitThen: visitThen, |
| 8041 visitElse: visitElse); |
| 7884 } | 8042 } |
| 7885 } | 8043 } |
| 7886 | 8044 |
| 7887 ast.CatchBlock firstBlock = link.head; | 8045 ast.CatchBlock firstBlock = link.head; |
| 7888 handleIf(node, () { pushCondition(firstBlock); }, visitThen, visitElse); | 8046 handleIf(node, |
| 8047 visitCondition: () { pushCondition(firstBlock); }, |
| 8048 visitThen: visitThen, |
| 8049 visitElse: visitElse); |
| 7889 if (!isAborted()) endCatchBlock = close(new HGoto()); | 8050 if (!isAborted()) endCatchBlock = close(new HGoto()); |
| 7890 | 8051 |
| 7891 rethrowableException = oldRethrowableException; | 8052 rethrowableException = oldRethrowableException; |
| 7892 tryInstruction.catchBlock = startCatchBlock; | 8053 tryInstruction.catchBlock = startCatchBlock; |
| 7893 catchGraph = new SubGraph(startCatchBlock, lastOpenedBlock); | 8054 catchGraph = new SubGraph(startCatchBlock, lastOpenedBlock); |
| 7894 } | 8055 } |
| 7895 | 8056 |
| 7896 SubGraph finallyGraph = null; | 8057 SubGraph finallyGraph = null; |
| 7897 if (node.finallyBlock != null) { | 8058 if (node.finallyBlock != null) { |
| 7898 localsHandler = new LocalsHandler.from(savedLocals); | 8059 localsHandler = new LocalsHandler.from(savedLocals); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8009 restoreState(state); | 8170 restoreState(state); |
| 8010 stack.add(result); | 8171 stack.add(result); |
| 8011 } | 8172 } |
| 8012 | 8173 |
| 8013 void doInline(FunctionElement function) { | 8174 void doInline(FunctionElement function) { |
| 8014 visitInlinedFunction(function); | 8175 visitInlinedFunction(function); |
| 8015 } | 8176 } |
| 8016 | 8177 |
| 8017 void emitReturn(HInstruction value, ast.Node node) { | 8178 void emitReturn(HInstruction value, ast.Node node) { |
| 8018 if (inliningStack.isEmpty) { | 8179 if (inliningStack.isEmpty) { |
| 8019 closeAndGotoExit(attachPosition(new HReturn(value), node)); | 8180 closeAndGotoExit(new HReturn(value, |
| 8181 sourceInformationBuilder.buildReturn(node))); |
| 8020 } else { | 8182 } else { |
| 8021 localsHandler.updateLocal(returnLocal, value); | 8183 localsHandler.updateLocal(returnLocal, value); |
| 8022 } | 8184 } |
| 8023 } | 8185 } |
| 8024 | 8186 |
| 8025 @override | 8187 @override |
| 8026 void handleTypeLiteralConstantCompounds( | 8188 void handleTypeLiteralConstantCompounds( |
| 8027 ast.SendSet node, | 8189 ast.SendSet node, |
| 8028 ConstantExpression constant, | 8190 ConstantExpression constant, |
| 8029 CompoundRhs rhs, | 8191 CompoundRhs rhs, |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8368 | 8530 |
| 8369 void checkNotAborted() { | 8531 void checkNotAborted() { |
| 8370 if (builder.isAborted()) { | 8532 if (builder.isAborted()) { |
| 8371 compiler.unimplemented(diagnosticNode, "aborted control flow"); | 8533 compiler.unimplemented(diagnosticNode, "aborted control flow"); |
| 8372 } | 8534 } |
| 8373 } | 8535 } |
| 8374 | 8536 |
| 8375 void buildCondition(void visitCondition(), | 8537 void buildCondition(void visitCondition(), |
| 8376 SsaBranch conditionBranch, | 8538 SsaBranch conditionBranch, |
| 8377 SsaBranch thenBranch, | 8539 SsaBranch thenBranch, |
| 8378 SsaBranch elseBranch) { | 8540 SsaBranch elseBranch, |
| 8541 SourceInformation sourceInformation) { |
| 8379 startBranch(conditionBranch); | 8542 startBranch(conditionBranch); |
| 8380 visitCondition(); | 8543 visitCondition(); |
| 8381 checkNotAborted(); | 8544 checkNotAborted(); |
| 8382 assert(identical(builder.current, builder.lastOpenedBlock)); | 8545 assert(identical(builder.current, builder.lastOpenedBlock)); |
| 8383 HInstruction conditionValue = builder.popBoolified(); | 8546 HInstruction conditionValue = builder.popBoolified(); |
| 8384 HIf branch = new HIf(conditionValue); | 8547 HIf branch = new HIf(conditionValue)..sourceInformation = sourceInformation; |
| 8385 HBasicBlock conditionExitBlock = builder.current; | 8548 HBasicBlock conditionExitBlock = builder.current; |
| 8386 builder.close(branch); | 8549 builder.close(branch); |
| 8387 conditionBranch.exitLocals = builder.localsHandler; | 8550 conditionBranch.exitLocals = builder.localsHandler; |
| 8388 conditionExitBlock.addSuccessor(thenBranch.block); | 8551 conditionExitBlock.addSuccessor(thenBranch.block); |
| 8389 conditionExitBlock.addSuccessor(elseBranch.block); | 8552 conditionExitBlock.addSuccessor(elseBranch.block); |
| 8390 bool conditionBranchLocalsCanBeReused = | 8553 bool conditionBranchLocalsCanBeReused = |
| 8391 mergeLocals(conditionBranch, thenBranch, mayReuseFromLocals: true); | 8554 mergeLocals(conditionBranch, thenBranch, mayReuseFromLocals: true); |
| 8392 mergeLocals(conditionBranch, elseBranch, | 8555 mergeLocals(conditionBranch, elseBranch, |
| 8393 mayReuseFromLocals: conditionBranchLocalsCanBeReused); | 8556 mayReuseFromLocals: conditionBranchLocalsCanBeReused); |
| 8394 | 8557 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8435 builder.goto(builder.current, joinBranch.block); | 8598 builder.goto(builder.current, joinBranch.block); |
| 8436 mergeLocals(branch, joinBranch, mayReuseFromLocals: true); | 8599 mergeLocals(branch, joinBranch, mayReuseFromLocals: true); |
| 8437 } | 8600 } |
| 8438 if (isExpression) { | 8601 if (isExpression) { |
| 8439 checkNotAborted(); | 8602 checkNotAborted(); |
| 8440 return builder.pop(); | 8603 return builder.pop(); |
| 8441 } | 8604 } |
| 8442 return null; | 8605 return null; |
| 8443 } | 8606 } |
| 8444 | 8607 |
| 8445 handleIf(void visitCondition(), void visitThen(), void visitElse()) { | 8608 handleIf(void visitCondition(), |
| 8609 void visitThen(), |
| 8610 void visitElse(), |
| 8611 {SourceInformation sourceInformation}) { |
| 8446 if (visitElse == null) { | 8612 if (visitElse == null) { |
| 8447 // Make sure to have an else part to avoid a critical edge. A | 8613 // Make sure to have an else part to avoid a critical edge. A |
| 8448 // critical edge is an edge that connects a block with multiple | 8614 // critical edge is an edge that connects a block with multiple |
| 8449 // successors to a block with multiple predecessors. We avoid | 8615 // successors to a block with multiple predecessors. We avoid |
| 8450 // such edges because they prevent inserting copies during code | 8616 // such edges because they prevent inserting copies during code |
| 8451 // generation of phi instructions. | 8617 // generation of phi instructions. |
| 8452 visitElse = () {}; | 8618 visitElse = () {}; |
| 8453 } | 8619 } |
| 8454 | 8620 |
| 8455 _handleDiamondBranch(visitCondition, visitThen, visitElse, false); | 8621 _handleDiamondBranch( |
| 8622 visitCondition, visitThen, visitElse, isExpression: false, |
| 8623 sourceInformation: sourceInformation); |
| 8456 } | 8624 } |
| 8457 | 8625 |
| 8458 handleConditional(void visitCondition(), void visitThen(), void visitElse()) { | 8626 handleConditional(void visitCondition(), |
| 8627 void visitThen(), |
| 8628 void visitElse()) { |
| 8459 assert(visitElse != null); | 8629 assert(visitElse != null); |
| 8460 _handleDiamondBranch(visitCondition, visitThen, visitElse, true); | 8630 _handleDiamondBranch( |
| 8631 visitCondition, visitThen, visitElse, isExpression: true); |
| 8461 } | 8632 } |
| 8462 | 8633 |
| 8463 handleIfNull(void left(), void right()) { | 8634 handleIfNull(void left(), void right()) { |
| 8464 // x ?? y is transformed into: x == null ? y : x | 8635 // x ?? y is transformed into: x == null ? y : x |
| 8465 HInstruction leftExpression; | 8636 HInstruction leftExpression; |
| 8466 handleConditional( | 8637 handleConditional( |
| 8467 () { | 8638 () { |
| 8468 left(); | 8639 left(); |
| 8469 leftExpression = builder.pop(); | 8640 leftExpression = builder.pop(); |
| 8470 builder.pushCheckNull(leftExpression); | 8641 builder.pushCheckNull(leftExpression); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8545 isAnd: isAnd), | 8716 isAnd: isAnd), |
| 8546 isAnd: isAnd); | 8717 isAnd: isAnd); |
| 8547 } else { | 8718 } else { |
| 8548 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd: isAnd); | 8719 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd: isAnd); |
| 8549 } | 8720 } |
| 8550 } | 8721 } |
| 8551 | 8722 |
| 8552 void _handleDiamondBranch(void visitCondition(), | 8723 void _handleDiamondBranch(void visitCondition(), |
| 8553 void visitThen(), | 8724 void visitThen(), |
| 8554 void visitElse(), | 8725 void visitElse(), |
| 8555 bool isExpression) { | 8726 {bool isExpression, |
| 8727 SourceInformation sourceInformation}) { |
| 8556 SsaBranch conditionBranch = new SsaBranch(this); | 8728 SsaBranch conditionBranch = new SsaBranch(this); |
| 8557 SsaBranch thenBranch = new SsaBranch(this); | 8729 SsaBranch thenBranch = new SsaBranch(this); |
| 8558 SsaBranch elseBranch = new SsaBranch(this); | 8730 SsaBranch elseBranch = new SsaBranch(this); |
| 8559 SsaBranch joinBranch = new SsaBranch(this); | 8731 SsaBranch joinBranch = new SsaBranch(this); |
| 8560 | 8732 |
| 8561 conditionBranch.startLocals = builder.localsHandler; | 8733 conditionBranch.startLocals = builder.localsHandler; |
| 8562 builder.goto(builder.current, conditionBranch.block); | 8734 builder.goto(builder.current, conditionBranch.block); |
| 8563 | 8735 |
| 8564 buildCondition(visitCondition, conditionBranch, thenBranch, elseBranch); | 8736 buildCondition(visitCondition, conditionBranch, thenBranch, elseBranch, |
| 8737 sourceInformation); |
| 8565 HInstruction thenValue = | 8738 HInstruction thenValue = |
| 8566 buildBranch(thenBranch, visitThen, joinBranch, isExpression); | 8739 buildBranch(thenBranch, visitThen, joinBranch, isExpression); |
| 8567 HInstruction elseValue = | 8740 HInstruction elseValue = |
| 8568 buildBranch(elseBranch, visitElse, joinBranch, isExpression); | 8741 buildBranch(elseBranch, visitElse, joinBranch, isExpression); |
| 8569 | 8742 |
| 8570 if (isExpression) { | 8743 if (isExpression) { |
| 8571 assert(thenValue != null && elseValue != null); | 8744 assert(thenValue != null && elseValue != null); |
| 8572 JavaScriptBackend backend = builder.backend; | 8745 JavaScriptBackend backend = builder.backend; |
| 8573 HPhi phi = new HPhi.manyInputs( | 8746 HPhi phi = new HPhi.manyInputs( |
| 8574 null, <HInstruction>[thenValue, elseValue], backend.dynamicType); | 8747 null, <HInstruction>[thenValue, elseValue], backend.dynamicType); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8684 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 8857 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 8685 unaliased.accept(this, builder); | 8858 unaliased.accept(this, builder); |
| 8686 } | 8859 } |
| 8687 | 8860 |
| 8688 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 8861 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 8689 JavaScriptBackend backend = builder.compiler.backend; | 8862 JavaScriptBackend backend = builder.compiler.backend; |
| 8690 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 8863 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 8691 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 8864 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 8692 } | 8865 } |
| 8693 } | 8866 } |
| OLD | NEW |