| 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 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1106 /// Returns `true` if the current element is an `async` function. | 1112 /// Returns `true` if the current element is an `async` function. |
| 1107 bool get isBuildingAsyncFunction { | 1113 bool get isBuildingAsyncFunction { |
| 1108 Element element = sourceElement; | 1114 Element element = sourceElement; |
| 1109 return (element is FunctionElement && | 1115 return (element is FunctionElement && |
| 1110 element.asyncMarker == AsyncMarker.ASYNC); | 1116 element.asyncMarker == AsyncMarker.ASYNC); |
| 1111 } | 1117 } |
| 1112 | 1118 |
| 1113 SsaBuilder(JavaScriptBackend backend, | 1119 SsaBuilder(JavaScriptBackend backend, |
| 1114 CodegenWorkItem work, | 1120 CodegenWorkItem work, |
| 1115 this.nativeEmitter, | 1121 this.nativeEmitter, |
| 1116 SourceInformationFactory sourceInformationFactory) | 1122 SourceInformationStrategy sourceInformationFactory) |
| 1117 : this.compiler = backend.compiler, | 1123 : this.compiler = backend.compiler, |
| 1118 this.backend = backend, | 1124 this.backend = backend, |
| 1119 this.constantSystem = backend.constantSystem, | 1125 this.constantSystem = backend.constantSystem, |
| 1120 this.work = work, | 1126 this.work = work, |
| 1121 this.rti = backend.rti, | 1127 this.rti = backend.rti, |
| 1122 super(work.resolutionTree) { | 1128 super(work.resolutionTree) { |
| 1123 localsHandler = new LocalsHandler(this, work.element, null); | 1129 localsHandler = new LocalsHandler(this, work.element, null); |
| 1124 sourceElementStack.add(work.element); | 1130 sourceElementStack.add(work.element); |
| 1125 sourceInformationBuilder = | 1131 sourceInformationBuilder = |
| 1126 sourceInformationFactory.forContext(work.element.implementation); | 1132 sourceInformationFactory.createBuilderForContext( |
| 1133 work.element.implementation); |
| 1127 } | 1134 } |
| 1128 | 1135 |
| 1129 CodegenRegistry get registry => work.registry; | 1136 CodegenRegistry get registry => work.registry; |
| 1130 | 1137 |
| 1131 /// Returns the current source element. | 1138 /// Returns the current source element. |
| 1132 /// | 1139 /// |
| 1133 /// The returned element is a declaration element. | 1140 /// The returned element is a declaration element. |
| 1134 // TODO(johnniwinther): Check that all usages of sourceElement agree on | 1141 // TODO(johnniwinther): Check that all usages of sourceElement agree on |
| 1135 // implementation/declaration distinction. | 1142 // implementation/declaration distinction. |
| 1136 Element get sourceElement => sourceElementStack.last; | 1143 Element get sourceElement => sourceElementStack.last; |
| (...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1605 assert(elements.getFunctionDefinition(function) != null); | 1612 assert(elements.getFunctionDefinition(function) != null); |
| 1606 openFunction(functionElement, function); | 1613 openFunction(functionElement, function); |
| 1607 String name = functionElement.name; | 1614 String name = functionElement.name; |
| 1608 // If [functionElement] is `operator==` we explicitely add a null check at | 1615 // If [functionElement] is `operator==` we explicitely add a null check at |
| 1609 // the beginning of the method. This is to avoid having call sites do the | 1616 // the beginning of the method. This is to avoid having call sites do the |
| 1610 // null check. | 1617 // null check. |
| 1611 if (name == '==') { | 1618 if (name == '==') { |
| 1612 if (!backend.operatorEqHandlesNullArgument(functionElement)) { | 1619 if (!backend.operatorEqHandlesNullArgument(functionElement)) { |
| 1613 handleIf( | 1620 handleIf( |
| 1614 function, | 1621 function, |
| 1615 () { | 1622 visitCondition: () { |
| 1616 HParameterValue parameter = parameters.values.first; | 1623 HParameterValue parameter = parameters.values.first; |
| 1617 push(new HIdentity( | 1624 push(new HIdentity( |
| 1618 parameter, graph.addConstantNull(compiler), null, | 1625 parameter, graph.addConstantNull(compiler), null, |
| 1619 backend.boolType)); | 1626 backend.boolType)); |
| 1620 }, | 1627 }, |
| 1621 () { | 1628 visitThen: () { |
| 1629 // TODO(johnniwinther): Add source information. |
| 1622 closeAndGotoExit(new HReturn( | 1630 closeAndGotoExit(new HReturn( |
| 1623 graph.addConstantBool(false, compiler))); | 1631 graph.addConstantBool(false, compiler), |
| 1632 null)); |
| 1624 }, | 1633 }, |
| 1625 null); | 1634 visitElse: null); |
| 1626 } | 1635 } |
| 1627 } | 1636 } |
| 1628 function.body.accept(this); | 1637 function.body.accept(this); |
| 1629 return closeFunction(); | 1638 return closeFunction(); |
| 1630 } | 1639 } |
| 1631 | 1640 |
| 1632 HGraph buildCheckedSetter(VariableElement field) { | 1641 HGraph buildCheckedSetter(VariableElement field) { |
| 1633 openFunction(field, field.node); | 1642 openFunction(field, field.node); |
| 1634 HInstruction thisInstruction = localsHandler.readThis(); | 1643 HInstruction thisInstruction = localsHandler.readThis(); |
| 1635 // Use dynamic type because the type computed by the inferrer is | 1644 // Use dynamic type because the type computed by the inferrer is |
| 1636 // narrowed to the type annotation. | 1645 // narrowed to the type annotation. |
| 1637 HInstruction parameter = new HParameterValue(field, backend.dynamicType); | 1646 HInstruction parameter = new HParameterValue(field, backend.dynamicType); |
| 1638 // Add the parameter as the last instruction of the entry block. | 1647 // Add the parameter as the last instruction of the entry block. |
| 1639 // If the method is intercepted, we want the actual receiver | 1648 // If the method is intercepted, we want the actual receiver |
| 1640 // to be the first parameter. | 1649 // to be the first parameter. |
| 1641 graph.entry.addBefore(graph.entry.last, parameter); | 1650 graph.entry.addBefore(graph.entry.last, parameter); |
| 1642 HInstruction value = potentiallyCheckOrTrustType(parameter, field.type); | 1651 HInstruction value = potentiallyCheckOrTrustType(parameter, field.type); |
| 1643 add(new HFieldSet(field, thisInstruction, value)); | 1652 add(new HFieldSet(field, thisInstruction, value)); |
| 1644 return closeFunction(); | 1653 return closeFunction(); |
| 1645 } | 1654 } |
| 1646 | 1655 |
| 1647 HGraph buildLazyInitializer(VariableElement variable) { | 1656 HGraph buildLazyInitializer(VariableElement variable) { |
| 1648 inLazyInitializerExpression = true; | 1657 inLazyInitializerExpression = true; |
| 1649 ast.Node node = variable.node; | 1658 ast.VariableDefinitions node = variable.node; |
| 1650 openFunction(variable, node); | 1659 openFunction(variable, node); |
| 1651 assert(invariant(variable, variable.initializer != null, | 1660 assert(invariant(variable, variable.initializer != null, |
| 1652 message: "Non-constant variable $variable has no initializer.")); | 1661 message: "Non-constant variable $variable has no initializer.")); |
| 1653 visit(variable.initializer); | 1662 visit(variable.initializer); |
| 1654 HInstruction value = pop(); | 1663 HInstruction value = pop(); |
| 1655 value = potentiallyCheckOrTrustType(value, variable.type); | 1664 value = potentiallyCheckOrTrustType(value, variable.type); |
| 1656 closeAndGotoExit(new HReturn(value)); | 1665 ast.SendSet sendSet = node.definitions.nodes.head; |
| 1666 closeAndGotoExit(new HReturn(value, |
| 1667 sourceInformationBuilder.buildReturn(sendSet.assignmentOperator))); |
| 1657 return closeFunction(); | 1668 return closeFunction(); |
| 1658 } | 1669 } |
| 1659 | 1670 |
| 1660 /** | 1671 /** |
| 1661 * Returns the constructor body associated with the given constructor or | 1672 * Returns the constructor body associated with the given constructor or |
| 1662 * creates a new constructor body, if none can be found. | 1673 * creates a new constructor body, if none can be found. |
| 1663 * | 1674 * |
| 1664 * Returns [:null:] if the constructor does not have a body. | 1675 * Returns [:null:] if the constructor does not have a body. |
| 1665 */ | 1676 */ |
| 1666 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { | 1677 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { |
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2148 if (!currentInlinedInstantiations.isEmpty) { | 2159 if (!currentInlinedInstantiations.isEmpty) { |
| 2149 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations); | 2160 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations); |
| 2150 } | 2161 } |
| 2151 | 2162 |
| 2152 HInstruction newObject; | 2163 HInstruction newObject; |
| 2153 if (!isNativeUpgradeFactory) { | 2164 if (!isNativeUpgradeFactory) { |
| 2154 newObject = new HForeignNew(classElement, | 2165 newObject = new HForeignNew(classElement, |
| 2155 ssaType, | 2166 ssaType, |
| 2156 constructorArguments, | 2167 constructorArguments, |
| 2157 instantiatedTypes); | 2168 instantiatedTypes); |
| 2169 if (function != null) { |
| 2170 newObject.sourceInformation = |
| 2171 sourceInformationBuilder.buildGeneric(function); |
| 2172 } |
| 2158 add(newObject); | 2173 add(newObject); |
| 2159 } else { | 2174 } else { |
| 2160 // Bulk assign to the initialized fields. | 2175 // Bulk assign to the initialized fields. |
| 2161 newObject = graph.explicitReceiverParameter; | 2176 newObject = graph.explicitReceiverParameter; |
| 2162 // Null guard ensures an error if we are being called from an explicit | 2177 // Null guard ensures an error if we are being called from an explicit |
| 2163 // 'new' of the constructor instead of via an upgrade. It is optimized out | 2178 // 'new' of the constructor instead of via an upgrade. It is optimized out |
| 2164 // if there are field initializers. | 2179 // if there are field initializers. |
| 2165 add(new HFieldGet( | 2180 add(new HFieldGet( |
| 2166 null, newObject, backend.dynamicType, isAssignable: false)); | 2181 null, newObject, backend.dynamicType, isAssignable: false)); |
| 2167 for (int i = 0; i < fields.length; i++) { | 2182 for (int i = 0; i < fields.length; i++) { |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2301 pop(); | 2316 pop(); |
| 2302 } else { | 2317 } else { |
| 2303 HInvokeConstructorBody invoke = new HInvokeConstructorBody( | 2318 HInvokeConstructorBody invoke = new HInvokeConstructorBody( |
| 2304 body.declaration, bodyCallInputs, backend.nonNullType); | 2319 body.declaration, bodyCallInputs, backend.nonNullType); |
| 2305 invoke.sideEffects = | 2320 invoke.sideEffects = |
| 2306 compiler.world.getSideEffectsOfElement(constructor); | 2321 compiler.world.getSideEffectsOfElement(constructor); |
| 2307 add(invoke); | 2322 add(invoke); |
| 2308 } | 2323 } |
| 2309 } | 2324 } |
| 2310 if (inliningStack.isEmpty) { | 2325 if (inliningStack.isEmpty) { |
| 2311 closeAndGotoExit(new HReturn(newObject)); | 2326 closeAndGotoExit(new HReturn(newObject, |
| 2327 sourceInformationBuilder.buildImplicitReturn(functionElement))); |
| 2312 return closeFunction(); | 2328 return closeFunction(); |
| 2313 } else { | 2329 } else { |
| 2314 localsHandler.updateLocal(returnLocal, newObject); | 2330 localsHandler.updateLocal(returnLocal, newObject); |
| 2315 return null; | 2331 return null; |
| 2316 } | 2332 } |
| 2317 } | 2333 } |
| 2318 | 2334 |
| 2319 /** | 2335 /** |
| 2320 * Documentation wanted -- johnniwinther | 2336 * Documentation wanted -- johnniwinther |
| 2321 * | 2337 * |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2602 inExpressionOfThrow = old; | 2618 inExpressionOfThrow = old; |
| 2603 } | 2619 } |
| 2604 } | 2620 } |
| 2605 | 2621 |
| 2606 visitExpressionStatement(ast.ExpressionStatement node) { | 2622 visitExpressionStatement(ast.ExpressionStatement node) { |
| 2607 if (!isReachable) return; | 2623 if (!isReachable) return; |
| 2608 ast.Throw throwExpression = node.expression.asThrow(); | 2624 ast.Throw throwExpression = node.expression.asThrow(); |
| 2609 if (throwExpression != null && inliningStack.isEmpty) { | 2625 if (throwExpression != null && inliningStack.isEmpty) { |
| 2610 visitThrowExpression(throwExpression.expression); | 2626 visitThrowExpression(throwExpression.expression); |
| 2611 handleInTryStatement(); | 2627 handleInTryStatement(); |
| 2612 closeAndGotoExit(new HThrow(pop())); | 2628 closeAndGotoExit( |
| 2629 new HThrow(pop(), sourceInformationBuilder.buildThrow(node))); |
| 2613 } else { | 2630 } else { |
| 2614 visit(node.expression); | 2631 visit(node.expression); |
| 2615 pop(); | 2632 pop(); |
| 2616 } | 2633 } |
| 2617 } | 2634 } |
| 2618 | 2635 |
| 2619 /** | 2636 /** |
| 2620 * Creates a new loop-header block. The previous [current] block | 2637 * Creates a new loop-header block. The previous [current] block |
| 2621 * is closed with an [HGoto] and replaced by the newly created block. | 2638 * is closed with an [HGoto] and replaced by the newly created block. |
| 2622 * Also notifies the locals handler that we're entering a loop. | 2639 * Also notifies the locals handler that we're entering a loop. |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3097 List<HInstruction> capturedVariables = <HInstruction>[]; | 3114 List<HInstruction> capturedVariables = <HInstruction>[]; |
| 3098 closureClassElement.closureFields.forEach((ClosureFieldElement field) { | 3115 closureClassElement.closureFields.forEach((ClosureFieldElement field) { |
| 3099 Local capturedLocal = | 3116 Local capturedLocal = |
| 3100 nestedClosureData.getLocalVariableForClosureField(field); | 3117 nestedClosureData.getLocalVariableForClosureField(field); |
| 3101 assert(capturedLocal != null); | 3118 assert(capturedLocal != null); |
| 3102 capturedVariables.add(localsHandler.readLocal(capturedLocal)); | 3119 capturedVariables.add(localsHandler.readLocal(capturedLocal)); |
| 3103 }); | 3120 }); |
| 3104 | 3121 |
| 3105 TypeMask type = | 3122 TypeMask type = |
| 3106 new TypeMask.nonNullExact(compiler.functionClass, compiler.world); | 3123 new TypeMask.nonNullExact(compiler.functionClass, compiler.world); |
| 3107 push(new HForeignNew(closureClassElement, type, capturedVariables)); | 3124 push(new HForeignNew(closureClassElement, type, capturedVariables) |
| 3125 ..sourceInformation = sourceInformationBuilder.buildGeneric(node)); |
| 3108 | 3126 |
| 3109 Element methodElement = nestedClosureData.closureElement; | 3127 Element methodElement = nestedClosureData.closureElement; |
| 3110 if (compiler.backend.methodNeedsRti(methodElement)) { | 3128 if (compiler.backend.methodNeedsRti(methodElement)) { |
| 3111 registry.registerClosureWithFreeTypeVariables(methodElement); | 3129 registry.registerClosureWithFreeTypeVariables(methodElement); |
| 3112 } | 3130 } |
| 3113 } | 3131 } |
| 3114 | 3132 |
| 3115 visitFunctionDeclaration(ast.FunctionDeclaration node) { | 3133 visitFunctionDeclaration(ast.FunctionDeclaration node) { |
| 3116 assert(isReachable); | 3134 assert(isReachable); |
| 3117 visit(node.function); | 3135 visit(node.function); |
| 3118 LocalFunctionElement localFunction = | 3136 LocalFunctionElement localFunction = |
| 3119 elements.getFunctionDefinition(node.function); | 3137 elements.getFunctionDefinition(node.function); |
| 3120 localsHandler.updateLocal(localFunction, pop()); | 3138 localsHandler.updateLocal(localFunction, pop()); |
| 3121 } | 3139 } |
| 3122 | 3140 |
| 3123 visitIdentifier(ast.Identifier node) { | 3141 visitIdentifier(ast.Identifier node) { |
| 3124 if (node.isThis()) { | 3142 if (node.isThis()) { |
| 3125 stack.add(localsHandler.readThis()); | 3143 stack.add(localsHandler.readThis()); |
| 3126 } else { | 3144 } else { |
| 3127 compiler.internalError(node, | 3145 compiler.internalError(node, |
| 3128 "SsaFromAstMixin.visitIdentifier on non-this."); | 3146 "SsaFromAstMixin.visitIdentifier on non-this."); |
| 3129 } | 3147 } |
| 3130 } | 3148 } |
| 3131 | 3149 |
| 3132 visitIf(ast.If node) { | 3150 visitIf(ast.If node) { |
| 3133 assert(isReachable); | 3151 assert(isReachable); |
| 3134 handleIf(node, | 3152 handleIf( |
| 3135 () => visit(node.condition), | 3153 node, |
| 3136 () => visit(node.thenPart), | 3154 visitCondition: () => visit(node.condition), |
| 3137 node.elsePart != null ? () => visit(node.elsePart) : null); | 3155 visitThen: () => visit(node.thenPart), |
| 3156 visitElse: node.elsePart != null ? () => visit(node.elsePart) : null, |
| 3157 sourceInformation: sourceInformationBuilder.buildIf(node)); |
| 3138 } | 3158 } |
| 3139 | 3159 |
| 3140 void handleIf(ast.Node diagnosticNode, | 3160 void handleIf(ast.Node diagnosticNode, |
| 3141 void visitCondition(), void visitThen(), void visitElse()) { | 3161 {void visitCondition(), |
| 3162 void visitThen(), |
| 3163 void visitElse(), |
| 3164 SourceInformation sourceInformation}) { |
| 3142 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode); | 3165 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode); |
| 3143 branchBuilder.handleIf(visitCondition, visitThen, visitElse); | 3166 branchBuilder.handleIf( |
| 3167 visitCondition, visitThen, visitElse, |
| 3168 sourceInformation: sourceInformation); |
| 3144 } | 3169 } |
| 3145 | 3170 |
| 3146 @override | 3171 @override |
| 3147 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) { | 3172 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) { |
| 3148 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 3173 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 3149 brancher.handleIfNull(() => visit(left), () => visit(right)); | 3174 brancher.handleIfNull(() => visit(left), () => visit(right)); |
| 3150 } | 3175 } |
| 3151 | 3176 |
| 3152 @override | 3177 @override |
| 3153 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) { | 3178 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3164 branchBuilder.handleLogicalAndOrWithLeftNode( | 3189 branchBuilder.handleLogicalAndOrWithLeftNode( |
| 3165 left, | 3190 left, |
| 3166 () { visit(right); }, | 3191 () { visit(right); }, |
| 3167 isAnd: false); | 3192 isAnd: false); |
| 3168 } | 3193 } |
| 3169 | 3194 |
| 3170 @override | 3195 @override |
| 3171 void visitNot(ast.Send node, ast.Node expression, _) { | 3196 void visitNot(ast.Send node, ast.Node expression, _) { |
| 3172 assert(node.argumentsNode is ast.Prefix); | 3197 assert(node.argumentsNode is ast.Prefix); |
| 3173 visit(expression); | 3198 visit(expression); |
| 3174 HNot not = new HNot(popBoolified(), backend.boolType); | 3199 SourceInformation sourceInformation = |
| 3175 pushWithPosition(not, node); | 3200 sourceInformationBuilder.buildGeneric(node); |
| 3201 push(new HNot(popBoolified(), backend.boolType) |
| 3202 ..sourceInformation = sourceInformation); |
| 3176 } | 3203 } |
| 3177 | 3204 |
| 3178 @override | 3205 @override |
| 3179 void visitUnary(ast.Send node, | 3206 void visitUnary(ast.Send node, |
| 3180 UnaryOperator operator, | 3207 UnaryOperator operator, |
| 3181 ast.Node expression,_) { | 3208 ast.Node expression,_) { |
| 3182 assert(node.argumentsNode is ast.Prefix); | 3209 assert(node.argumentsNode is ast.Prefix); |
| 3183 HInstruction operand = visitAndPop(expression); | 3210 HInstruction operand = visitAndPop(expression); |
| 3184 | 3211 |
| 3185 // See if we can constant-fold right away. This avoids rewrites later on. | 3212 // See if we can constant-fold right away. This avoids rewrites later on. |
| 3186 if (operand is HConstant) { | 3213 if (operand is HConstant) { |
| 3187 UnaryOperation operation = constantSystem.lookupUnary(operator); | 3214 UnaryOperation operation = constantSystem.lookupUnary(operator); |
| 3188 HConstant constant = operand; | 3215 HConstant constant = operand; |
| 3189 ConstantValue folded = operation.fold(constant.constant); | 3216 ConstantValue folded = operation.fold(constant.constant); |
| 3190 if (folded != null) { | 3217 if (folded != null) { |
| 3191 stack.add(graph.addConstant(folded, compiler)); | 3218 stack.add(graph.addConstant(folded, compiler)); |
| 3192 return; | 3219 return; |
| 3193 } | 3220 } |
| 3194 } | 3221 } |
| 3195 | 3222 |
| 3196 pushInvokeDynamic(node, elements.getSelector(node), [operand]); | 3223 pushInvokeDynamic(node, elements.getSelector(node), [operand], |
| 3224 sourceInformation: sourceInformationBuilder.buildGeneric(node)); |
| 3197 } | 3225 } |
| 3198 | 3226 |
| 3199 @override | 3227 @override |
| 3200 void visitBinary(ast.Send node, | 3228 void visitBinary(ast.Send node, |
| 3201 ast.Node left, | 3229 ast.Node left, |
| 3202 BinaryOperator operator, | 3230 BinaryOperator operator, |
| 3203 ast.Node right, _) { | 3231 ast.Node right, _) { |
| 3204 handleBinary(node, left, right); | 3232 handleBinary(node, left, right); |
| 3205 } | 3233 } |
| 3206 | 3234 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3219 handleBinary(node, left, right); | 3247 handleBinary(node, left, right); |
| 3220 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); | 3248 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); |
| 3221 } | 3249 } |
| 3222 | 3250 |
| 3223 void handleBinary(ast.Send node, ast.Node left, ast.Node right) { | 3251 void handleBinary(ast.Send node, ast.Node left, ast.Node right) { |
| 3224 visitBinarySend( | 3252 visitBinarySend( |
| 3225 visitAndPop(left), | 3253 visitAndPop(left), |
| 3226 visitAndPop(right), | 3254 visitAndPop(right), |
| 3227 elements.getSelector(node), | 3255 elements.getSelector(node), |
| 3228 node, | 3256 node, |
| 3229 location: node.selector); | 3257 sourceInformation: |
| 3258 sourceInformationBuilder.buildGeneric(node.selector)); |
| 3230 } | 3259 } |
| 3231 | 3260 |
| 3232 /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and | 3261 /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and |
| 3233 /// remove use of [location] for source information. | 3262 /// remove use of [location] for source information. |
| 3234 void visitBinarySend(HInstruction left, | 3263 void visitBinarySend(HInstruction left, |
| 3235 HInstruction right, | 3264 HInstruction right, |
| 3236 Selector selector, | 3265 Selector selector, |
| 3237 ast.Send send, | 3266 ast.Send send, |
| 3238 {ast.Node location}) { | 3267 {SourceInformation sourceInformation}) { |
| 3239 pushInvokeDynamic(send, selector, [left, right], location: location); | 3268 pushInvokeDynamic(send, selector, [left, right], |
| 3269 sourceInformation: sourceInformation); |
| 3240 } | 3270 } |
| 3241 | 3271 |
| 3242 HInstruction generateInstanceSendReceiver(ast.Send send) { | 3272 HInstruction generateInstanceSendReceiver(ast.Send send) { |
| 3243 assert(Elements.isInstanceSend(send, elements)); | 3273 assert(Elements.isInstanceSend(send, elements)); |
| 3244 if (send.receiver == null) { | 3274 if (send.receiver == null) { |
| 3245 return localsHandler.readThis(); | 3275 return localsHandler.readThis(); |
| 3246 } | 3276 } |
| 3247 visit(send.receiver); | 3277 visit(send.receiver); |
| 3248 return pop(); | 3278 return pop(); |
| 3249 } | 3279 } |
| 3250 | 3280 |
| 3251 String noSuchMethodTargetSymbolString(Element error, [String prefix]) { | 3281 String noSuchMethodTargetSymbolString(Element error, [String prefix]) { |
| 3252 String result = error.name; | 3282 String result = error.name; |
| 3253 if (prefix == "set") return "$result="; | 3283 if (prefix == "set") return "$result="; |
| 3254 return result; | 3284 return result; |
| 3255 } | 3285 } |
| 3256 | 3286 |
| 3257 /** | 3287 /** |
| 3258 * Returns a set of interceptor classes that contain the given | 3288 * Returns a set of interceptor classes that contain the given |
| 3259 * [selector]. | 3289 * [selector]. |
| 3260 */ | 3290 */ |
| 3261 void generateInstanceGetterWithCompiledReceiver(ast.Send send, | 3291 void generateInstanceGetterWithCompiledReceiver( |
| 3262 Selector selector, | 3292 ast.Send send, |
| 3263 HInstruction receiver) { | 3293 Selector selector, |
| 3294 HInstruction receiver) { |
| 3264 assert(Elements.isInstanceSend(send, elements)); | 3295 assert(Elements.isInstanceSend(send, elements)); |
| 3265 assert(selector.isGetter); | 3296 assert(selector.isGetter); |
| 3266 pushInvokeDynamic(send, selector, [receiver]); | 3297 pushInvokeDynamic(send, selector, [receiver], |
| 3298 sourceInformation: sourceInformationBuilder.buildGet(send)); |
| 3267 } | 3299 } |
| 3268 | 3300 |
| 3269 /// Inserts a call to checkDeferredIsLoaded for [prefixElement]. | 3301 /// Inserts a call to checkDeferredIsLoaded for [prefixElement]. |
| 3270 /// If [prefixElement] is [null] ndo nothing. | 3302 /// If [prefixElement] is [null] ndo nothing. |
| 3271 void generateIsDeferredLoadedCheckIfNeeded(PrefixElement prefixElement, | 3303 void generateIsDeferredLoadedCheckIfNeeded(PrefixElement prefixElement, |
| 3272 ast.Node location) { | 3304 ast.Node location) { |
| 3273 if (prefixElement == null) return; | 3305 if (prefixElement == null) return; |
| 3274 String loadId = | 3306 String loadId = |
| 3275 compiler.deferredLoadTask.importDeferName[prefixElement.deferredImport]; | 3307 compiler.deferredLoadTask.importDeferName[prefixElement.deferredImport]; |
| 3276 HInstruction loadIdConstant = addConstantString(loadId); | 3308 HInstruction loadIdConstant = addConstantString(loadId); |
| 3277 String uri = prefixElement.deferredImport.uri.dartString.slowToString(); | 3309 String uri = prefixElement.deferredImport.uri.dartString.slowToString(); |
| 3278 HInstruction uriConstant = addConstantString(uri); | 3310 HInstruction uriConstant = addConstantString(uri); |
| 3279 Element helper = backend.getCheckDeferredIsLoaded(); | 3311 Element helper = backend.getCheckDeferredIsLoaded(); |
| 3280 pushInvokeStatic(location, helper, [loadIdConstant, uriConstant]); | 3312 pushInvokeStatic(location, helper, [loadIdConstant, uriConstant]); |
| 3281 pop(); | 3313 pop(); |
| 3282 } | 3314 } |
| 3283 | 3315 |
| 3284 /// Inserts a call to checkDeferredIsLoaded if the send has a prefix that | 3316 /// Inserts a call to checkDeferredIsLoaded if the send has a prefix that |
| 3285 /// resolves to a deferred library. | 3317 /// resolves to a deferred library. |
| 3286 void generateIsDeferredLoadedCheckOfSend(ast.Send node) { | 3318 void generateIsDeferredLoadedCheckOfSend(ast.Send node) { |
| 3287 generateIsDeferredLoadedCheckIfNeeded( | 3319 generateIsDeferredLoadedCheckIfNeeded( |
| 3288 compiler.deferredLoadTask.deferredPrefixElement(node, elements), | 3320 compiler.deferredLoadTask.deferredPrefixElement(node, elements), |
| 3289 node); | 3321 node); |
| 3290 } | 3322 } |
| 3291 | 3323 |
| 3292 void handleInvalidStaticGet(ast.Send node, Element element) { | 3324 void handleInvalidStaticGet(ast.Send node, Element element) { |
| 3325 SourceInformation sourceInformation = |
| 3326 sourceInformationBuilder.buildGet(node); |
| 3293 generateThrowNoSuchMethod( | 3327 generateThrowNoSuchMethod( |
| 3294 node, | 3328 node, |
| 3295 noSuchMethodTargetSymbolString(element, 'get'), | 3329 noSuchMethodTargetSymbolString(element, 'get'), |
| 3296 argumentNodes: const Link<ast.Node>()); | 3330 argumentNodes: const Link<ast.Node>(), |
| 3331 sourceInformation: sourceInformation); |
| 3297 } | 3332 } |
| 3298 | 3333 |
| 3299 /// Generate read access of an unresolved static or top level entity. | 3334 /// Generate read access of an unresolved static or top level entity. |
| 3300 void generateStaticUnresolvedGet(ast.Send node, Element element) { | 3335 void generateStaticUnresolvedGet(ast.Send node, Element element) { |
| 3301 if (element is ErroneousElement) { | 3336 if (element is ErroneousElement) { |
| 3337 SourceInformation sourceInformation = |
| 3338 sourceInformationBuilder.buildGet(node); |
| 3302 // An erroneous element indicates an unresolved static getter. | 3339 // An erroneous element indicates an unresolved static getter. |
| 3303 handleInvalidStaticGet(node, element); | 3340 handleInvalidStaticGet(node, element); |
| 3304 } else { | 3341 } else { |
| 3305 // This happens when [element] has parse errors. | 3342 // This happens when [element] has parse errors. |
| 3306 assert(invariant(node, element == null || element.isErroneous)); | 3343 assert(invariant(node, element == null || element.isErroneous)); |
| 3307 // TODO(ahe): Do something like the above, that is, emit a runtime | 3344 // TODO(ahe): Do something like the above, that is, emit a runtime |
| 3308 // error. | 3345 // error. |
| 3309 stack.add(graph.addConstantNull(compiler)); | 3346 stack.add(graph.addConstantNull(compiler)); |
| 3310 } | 3347 } |
| 3311 } | 3348 } |
| 3312 | 3349 |
| 3313 /// Read a static or top level [field] of constant value. | 3350 /// Read a static or top level [field] of constant value. |
| 3314 void generateStaticConstGet( | 3351 void generateStaticConstGet( |
| 3315 ast.Send node, | 3352 ast.Send node, |
| 3316 FieldElement field, | 3353 FieldElement field, |
| 3317 ConstantExpression constant) { | 3354 ConstantExpression constant, |
| 3355 SourceInformation sourceInformation) { |
| 3318 ConstantValue value = backend.constants.getConstantValue(constant); | 3356 ConstantValue value = backend.constants.getConstantValue(constant); |
| 3319 HConstant instruction; | 3357 HConstant instruction; |
| 3320 // Constants that are referred via a deferred prefix should be referred | 3358 // Constants that are referred via a deferred prefix should be referred |
| 3321 // by reference. | 3359 // by reference. |
| 3322 PrefixElement prefix = compiler.deferredLoadTask | 3360 PrefixElement prefix = compiler.deferredLoadTask |
| 3323 .deferredPrefixElement(node, elements); | 3361 .deferredPrefixElement(node, elements); |
| 3324 if (prefix != null) { | 3362 if (prefix != null) { |
| 3325 instruction = graph.addDeferredConstant(value, prefix, compiler); | 3363 instruction = |
| 3364 graph.addDeferredConstant(value, prefix, sourceInformation, compiler); |
| 3326 } else { | 3365 } else { |
| 3327 instruction = graph.addConstant(value, compiler); | 3366 instruction = graph.addConstant( |
| 3367 value, compiler, sourceInformation: sourceInformation); |
| 3328 } | 3368 } |
| 3329 stack.add(instruction); | 3369 stack.add(instruction); |
| 3330 // The inferrer may have found a better type than the constant | 3370 // The inferrer may have found a better type than the constant |
| 3331 // handler in the case of lists, because the constant handler | 3371 // handler in the case of lists, because the constant handler |
| 3332 // does not look at elements in the list. | 3372 // does not look at elements in the list. |
| 3333 TypeMask type = | 3373 TypeMask type = |
| 3334 TypeMaskFactory.inferredTypeForElement(field, compiler); | 3374 TypeMaskFactory.inferredTypeForElement(field, compiler); |
| 3335 if (!type.containsAll(compiler.world) && | 3375 if (!type.containsAll(compiler.world) && |
| 3336 !instruction.isConstantNull()) { | 3376 !instruction.isConstantNull()) { |
| 3337 // TODO(13429): The inferrer should know that an element | 3377 // TODO(13429): The inferrer should know that an element |
| 3338 // cannot be null. | 3378 // cannot be null. |
| 3339 instruction.instructionType = type.nonNullable(); | 3379 instruction.instructionType = type.nonNullable(); |
| 3340 } | 3380 } |
| 3341 } | 3381 } |
| 3342 | 3382 |
| 3343 /// Read a static or top level [field]. | 3383 /// Read a static or top level [field]. |
| 3344 void generateStaticFieldGet(ast.Send node, FieldElement field) { | 3384 void generateStaticFieldGet(ast.Send node, FieldElement field) { |
| 3345 generateIsDeferredLoadedCheckOfSend(node); | 3385 generateIsDeferredLoadedCheckOfSend(node); |
| 3346 | 3386 |
| 3347 ConstantExpression constant = | 3387 ConstantExpression constant = |
| 3348 backend.constants.getConstantForVariable(field); | 3388 backend.constants.getConstantForVariable(field); |
| 3389 SourceInformation sourceInformation = |
| 3390 sourceInformationBuilder.buildGet(node); |
| 3349 if (constant != null) { | 3391 if (constant != null) { |
| 3350 if (!field.isAssignable) { | 3392 if (!field.isAssignable) { |
| 3351 // A static final or const. Get its constant value and inline it if | 3393 // A static final or const. Get its constant value and inline it if |
| 3352 // the value can be compiled eagerly. | 3394 // the value can be compiled eagerly. |
| 3353 generateStaticConstGet(node, field, constant); | 3395 generateStaticConstGet(node, field, constant, sourceInformation); |
| 3354 } else { | 3396 } else { |
| 3355 // TODO(5346): Try to avoid the need for calling [declaration] before | 3397 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 3356 // creating an [HStatic]. | 3398 // creating an [HStatic]. |
| 3357 HInstruction instruction = new HStatic( | 3399 HInstruction instruction = new HStatic( |
| 3358 field.declaration, | 3400 field.declaration, |
| 3359 TypeMaskFactory.inferredTypeForElement(field, compiler)); | 3401 TypeMaskFactory.inferredTypeForElement(field, compiler)) |
| 3402 ..sourceInformation = sourceInformation; |
| 3360 push(instruction); | 3403 push(instruction); |
| 3361 } | 3404 } |
| 3362 } else { | 3405 } else { |
| 3363 HInstruction instruction = new HLazyStatic( | 3406 HInstruction instruction = new HLazyStatic( |
| 3364 field, | 3407 field, |
| 3365 TypeMaskFactory.inferredTypeForElement(field, compiler)); | 3408 TypeMaskFactory.inferredTypeForElement(field, compiler)) |
| 3409 ..sourceInformation = sourceInformation; |
| 3366 push(instruction); | 3410 push(instruction); |
| 3367 } | 3411 } |
| 3368 } | 3412 } |
| 3369 | 3413 |
| 3370 /// Generate a getter invocation of the static or top level [getter]. | 3414 /// Generate a getter invocation of the static or top level [getter]. |
| 3371 void generateStaticGetterGet(ast.Send node, MethodElement getter) { | 3415 void generateStaticGetterGet(ast.Send node, MethodElement getter) { |
| 3416 SourceInformation sourceInformation = |
| 3417 sourceInformationBuilder.buildGet(node); |
| 3372 if (getter.isDeferredLoaderGetter) { | 3418 if (getter.isDeferredLoaderGetter) { |
| 3373 generateDeferredLoaderGet(node, getter); | 3419 generateDeferredLoaderGet(node, getter, sourceInformation); |
| 3374 } else { | 3420 } else { |
| 3375 generateIsDeferredLoadedCheckOfSend(node); | 3421 generateIsDeferredLoadedCheckOfSend(node); |
| 3376 pushInvokeStatic(node, getter, <HInstruction>[]); | 3422 pushInvokeStatic(node, getter, <HInstruction>[], |
| 3423 sourceInformation: sourceInformation); |
| 3377 } | 3424 } |
| 3378 } | 3425 } |
| 3379 | 3426 |
| 3380 /// Generate a dynamic getter invocation. | 3427 /// Generate a dynamic getter invocation. |
| 3381 void generateDynamicGet(ast.Send node) { | 3428 void generateDynamicGet(ast.Send node) { |
| 3382 HInstruction receiver = generateInstanceSendReceiver(node); | 3429 HInstruction receiver = generateInstanceSendReceiver(node); |
| 3383 generateInstanceGetterWithCompiledReceiver( | 3430 generateInstanceGetterWithCompiledReceiver( |
| 3384 node, elements.getSelector(node), receiver); | 3431 node, elements.getSelector(node), receiver); |
| 3385 } | 3432 } |
| 3386 | 3433 |
| 3387 /// Generate a closurization of the static or top level [function]. | 3434 /// Generate a closurization of the static or top level [function]. |
| 3388 void generateStaticFunctionGet(ast.Send node, MethodElement function) { | 3435 void generateStaticFunctionGet(ast.Send node, MethodElement function) { |
| 3389 generateIsDeferredLoadedCheckOfSend(node); | 3436 generateIsDeferredLoadedCheckOfSend(node); |
| 3390 // TODO(5346): Try to avoid the need for calling [declaration] before | 3437 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 3391 // creating an [HStatic]. | 3438 // creating an [HStatic]. |
| 3392 push(new HStatic(function.declaration, backend.nonNullType)); | 3439 SourceInformation sourceInformation = |
| 3440 sourceInformationBuilder.buildGet(node); |
| 3441 push(new HStatic(function.declaration, backend.nonNullType) |
| 3442 ..sourceInformation = sourceInformation); |
| 3393 // TODO(ahe): This should be registered in codegen. | 3443 // TODO(ahe): This should be registered in codegen. |
| 3394 registry.registerGetOfStaticFunction(function.declaration); | 3444 registry.registerGetOfStaticFunction(function.declaration); |
| 3395 } | 3445 } |
| 3396 | 3446 |
| 3397 /// Read a local variable, function or parameter. | 3447 /// Read a local variable, function or parameter. |
| 3398 void handleLocalGet(LocalElement local) { | 3448 void buildLocalGet(LocalElement local, SourceInformation sourceInformation) { |
| 3399 stack.add(localsHandler.readLocal(local)); | 3449 stack.add(localsHandler.readLocal( |
| 3450 local, sourceInformation: sourceInformation)); |
| 3451 } |
| 3452 |
| 3453 void handleLocalGet(ast.Send node, LocalElement local) { |
| 3454 buildLocalGet(local, sourceInformationBuilder.buildGet(node)); |
| 3400 } | 3455 } |
| 3401 | 3456 |
| 3402 @override | 3457 @override |
| 3403 void visitDynamicPropertyGet( | 3458 void visitDynamicPropertyGet( |
| 3404 ast.Send node, | 3459 ast.Send node, |
| 3405 ast.Node receiver, | 3460 ast.Node receiver, |
| 3406 Selector selector, | 3461 Selector selector, |
| 3407 _) { | 3462 _) { |
| 3408 generateDynamicGet(node); | 3463 generateDynamicGet(node); |
| 3409 } | 3464 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3433 } | 3488 } |
| 3434 | 3489 |
| 3435 /// Pushes a boolean checking [expression] against null. | 3490 /// Pushes a boolean checking [expression] against null. |
| 3436 pushCheckNull(HInstruction expression) { | 3491 pushCheckNull(HInstruction expression) { |
| 3437 push(new HIdentity(expression, graph.addConstantNull(compiler), | 3492 push(new HIdentity(expression, graph.addConstantNull(compiler), |
| 3438 null, backend.boolType)); | 3493 null, backend.boolType)); |
| 3439 } | 3494 } |
| 3440 | 3495 |
| 3441 @override | 3496 @override |
| 3442 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { | 3497 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { |
| 3443 handleLocalGet(variable); | 3498 handleLocalGet(node, variable); |
| 3444 } | 3499 } |
| 3445 | 3500 |
| 3446 @override | 3501 @override |
| 3447 void visitParameterGet(ast.Send node, ParameterElement parameter, _) { | 3502 void visitParameterGet(ast.Send node, ParameterElement parameter, _) { |
| 3448 handleLocalGet(parameter); | 3503 handleLocalGet(node, parameter); |
| 3449 } | 3504 } |
| 3450 | 3505 |
| 3451 @override | 3506 @override |
| 3452 void visitLocalFunctionGet(ast.Send node, LocalFunctionElement function, _) { | 3507 void visitLocalFunctionGet(ast.Send node, LocalFunctionElement function, _) { |
| 3453 handleLocalGet(function); | 3508 handleLocalGet(node, function); |
| 3454 } | 3509 } |
| 3455 | 3510 |
| 3456 @override | 3511 @override |
| 3457 void visitStaticFieldGet( | 3512 void visitStaticFieldGet( |
| 3458 ast.Send node, | 3513 ast.Send node, |
| 3459 FieldElement field, | 3514 FieldElement field, |
| 3460 _) { | 3515 _) { |
| 3461 generateStaticFieldGet(node, field); | 3516 generateStaticFieldGet(node, field); |
| 3462 } | 3517 } |
| 3463 | 3518 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3517 assert(send == null || Elements.isInstanceSend(send, elements)); | 3572 assert(send == null || Elements.isInstanceSend(send, elements)); |
| 3518 if (selector == null) { | 3573 if (selector == null) { |
| 3519 assert(send != null); | 3574 assert(send != null); |
| 3520 selector = elements.getSelector(send); | 3575 selector = elements.getSelector(send); |
| 3521 } | 3576 } |
| 3522 if (location == null) { | 3577 if (location == null) { |
| 3523 assert(send != null); | 3578 assert(send != null); |
| 3524 location = send; | 3579 location = send; |
| 3525 } | 3580 } |
| 3526 assert(selector.isSetter); | 3581 assert(selector.isSetter); |
| 3527 pushInvokeDynamic(location, selector, [receiver, value]); | 3582 pushInvokeDynamic(location, selector, [receiver, value], |
| 3583 sourceInformation: sourceInformationBuilder.buildAssignment(location)); |
| 3528 pop(); | 3584 pop(); |
| 3529 stack.add(value); | 3585 stack.add(value); |
| 3530 } | 3586 } |
| 3531 | 3587 |
| 3532 void generateNonInstanceSetter(ast.SendSet send, | 3588 void generateNonInstanceSetter(ast.SendSet send, |
| 3533 Element element, | 3589 Element element, |
| 3534 HInstruction value, | 3590 HInstruction value, |
| 3535 {ast.Node location}) { | 3591 {ast.Node location}) { |
| 3536 assert(send == null || !Elements.isInstanceSend(send, elements)); | 3592 assert(send == null || !Elements.isInstanceSend(send, elements)); |
| 3537 if (location == null) { | 3593 if (location == null) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 3567 if (value.sourceElement == null) { | 3623 if (value.sourceElement == null) { |
| 3568 value.sourceElement = local; | 3624 value.sourceElement = local; |
| 3569 } | 3625 } |
| 3570 HInstruction checkedOrTrusted = | 3626 HInstruction checkedOrTrusted = |
| 3571 potentiallyCheckOrTrustType(value, local.type); | 3627 potentiallyCheckOrTrustType(value, local.type); |
| 3572 if (!identical(checkedOrTrusted, value)) { | 3628 if (!identical(checkedOrTrusted, value)) { |
| 3573 pop(); | 3629 pop(); |
| 3574 stack.add(checkedOrTrusted); | 3630 stack.add(checkedOrTrusted); |
| 3575 } | 3631 } |
| 3576 | 3632 |
| 3577 localsHandler.updateLocal(local, checkedOrTrusted); | 3633 localsHandler.updateLocal(local, checkedOrTrusted, |
| 3634 sourceInformation: |
| 3635 sourceInformationBuilder.buildAssignment(location)); |
| 3578 } | 3636 } |
| 3579 } | 3637 } |
| 3580 | 3638 |
| 3581 HInstruction invokeInterceptor(HInstruction receiver) { | 3639 HInstruction invokeInterceptor(HInstruction receiver) { |
| 3582 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); | 3640 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); |
| 3583 add(interceptor); | 3641 add(interceptor); |
| 3584 return interceptor; | 3642 return interceptor; |
| 3585 } | 3643 } |
| 3586 | 3644 |
| 3587 HLiteralList buildLiteralList(List<HInstruction> inputs) { | 3645 HLiteralList buildLiteralList(List<HInstruction> inputs) { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3774 } | 3832 } |
| 3775 | 3833 |
| 3776 /// Generate a dynamic method, getter or setter invocation. | 3834 /// Generate a dynamic method, getter or setter invocation. |
| 3777 void generateDynamicSend(ast.Send node) { | 3835 void generateDynamicSend(ast.Send node) { |
| 3778 HInstruction receiver = generateInstanceSendReceiver(node); | 3836 HInstruction receiver = generateInstanceSendReceiver(node); |
| 3779 _generateDynamicSend(node, receiver); | 3837 _generateDynamicSend(node, receiver); |
| 3780 } | 3838 } |
| 3781 | 3839 |
| 3782 void _generateDynamicSend(ast.Send node, HInstruction receiver) { | 3840 void _generateDynamicSend(ast.Send node, HInstruction receiver) { |
| 3783 Selector selector = elements.getSelector(node); | 3841 Selector selector = elements.getSelector(node); |
| 3842 SourceInformation sourceInformation = |
| 3843 sourceInformationBuilder.buildCall(node, node.selector); |
| 3784 | 3844 |
| 3785 List<HInstruction> inputs = <HInstruction>[]; | 3845 List<HInstruction> inputs = <HInstruction>[]; |
| 3786 inputs.add(receiver); | 3846 inputs.add(receiver); |
| 3787 addDynamicSendArgumentsToList(node, inputs); | 3847 addDynamicSendArgumentsToList(node, inputs); |
| 3788 | 3848 |
| 3789 pushInvokeDynamic(node, selector, inputs); | 3849 pushInvokeDynamic(node, selector, inputs, |
| 3850 sourceInformation: sourceInformation); |
| 3790 if (selector.isSetter || selector.isIndexSet) { | 3851 if (selector.isSetter || selector.isIndexSet) { |
| 3791 pop(); | 3852 pop(); |
| 3792 stack.add(inputs.last); | 3853 stack.add(inputs.last); |
| 3793 } | 3854 } |
| 3794 } | 3855 } |
| 3795 | 3856 |
| 3796 @override | 3857 @override |
| 3797 visitDynamicPropertyInvoke( | 3858 visitDynamicPropertyInvoke( |
| 3798 ast.Send node, | 3859 ast.Send node, |
| 3799 ast.Node receiver, | 3860 ast.Node receiver, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3831 generateDynamicSend(node); | 3892 generateDynamicSend(node); |
| 3832 } | 3893 } |
| 3833 | 3894 |
| 3834 @override | 3895 @override |
| 3835 visitExpressionInvoke( | 3896 visitExpressionInvoke( |
| 3836 ast.Send node, | 3897 ast.Send node, |
| 3837 ast.Node expression, | 3898 ast.Node expression, |
| 3838 ast.NodeList arguments, | 3899 ast.NodeList arguments, |
| 3839 Selector selector, | 3900 Selector selector, |
| 3840 _) { | 3901 _) { |
| 3841 generateCallInvoke(node, visitAndPop(expression)); | 3902 generateCallInvoke( |
| 3903 node, |
| 3904 visitAndPop(expression), |
| 3905 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 3842 } | 3906 } |
| 3843 | 3907 |
| 3844 @override | 3908 @override |
| 3845 visitThisInvoke( | 3909 visitThisInvoke( |
| 3846 ast.Send node, | 3910 ast.Send node, |
| 3847 ast.NodeList arguments, | 3911 ast.NodeList arguments, |
| 3848 CallStructure callStructure, | 3912 CallStructure callStructure, |
| 3849 _) { | 3913 _) { |
| 3850 generateCallInvoke(node, localsHandler.readThis()); | 3914 generateCallInvoke( |
| 3915 node, |
| 3916 localsHandler.readThis(), |
| 3917 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 3851 } | 3918 } |
| 3852 | 3919 |
| 3853 @override | 3920 @override |
| 3854 visitParameterInvoke( | 3921 visitParameterInvoke( |
| 3855 ast.Send node, | 3922 ast.Send node, |
| 3856 ParameterElement parameter, | 3923 ParameterElement parameter, |
| 3857 ast.NodeList arguments, | 3924 ast.NodeList arguments, |
| 3858 CallStructure callStructure, | 3925 CallStructure callStructure, |
| 3859 _) { | 3926 _) { |
| 3860 generateCallInvoke(node, localsHandler.readLocal(parameter)); | 3927 generateCallInvoke( |
| 3928 node, |
| 3929 localsHandler.readLocal(parameter), |
| 3930 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 3861 } | 3931 } |
| 3862 | 3932 |
| 3863 @override | 3933 @override |
| 3864 visitLocalVariableInvoke( | 3934 visitLocalVariableInvoke( |
| 3865 ast.Send node, | 3935 ast.Send node, |
| 3866 LocalVariableElement variable, | 3936 LocalVariableElement variable, |
| 3867 ast.NodeList arguments, | 3937 ast.NodeList arguments, |
| 3868 CallStructure callStructure, | 3938 CallStructure callStructure, |
| 3869 _) { | 3939 _) { |
| 3870 generateCallInvoke(node, localsHandler.readLocal(variable)); | 3940 generateCallInvoke( |
| 3941 node, |
| 3942 localsHandler.readLocal(variable), |
| 3943 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 3871 } | 3944 } |
| 3872 | 3945 |
| 3873 @override | 3946 @override |
| 3874 visitLocalFunctionInvoke( | 3947 visitLocalFunctionInvoke( |
| 3875 ast.Send node, | 3948 ast.Send node, |
| 3876 LocalFunctionElement function, | 3949 LocalFunctionElement function, |
| 3877 ast.NodeList arguments, | 3950 ast.NodeList arguments, |
| 3878 CallStructure callStructure, | 3951 CallStructure callStructure, |
| 3879 _) { | 3952 _) { |
| 3880 generateCallInvoke(node, localsHandler.readLocal(function)); | 3953 generateCallInvoke( |
| 3954 node, |
| 3955 localsHandler.readLocal(function), |
| 3956 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 3881 } | 3957 } |
| 3882 | 3958 |
| 3883 @override | 3959 @override |
| 3884 visitLocalFunctionIncompatibleInvoke( | 3960 visitLocalFunctionIncompatibleInvoke( |
| 3885 ast.Send node, | 3961 ast.Send node, |
| 3886 LocalFunctionElement function, | 3962 LocalFunctionElement function, |
| 3887 ast.NodeList arguments, | 3963 ast.NodeList arguments, |
| 3888 CallStructure callStructure, | 3964 CallStructure callStructure, |
| 3889 _) { | 3965 _) { |
| 3890 generateCallInvoke(node, localsHandler.readLocal(function)); | 3966 generateCallInvoke(node, localsHandler.readLocal(function), |
| 3967 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 3891 } | 3968 } |
| 3892 | 3969 |
| 3893 void handleForeignJs(ast.Send node) { | 3970 void handleForeignJs(ast.Send node) { |
| 3894 Link<ast.Node> link = node.arguments; | 3971 Link<ast.Node> link = node.arguments; |
| 3895 // Don't visit the first argument, which is the type, and the second | 3972 // Don't visit the first argument, which is the type, and the second |
| 3896 // argument, which is the foreign code. | 3973 // argument, which is the foreign code. |
| 3897 if (link.isEmpty || link.tail.isEmpty) { | 3974 if (link.isEmpty || link.tail.isEmpty) { |
| 3898 compiler.internalError(node.argumentsNode, | 3975 compiler.internalError(node.argumentsNode, |
| 3899 'At least two arguments expected.'); | 3976 'At least two arguments expected.'); |
| 3900 } | 3977 } |
| 3901 native.NativeBehavior nativeBehavior = | 3978 native.NativeBehavior nativeBehavior = |
| 3902 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); | 3979 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); |
| 3903 | 3980 |
| 3904 List<HInstruction> inputs = <HInstruction>[]; | 3981 List<HInstruction> inputs = <HInstruction>[]; |
| 3905 addGenericSendArgumentsToList(link.tail.tail, inputs); | 3982 addGenericSendArgumentsToList(link.tail.tail, inputs); |
| 3906 | 3983 |
| 3907 TypeMask ssaType = | 3984 TypeMask ssaType = |
| 3908 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); | 3985 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); |
| 3909 | 3986 |
| 3987 SourceInformation sourceInformation = |
| 3988 sourceInformationBuilder.buildCall(node, node.argumentsNode); |
| 3910 if (nativeBehavior.codeTemplate.isExpression) { | 3989 if (nativeBehavior.codeTemplate.isExpression) { |
| 3911 push(new HForeignCode( | 3990 push(new HForeignCode( |
| 3912 nativeBehavior.codeTemplate, ssaType, inputs, | 3991 nativeBehavior.codeTemplate, ssaType, inputs, |
| 3913 effects: nativeBehavior.sideEffects, | 3992 effects: nativeBehavior.sideEffects, |
| 3914 nativeBehavior: nativeBehavior)); | 3993 nativeBehavior: nativeBehavior) |
| 3994 ..sourceInformation = sourceInformation); |
| 3915 } else { | 3995 } else { |
| 3916 push(new HForeignCode( | 3996 push(new HForeignCode( |
| 3917 nativeBehavior.codeTemplate, ssaType, inputs, | 3997 nativeBehavior.codeTemplate, ssaType, inputs, |
| 3918 isStatement: true, | 3998 isStatement: true, |
| 3919 effects: nativeBehavior.sideEffects, | 3999 effects: nativeBehavior.sideEffects, |
| 3920 nativeBehavior: nativeBehavior)); | 4000 nativeBehavior: nativeBehavior) |
| 4001 ..sourceInformation = sourceInformation); |
| 3921 } | 4002 } |
| 3922 } | 4003 } |
| 3923 | 4004 |
| 3924 void handleJsStringConcat(ast.Send node) { | 4005 void handleJsStringConcat(ast.Send node) { |
| 3925 List<HInstruction> inputs = <HInstruction>[]; | 4006 List<HInstruction> inputs = <HInstruction>[]; |
| 3926 addGenericSendArgumentsToList(node.arguments, inputs); | 4007 addGenericSendArgumentsToList(node.arguments, inputs); |
| 3927 if (inputs.length != 2) { | 4008 if (inputs.length != 2) { |
| 3928 compiler.internalError(node.argumentsNode, 'Two arguments expected.'); | 4009 compiler.internalError(node.argumentsNode, 'Two arguments expected.'); |
| 3929 } | 4010 } |
| 3930 push(new HStringConcat(inputs[0], inputs[1], node, backend.stringType)); | 4011 push(new HStringConcat(inputs[0], inputs[1], node, backend.stringType)); |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4260 stack.add(graph.addConstantNull(compiler)); | 4341 stack.add(graph.addConstantNull(compiler)); |
| 4261 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { | 4342 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { |
| 4262 handleJsInterceptorConstant(node); | 4343 handleJsInterceptorConstant(node); |
| 4263 } else if (name == 'JS_STRING_CONCAT') { | 4344 } else if (name == 'JS_STRING_CONCAT') { |
| 4264 handleJsStringConcat(node); | 4345 handleJsStringConcat(node); |
| 4265 } else { | 4346 } else { |
| 4266 compiler.internalError(node, "Unknown foreign: ${element}"); | 4347 compiler.internalError(node, "Unknown foreign: ${element}"); |
| 4267 } | 4348 } |
| 4268 } | 4349 } |
| 4269 | 4350 |
| 4270 generateDeferredLoaderGet(ast.Send node, FunctionElement deferredLoader) { | 4351 generateDeferredLoaderGet(ast.Send node, |
| 4352 FunctionElement deferredLoader, |
| 4353 SourceInformation sourceInformation) { |
| 4271 // Until now we only handle these as getters. | 4354 // Until now we only handle these as getters. |
| 4272 invariant(node, deferredLoader.isDeferredLoaderGetter); | 4355 invariant(node, deferredLoader.isDeferredLoaderGetter); |
| 4273 Element loadFunction = compiler.loadLibraryFunction; | 4356 Element loadFunction = compiler.loadLibraryFunction; |
| 4274 PrefixElement prefixElement = deferredLoader.enclosingElement; | 4357 PrefixElement prefixElement = deferredLoader.enclosingElement; |
| 4275 String loadId = compiler.deferredLoadTask | 4358 String loadId = compiler.deferredLoadTask |
| 4276 .importDeferName[prefixElement.deferredImport]; | 4359 .importDeferName[prefixElement.deferredImport]; |
| 4277 var inputs = [graph.addConstantString( | 4360 var inputs = [graph.addConstantString( |
| 4278 new ast.DartString.literal(loadId), compiler)]; | 4361 new ast.DartString.literal(loadId), compiler)]; |
| 4279 push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType, | 4362 push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType, |
| 4280 targetCanThrow: false)); | 4363 targetCanThrow: false) |
| 4364 ..sourceInformation = sourceInformation); |
| 4281 } | 4365 } |
| 4282 | 4366 |
| 4283 generateSuperNoSuchMethodSend(ast.Send node, | 4367 generateSuperNoSuchMethodSend(ast.Send node, |
| 4284 Selector selector, | 4368 Selector selector, |
| 4285 List<HInstruction> arguments) { | 4369 List<HInstruction> arguments) { |
| 4286 String name = selector.name; | 4370 String name = selector.name; |
| 4287 | 4371 |
| 4288 ClassElement cls = currentNonClosureClass; | 4372 ClassElement cls = currentNonClosureClass; |
| 4289 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); | 4373 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); |
| 4290 if (compiler.enabledInvokeOn | 4374 if (compiler.enabledInvokeOn |
| (...skipping 30 matching lines...) Expand all Loading... |
| 4321 ConstantValue kindConstant = | 4405 ConstantValue kindConstant = |
| 4322 constantSystem.createInt(selector.invocationMirrorKind); | 4406 constantSystem.createInt(selector.invocationMirrorKind); |
| 4323 | 4407 |
| 4324 pushInvokeStatic(null, | 4408 pushInvokeStatic(null, |
| 4325 createInvocationMirror, | 4409 createInvocationMirror, |
| 4326 [graph.addConstant(nameConstant, compiler), | 4410 [graph.addConstant(nameConstant, compiler), |
| 4327 graph.addConstant(internalNameConstant, compiler), | 4411 graph.addConstant(internalNameConstant, compiler), |
| 4328 graph.addConstant(kindConstant, compiler), | 4412 graph.addConstant(kindConstant, compiler), |
| 4329 argumentsInstruction, | 4413 argumentsInstruction, |
| 4330 argumentNamesInstruction], | 4414 argumentNamesInstruction], |
| 4331 typeMask: backend.dynamicType); | 4415 typeMask: backend.dynamicType); |
| 4332 | 4416 |
| 4333 var inputs = <HInstruction>[pop()]; | 4417 var inputs = <HInstruction>[pop()]; |
| 4334 push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs)); | 4418 push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs)); |
| 4335 } | 4419 } |
| 4336 | 4420 |
| 4337 /// Generate a call to a super method or constructor. | 4421 /// Generate a call to a super method or constructor. |
| 4338 void generateSuperInvoke(ast.Send node, FunctionElement function) { | 4422 void generateSuperInvoke(ast.Send node, |
| 4423 FunctionElement function, |
| 4424 SourceInformation sourceInformation) { |
| 4339 // TODO(5347): Try to avoid the need for calling [implementation] before | 4425 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 4340 // calling [makeStaticArgumentList]. | 4426 // calling [makeStaticArgumentList]. |
| 4341 Selector selector = elements.getSelector(node); | 4427 Selector selector = elements.getSelector(node); |
| 4342 assert(invariant(node, | 4428 assert(invariant(node, |
| 4343 selector.applies(function.implementation, compiler.world), | 4429 selector.applies(function.implementation, compiler.world), |
| 4344 message: "$selector does not apply to ${function.implementation}")); | 4430 message: "$selector does not apply to ${function.implementation}")); |
| 4345 List<HInstruction> inputs = | 4431 List<HInstruction> inputs = |
| 4346 makeStaticArgumentList(selector.callStructure, | 4432 makeStaticArgumentList(selector.callStructure, |
| 4347 node.arguments, | 4433 node.arguments, |
| 4348 function.implementation); | 4434 function.implementation); |
| 4349 push(buildInvokeSuper(selector, function, inputs)); | 4435 push(buildInvokeSuper(selector, function, inputs, sourceInformation)); |
| 4350 } | 4436 } |
| 4351 | 4437 |
| 4352 /// Access the value from the super [element]. | 4438 /// Access the value from the super [element]. |
| 4353 void handleSuperGet(ast.Send node, Element element) { | 4439 void handleSuperGet(ast.Send node, Element element) { |
| 4354 Selector selector = elements.getSelector(node); | 4440 Selector selector = elements.getSelector(node); |
| 4355 push(buildInvokeSuper(selector, element, const <HInstruction>[])); | 4441 SourceInformation sourceInformation = |
| 4442 sourceInformationBuilder.buildGet(node); |
| 4443 push(buildInvokeSuper( |
| 4444 selector, element, const <HInstruction>[], sourceInformation)); |
| 4356 } | 4445 } |
| 4357 | 4446 |
| 4358 /// Invoke .call on the value retrieved from the super [element]. | 4447 /// Invoke .call on the value retrieved from the super [element]. |
| 4359 void handleSuperCallInvoke(ast.Send node, Element element) { | 4448 void handleSuperCallInvoke(ast.Send node, Element element) { |
| 4360 Selector selector = elements.getSelector(node); | 4449 Selector selector = elements.getSelector(node); |
| 4361 HInstruction target = | 4450 HInstruction target = buildInvokeSuper( |
| 4362 buildInvokeSuper(selector, element, const <HInstruction>[]); | 4451 selector, element, const <HInstruction>[], |
| 4452 sourceInformationBuilder.buildGet(node)); |
| 4363 add(target); | 4453 add(target); |
| 4364 generateCallInvoke(node, target); | 4454 generateCallInvoke( |
| 4455 node, |
| 4456 target, |
| 4457 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 4365 } | 4458 } |
| 4366 | 4459 |
| 4367 /// Invoke super [method]. | 4460 /// Invoke super [method]. |
| 4368 void handleSuperMethodInvoke( | 4461 void handleSuperMethodInvoke( |
| 4369 ast.Send node, | 4462 ast.Send node, |
| 4370 MethodElement method) { | 4463 MethodElement method) { |
| 4371 generateSuperInvoke(node, method); | 4464 generateSuperInvoke(node, method, |
| 4465 sourceInformationBuilder.buildCall(node, node.selector)); |
| 4372 } | 4466 } |
| 4373 | 4467 |
| 4374 /// Access an unresolved super property. | 4468 /// Access an unresolved super property. |
| 4375 void handleUnresolvedSuperInvoke(ast.Send node) { | 4469 void handleUnresolvedSuperInvoke(ast.Send node) { |
| 4376 Selector selector = elements.getSelector(node); | 4470 Selector selector = elements.getSelector(node); |
| 4377 List<HInstruction> arguments = <HInstruction>[]; | 4471 List<HInstruction> arguments = <HInstruction>[]; |
| 4378 if (!node.isPropertyAccess) { | 4472 if (!node.isPropertyAccess) { |
| 4379 addGenericSendArgumentsToList(node.arguments, arguments); | 4473 addGenericSendArgumentsToList(node.arguments, arguments); |
| 4380 } | 4474 } |
| 4381 generateSuperNoSuchMethodSend(node, selector, arguments); | 4475 generateSuperNoSuchMethodSend(node, selector, arguments); |
| 4382 } | 4476 } |
| 4383 | 4477 |
| 4384 /// Handle super constructor invocation. | 4478 /// Handle super constructor invocation. |
| 4385 @override | 4479 @override |
| 4386 void handleSuperConstructorInvoke(ast.Send node) { | 4480 void handleSuperConstructorInvoke(ast.Send node) { |
| 4387 Selector selector = elements.getSelector(node); | 4481 Selector selector = elements.getSelector(node); |
| 4388 Element element = elements[node]; | 4482 Element element = elements[node]; |
| 4389 if (selector.applies(element, compiler.world)) { | 4483 if (selector.applies(element, compiler.world)) { |
| 4390 generateSuperInvoke(node, element); | 4484 generateSuperInvoke(node, element, |
| 4485 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 4391 } else { | 4486 } else { |
| 4392 generateWrongArgumentCountError(node, element, node.arguments); | 4487 generateWrongArgumentCountError(node, element, node.arguments); |
| 4393 } | 4488 } |
| 4394 } | 4489 } |
| 4395 | 4490 |
| 4396 @override | 4491 @override |
| 4397 void visitUnresolvedSuperIndex( | 4492 void visitUnresolvedSuperIndex( |
| 4398 ast.Send node, | 4493 ast.Send node, |
| 4399 Element element, | 4494 Element element, |
| 4400 ast.Node index, | 4495 ast.Node index, |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4570 return !rti.isTrivialSubstitution(subclass, cls); | 4665 return !rti.isTrivialSubstitution(subclass, cls); |
| 4571 }); | 4666 }); |
| 4572 } | 4667 } |
| 4573 | 4668 |
| 4574 /** | 4669 /** |
| 4575 * Generate code to extract the type arguments from the object, substitute | 4670 * Generate code to extract the type arguments from the object, substitute |
| 4576 * them as an instance of the type we are testing against (if necessary), and | 4671 * them as an instance of the type we are testing against (if necessary), and |
| 4577 * extract the type argument by the index of the variable in the list of type | 4672 * extract the type argument by the index of the variable in the list of type |
| 4578 * variables for that class. | 4673 * variables for that class. |
| 4579 */ | 4674 */ |
| 4580 HInstruction readTypeVariable(ClassElement cls, | 4675 HInstruction readTypeVariable( |
| 4581 TypeVariableElement variable) { | 4676 ClassElement cls, |
| 4677 TypeVariableElement variable, |
| 4678 {SourceInformation sourceInformation}) { |
| 4582 assert(sourceElement.isInstanceMember); | 4679 assert(sourceElement.isInstanceMember); |
| 4583 | 4680 |
| 4584 HInstruction target = localsHandler.readThis(); | 4681 HInstruction target = localsHandler.readThis(); |
| 4585 HConstant index = graph.addConstantInt( | 4682 HConstant index = graph.addConstantInt( |
| 4586 RuntimeTypes.getTypeVariableIndex(variable), | 4683 RuntimeTypes.getTypeVariableIndex(variable), |
| 4587 compiler); | 4684 compiler); |
| 4588 | 4685 |
| 4589 if (needsSubstitutionForTypeVariableAccess(cls)) { | 4686 if (needsSubstitutionForTypeVariableAccess(cls)) { |
| 4590 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to | 4687 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to |
| 4591 // string concatenation in the implementation), and may prevent | 4688 // string concatenation in the implementation), and may prevent |
| 4592 // segmentation of '$'. | 4689 // segmentation of '$'. |
| 4593 String substitutionNameString = backend.namer.runtimeTypeName(cls); | 4690 String substitutionNameString = backend.namer.runtimeTypeName(cls); |
| 4594 HInstruction substitutionName = graph.addConstantString( | 4691 HInstruction substitutionName = graph.addConstantString( |
| 4595 new ast.LiteralDartString(substitutionNameString), compiler); | 4692 new ast.LiteralDartString(substitutionNameString), compiler); |
| 4596 pushInvokeStatic(null, | 4693 pushInvokeStatic(null, |
| 4597 backend.getGetRuntimeTypeArgument(), | 4694 backend.getGetRuntimeTypeArgument(), |
| 4598 [target, substitutionName, index], | 4695 [target, substitutionName, index], |
| 4599 typeMask: backend.dynamicType); | 4696 typeMask: backend.dynamicType, |
| 4697 sourceInformation: sourceInformation); |
| 4600 } else { | 4698 } else { |
| 4601 pushInvokeStatic(null, backend.getGetTypeArgumentByIndex(), | 4699 pushInvokeStatic( |
| 4700 null, |
| 4701 backend.getGetTypeArgumentByIndex(), |
| 4602 [target, index], | 4702 [target, index], |
| 4603 typeMask: backend.dynamicType); | 4703 typeMask: backend.dynamicType, |
| 4704 sourceInformation: sourceInformation); |
| 4604 } | 4705 } |
| 4605 return pop(); | 4706 return pop(); |
| 4606 } | 4707 } |
| 4607 | 4708 |
| 4608 // TODO(karlklose): this is needed to avoid a bug where the resolved type is | 4709 // TODO(karlklose): this is needed to avoid a bug where the resolved type is |
| 4609 // not stored on a type annotation in the closure translator. Remove when | 4710 // not stored on a type annotation in the closure translator. Remove when |
| 4610 // fixed. | 4711 // fixed. |
| 4611 bool hasDirectLocal(Local local) { | 4712 bool hasDirectLocal(Local local) { |
| 4612 return !localsHandler.isAccessedDirectly(local) || | 4713 return !localsHandler.isAccessedDirectly(local) || |
| 4613 localsHandler.directLocals[local] != null; | 4714 localsHandler.directLocals[local] != null; |
| 4614 } | 4715 } |
| 4615 | 4716 |
| 4616 /** | 4717 /** |
| 4617 * Helper to create an instruction that gets the value of a type variable. | 4718 * Helper to create an instruction that gets the value of a type variable. |
| 4618 */ | 4719 */ |
| 4619 HInstruction addTypeVariableReference(TypeVariableType type) { | 4720 HInstruction addTypeVariableReference( |
| 4721 TypeVariableType type, |
| 4722 {SourceInformation sourceInformation}) { |
| 4723 |
| 4620 assert(assertTypeInContext(type)); | 4724 assert(assertTypeInContext(type)); |
| 4621 Element member = sourceElement; | 4725 Element member = sourceElement; |
| 4622 bool isClosure = member.enclosingElement.isClosure; | 4726 bool isClosure = member.enclosingElement.isClosure; |
| 4623 if (isClosure) { | 4727 if (isClosure) { |
| 4624 ClosureClassElement closureClass = member.enclosingElement; | 4728 ClosureClassElement closureClass = member.enclosingElement; |
| 4625 member = closureClass.methodElement; | 4729 member = closureClass.methodElement; |
| 4626 member = member.outermostEnclosingMemberOrTopLevel; | 4730 member = member.outermostEnclosingMemberOrTopLevel; |
| 4627 } | 4731 } |
| 4628 bool isInConstructorContext = member.isConstructor || | 4732 bool isInConstructorContext = member.isConstructor || |
| 4629 member.isGenerativeConstructorBody; | 4733 member.isGenerativeConstructorBody; |
| 4630 Local typeVariableLocal = localsHandler.getTypeVariableAsLocal(type); | 4734 Local typeVariableLocal = localsHandler.getTypeVariableAsLocal(type); |
| 4631 if (isClosure) { | 4735 if (isClosure) { |
| 4632 if (member.isFactoryConstructor || | 4736 if (member.isFactoryConstructor || |
| 4633 (isInConstructorContext && hasDirectLocal(typeVariableLocal))) { | 4737 (isInConstructorContext && hasDirectLocal(typeVariableLocal))) { |
| 4634 // The type variable is used from a closure in a factory constructor. | 4738 // The type variable is used from a closure in a factory constructor. |
| 4635 // The value of the type argument is stored as a local on the closure | 4739 // The value of the type argument is stored as a local on the closure |
| 4636 // itself. | 4740 // itself. |
| 4637 return localsHandler.readLocal(typeVariableLocal); | 4741 return localsHandler.readLocal( |
| 4742 typeVariableLocal, sourceInformation: sourceInformation); |
| 4638 } else if (member.isFunction || | 4743 } else if (member.isFunction || |
| 4639 member.isGetter || | 4744 member.isGetter || |
| 4640 member.isSetter || | 4745 member.isSetter || |
| 4641 isInConstructorContext) { | 4746 isInConstructorContext) { |
| 4642 // The type variable is stored on the "enclosing object" and needs to be | 4747 // The type variable is stored on the "enclosing object" and needs to be |
| 4643 // accessed using the this-reference in the closure. | 4748 // accessed using the this-reference in the closure. |
| 4644 return readTypeVariable(member.enclosingClass, type.element); | 4749 return readTypeVariable( |
| 4750 member.enclosingClass, |
| 4751 type.element, |
| 4752 sourceInformation: sourceInformation); |
| 4645 } else { | 4753 } else { |
| 4646 assert(member.isField); | 4754 assert(member.isField); |
| 4647 // The type variable is stored in a parameter of the method. | 4755 // The type variable is stored in a parameter of the method. |
| 4648 return localsHandler.readLocal(typeVariableLocal); | 4756 return localsHandler.readLocal(typeVariableLocal); |
| 4649 } | 4757 } |
| 4650 } else if (isInConstructorContext || | 4758 } else if (isInConstructorContext || |
| 4651 // When [member] is a field, we can be either | 4759 // When [member] is a field, we can be either |
| 4652 // generating a checked setter or inlining its | 4760 // generating a checked setter or inlining its |
| 4653 // initializer in a constructor. An initializer is | 4761 // initializer in a constructor. An initializer is |
| 4654 // never built standalone, so [isBuildingFor] will | 4762 // never built standalone, so [isBuildingFor] will |
| 4655 // always return true when seeing one. | 4763 // always return true when seeing one. |
| 4656 (member.isField && !isBuildingFor(member))) { | 4764 (member.isField && !isBuildingFor(member))) { |
| 4657 // The type variable is stored in a parameter of the method. | 4765 // The type variable is stored in a parameter of the method. |
| 4658 return localsHandler.readLocal(typeVariableLocal); | 4766 return localsHandler.readLocal( |
| 4767 typeVariableLocal, sourceInformation: sourceInformation); |
| 4659 } else if (member.isInstanceMember) { | 4768 } else if (member.isInstanceMember) { |
| 4660 // The type variable is stored on the object. | 4769 // The type variable is stored on the object. |
| 4661 return readTypeVariable(member.enclosingClass, | 4770 return readTypeVariable( |
| 4662 type.element); | 4771 member.enclosingClass, |
| 4772 type.element, |
| 4773 sourceInformation: sourceInformation); |
| 4663 } else { | 4774 } else { |
| 4664 compiler.internalError(type.element, | 4775 compiler.internalError(type.element, |
| 4665 'Unexpected type variable in static context.'); | 4776 'Unexpected type variable in static context.'); |
| 4666 return null; | 4777 return null; |
| 4667 } | 4778 } |
| 4668 } | 4779 } |
| 4669 | 4780 |
| 4670 HInstruction analyzeTypeArgument(DartType argument) { | 4781 HInstruction analyzeTypeArgument( |
| 4782 DartType argument, |
| 4783 {SourceInformation sourceInformation}) { |
| 4784 |
| 4671 assert(assertTypeInContext(argument)); | 4785 assert(assertTypeInContext(argument)); |
| 4672 if (argument.treatAsDynamic) { | 4786 if (argument.treatAsDynamic) { |
| 4673 // Represent [dynamic] as [null]. | 4787 // Represent [dynamic] as [null]. |
| 4674 return graph.addConstantNull(compiler); | 4788 return graph.addConstantNull(compiler); |
| 4675 } | 4789 } |
| 4676 | 4790 |
| 4677 if (argument.isTypeVariable) { | 4791 if (argument.isTypeVariable) { |
| 4678 return addTypeVariableReference(argument); | 4792 return addTypeVariableReference( |
| 4793 argument, sourceInformation: sourceInformation); |
| 4679 } | 4794 } |
| 4680 | 4795 |
| 4681 List<HInstruction> inputs = <HInstruction>[]; | 4796 List<HInstruction> inputs = <HInstruction>[]; |
| 4682 | 4797 |
| 4683 js.Expression template = | 4798 js.Expression template = |
| 4684 rti.getTypeRepresentationWithPlaceholders(argument, (variable) { | 4799 rti.getTypeRepresentationWithPlaceholders(argument, (variable) { |
| 4685 inputs.add(addTypeVariableReference(variable)); | 4800 inputs.add(addTypeVariableReference(variable)); |
| 4686 }); | 4801 }); |
| 4687 | 4802 |
| 4688 js.Template code = new js.Template(null, template); | 4803 js.Template code = new js.Template(null, template); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4703 type.typeArguments.forEach((DartType argument) { | 4818 type.typeArguments.forEach((DartType argument) { |
| 4704 inputs.add(analyzeTypeArgument(argument)); | 4819 inputs.add(analyzeTypeArgument(argument)); |
| 4705 }); | 4820 }); |
| 4706 // TODO(15489): Register at codegen. | 4821 // TODO(15489): Register at codegen. |
| 4707 registry.registerInstantiatedType(type); | 4822 registry.registerInstantiatedType(type); |
| 4708 return callSetRuntimeTypeInfo(type.element, inputs, newObject); | 4823 return callSetRuntimeTypeInfo(type.element, inputs, newObject); |
| 4709 } | 4824 } |
| 4710 | 4825 |
| 4711 void copyRuntimeTypeInfo(HInstruction source, HInstruction target) { | 4826 void copyRuntimeTypeInfo(HInstruction source, HInstruction target) { |
| 4712 Element copyHelper = backend.getCopyTypeArguments(); | 4827 Element copyHelper = backend.getCopyTypeArguments(); |
| 4713 pushInvokeStatic(null, copyHelper, [source, target]); | 4828 pushInvokeStatic(null, copyHelper, [source, target], |
| 4829 sourceInformation: target.sourceInformation); |
| 4714 pop(); | 4830 pop(); |
| 4715 } | 4831 } |
| 4716 | 4832 |
| 4717 HInstruction callSetRuntimeTypeInfo(ClassElement element, | 4833 HInstruction callSetRuntimeTypeInfo(ClassElement element, |
| 4718 List<HInstruction> rtiInputs, | 4834 List<HInstruction> rtiInputs, |
| 4719 HInstruction newObject) { | 4835 HInstruction newObject) { |
| 4720 if (!backend.classNeedsRti(element) || element.typeVariables.isEmpty) { | 4836 if (!backend.classNeedsRti(element) || element.typeVariables.isEmpty) { |
| 4721 return newObject; | 4837 return newObject; |
| 4722 } | 4838 } |
| 4723 | 4839 |
| 4724 HInstruction typeInfo = buildLiteralList(rtiInputs); | 4840 HInstruction typeInfo = buildLiteralList(rtiInputs); |
| 4725 add(typeInfo); | 4841 add(typeInfo); |
| 4726 | 4842 |
| 4727 // Set the runtime type information on the object. | 4843 // Set the runtime type information on the object. |
| 4728 Element typeInfoSetterElement = backend.getSetRuntimeTypeInfo(); | 4844 Element typeInfoSetterElement = backend.getSetRuntimeTypeInfo(); |
| 4729 pushInvokeStatic( | 4845 pushInvokeStatic( |
| 4730 null, | 4846 null, |
| 4731 typeInfoSetterElement, | 4847 typeInfoSetterElement, |
| 4732 <HInstruction>[newObject, typeInfo], | 4848 <HInstruction>[newObject, typeInfo], |
| 4733 typeMask: backend.dynamicType); | 4849 typeMask: backend.dynamicType, |
| 4850 sourceInformation: newObject.sourceInformation); |
| 4734 | 4851 |
| 4735 // The new object will now be referenced through the | 4852 // The new object will now be referenced through the |
| 4736 // `setRuntimeTypeInfo` call. We therefore set the type of that | 4853 // `setRuntimeTypeInfo` call. We therefore set the type of that |
| 4737 // instruction to be of the object's type. | 4854 // instruction to be of the object's type. |
| 4738 assert(stack.last is HInvokeStatic || stack.last == newObject); | 4855 assert(stack.last is HInvokeStatic || stack.last == newObject); |
| 4739 stack.last.instructionType = newObject.instructionType; | 4856 stack.last.instructionType = newObject.instructionType; |
| 4740 return pop(); | 4857 return pop(); |
| 4741 } | 4858 } |
| 4742 | 4859 |
| 4743 handleNewSend(ast.NewExpression node) { | 4860 handleNewSend(ast.NewExpression node) { |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4878 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); | 4995 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); |
| 4879 // We set the instruction as [canThrow] to avoid it being dead code. | 4996 // We set the instruction as [canThrow] to avoid it being dead code. |
| 4880 // We need a finer grained side effect. | 4997 // We need a finer grained side effect. |
| 4881 add(new HForeignCode(code, backend.nullType, [stack.last], | 4998 add(new HForeignCode(code, backend.nullType, [stack.last], |
| 4882 throwBehavior: native.NativeThrowBehavior.MAY)); | 4999 throwBehavior: native.NativeThrowBehavior.MAY)); |
| 4883 } | 5000 } |
| 4884 } else if (isGrowableListConstructorCall) { | 5001 } else if (isGrowableListConstructorCall) { |
| 4885 push(buildLiteralList(<HInstruction>[])); | 5002 push(buildLiteralList(<HInstruction>[])); |
| 4886 stack.last.instructionType = elementType; | 5003 stack.last.instructionType = elementType; |
| 4887 } else { | 5004 } else { |
| 5005 SourceInformation sourceInformation = |
| 5006 sourceInformationBuilder.buildNew(send); |
| 4888 ClassElement cls = constructor.enclosingClass; | 5007 ClassElement cls = constructor.enclosingClass; |
| 4889 if (cls.isAbstract && constructor.isGenerativeConstructor) { | 5008 if (cls.isAbstract && constructor.isGenerativeConstructor) { |
| 4890 generateAbstractClassInstantiationError(send, cls.name); | 5009 generateAbstractClassInstantiationError(send, cls.name); |
| 4891 return; | 5010 return; |
| 4892 } | 5011 } |
| 4893 potentiallyAddTypeArguments(inputs, cls, expectedType); | 5012 potentiallyAddTypeArguments(inputs, cls, expectedType); |
| 4894 | 5013 |
| 4895 addInlinedInstantiation(expectedType); | 5014 addInlinedInstantiation(expectedType); |
| 4896 pushInvokeStatic(node, constructor, inputs, | 5015 pushInvokeStatic(node, constructor, inputs, |
| 4897 typeMask: elementType, instanceType: expectedType); | 5016 typeMask: elementType, |
| 5017 instanceType: expectedType, |
| 5018 sourceInformation: sourceInformation); |
| 4898 removeInlinedInstantiation(expectedType); | 5019 removeInlinedInstantiation(expectedType); |
| 4899 } | 5020 } |
| 4900 HInstruction newInstance = stack.last; | 5021 HInstruction newInstance = stack.last; |
| 4901 if (isFixedList) { | 5022 if (isFixedList) { |
| 4902 // Overwrite the element type, in case the allocation site has | 5023 // Overwrite the element type, in case the allocation site has |
| 4903 // been inlined. | 5024 // been inlined. |
| 4904 newInstance.instructionType = elementType; | 5025 newInstance.instructionType = elementType; |
| 4905 JavaScriptItemCompilationContext context = work.compilationContext; | 5026 JavaScriptItemCompilationContext context = work.compilationContext; |
| 4906 context.allocatedFixedLists.add(newInstance); | 5027 context.allocatedFixedLists.add(newInstance); |
| 4907 } | 5028 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4921 if (isRedirected) { | 5042 if (isRedirected) { |
| 4922 HInstruction checked = potentiallyCheckOrTrustType(newInstance, type); | 5043 HInstruction checked = potentiallyCheckOrTrustType(newInstance, type); |
| 4923 if (checked != newInstance) { | 5044 if (checked != newInstance) { |
| 4924 pop(); | 5045 pop(); |
| 4925 stack.add(checked); | 5046 stack.add(checked); |
| 4926 } | 5047 } |
| 4927 } | 5048 } |
| 4928 } | 5049 } |
| 4929 | 5050 |
| 4930 void potentiallyAddTypeArguments(List<HInstruction> inputs, ClassElement cls, | 5051 void potentiallyAddTypeArguments(List<HInstruction> inputs, ClassElement cls, |
| 4931 InterfaceType expectedType) { | 5052 InterfaceType expectedType, |
| 5053 {SourceInformation sourceInformation}) { |
| 4932 if (!backend.classNeedsRti(cls)) return; | 5054 if (!backend.classNeedsRti(cls)) return; |
| 4933 assert(expectedType.typeArguments.isEmpty || | 5055 assert(expectedType.typeArguments.isEmpty || |
| 4934 cls.typeVariables.length == expectedType.typeArguments.length); | 5056 cls.typeVariables.length == expectedType.typeArguments.length); |
| 4935 expectedType.typeArguments.forEach((DartType argument) { | 5057 expectedType.typeArguments.forEach((DartType argument) { |
| 4936 inputs.add(analyzeTypeArgument(argument)); | 5058 inputs.add(analyzeTypeArgument( |
| 5059 argument, sourceInformation: sourceInformation)); |
| 4937 }); | 5060 }); |
| 4938 } | 5061 } |
| 4939 | 5062 |
| 4940 /// In checked mode checks the [type] of [node] to be well-bounded. The method | 5063 /// In checked mode checks the [type] of [node] to be well-bounded. The method |
| 4941 /// returns [:true:] if an error can be statically determined. | 5064 /// returns [:true:] if an error can be statically determined. |
| 4942 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { | 5065 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { |
| 4943 if (!compiler.enableTypeAssertions) return false; | 5066 if (!compiler.enableTypeAssertions) return false; |
| 4944 | 5067 |
| 4945 Map<DartType, Set<DartType>> seenChecksMap = | 5068 Map<DartType, Set<DartType>> seenChecksMap = |
| 4946 new Map<DartType, Set<DartType>>(); | 5069 new Map<DartType, Set<DartType>>(); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5019 List<HInstruction> inputs = makeStaticArgumentList( | 5142 List<HInstruction> inputs = makeStaticArgumentList( |
| 5020 callStructure, | 5143 callStructure, |
| 5021 node.arguments, | 5144 node.arguments, |
| 5022 function.implementation); | 5145 function.implementation); |
| 5023 | 5146 |
| 5024 if (function == compiler.identicalFunction) { | 5147 if (function == compiler.identicalFunction) { |
| 5025 pushWithPosition( | 5148 pushWithPosition( |
| 5026 new HIdentity(inputs[0], inputs[1], null, backend.boolType), node); | 5149 new HIdentity(inputs[0], inputs[1], null, backend.boolType), node); |
| 5027 return; | 5150 return; |
| 5028 } else { | 5151 } else { |
| 5029 pushInvokeStatic(node, function, inputs); | 5152 pushInvokeStatic(node, function, inputs, |
| 5153 sourceInformation: sourceInformationBuilder.buildCall( |
| 5154 node, node.selector)); |
| 5030 } | 5155 } |
| 5031 } | 5156 } |
| 5032 | 5157 |
| 5033 /// Generate an invocation to a static or top level function with the wrong | 5158 /// Generate an invocation to a static or top level function with the wrong |
| 5034 /// number of arguments. | 5159 /// number of arguments. |
| 5035 void generateStaticFunctionIncompatibleInvoke(ast.Send node, | 5160 void generateStaticFunctionIncompatibleInvoke(ast.Send node, |
| 5036 Element element) { | 5161 Element element) { |
| 5037 generateWrongArgumentCountError(node, element, node.arguments); | 5162 generateWrongArgumentCountError(node, element, node.arguments); |
| 5038 } | 5163 } |
| 5039 | 5164 |
| 5040 @override | 5165 @override |
| 5041 void visitStaticFieldInvoke( | 5166 void visitStaticFieldInvoke( |
| 5042 ast.Send node, | 5167 ast.Send node, |
| 5043 FieldElement field, | 5168 FieldElement field, |
| 5044 ast.NodeList arguments, | 5169 ast.NodeList arguments, |
| 5045 CallStructure callStructure, | 5170 CallStructure callStructure, |
| 5046 _) { | 5171 _) { |
| 5047 generateStaticFieldGet(node, field); | 5172 generateStaticFieldGet(node, field); |
| 5048 generateCallInvoke(node, pop()); | 5173 generateCallInvoke( |
| 5174 node, |
| 5175 pop(), |
| 5176 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 5049 } | 5177 } |
| 5050 | 5178 |
| 5051 @override | 5179 @override |
| 5052 void visitStaticFunctionInvoke( | 5180 void visitStaticFunctionInvoke( |
| 5053 ast.Send node, | 5181 ast.Send node, |
| 5054 MethodElement function, | 5182 MethodElement function, |
| 5055 ast.NodeList arguments, | 5183 ast.NodeList arguments, |
| 5056 CallStructure callStructure, | 5184 CallStructure callStructure, |
| 5057 _) { | 5185 _) { |
| 5058 generateStaticFunctionInvoke(node, function, callStructure); | 5186 generateStaticFunctionInvoke(node, function, callStructure); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5069 } | 5197 } |
| 5070 | 5198 |
| 5071 @override | 5199 @override |
| 5072 void visitStaticGetterInvoke( | 5200 void visitStaticGetterInvoke( |
| 5073 ast.Send node, | 5201 ast.Send node, |
| 5074 FunctionElement getter, | 5202 FunctionElement getter, |
| 5075 ast.NodeList arguments, | 5203 ast.NodeList arguments, |
| 5076 CallStructure callStructure, | 5204 CallStructure callStructure, |
| 5077 _) { | 5205 _) { |
| 5078 generateStaticGetterGet(node, getter); | 5206 generateStaticGetterGet(node, getter); |
| 5079 generateCallInvoke(node, pop()); | 5207 generateCallInvoke( |
| 5208 node, |
| 5209 pop(), |
| 5210 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 5080 } | 5211 } |
| 5081 | 5212 |
| 5082 @override | 5213 @override |
| 5083 void visitTopLevelFieldInvoke( | 5214 void visitTopLevelFieldInvoke( |
| 5084 ast.Send node, | 5215 ast.Send node, |
| 5085 FieldElement field, | 5216 FieldElement field, |
| 5086 ast.NodeList arguments, | 5217 ast.NodeList arguments, |
| 5087 CallStructure callStructure, | 5218 CallStructure callStructure, |
| 5088 _) { | 5219 _) { |
| 5089 generateStaticFieldGet(node, field); | 5220 generateStaticFieldGet(node, field); |
| 5090 generateCallInvoke(node, pop()); | 5221 generateCallInvoke( |
| 5222 node, |
| 5223 pop(), |
| 5224 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 5091 } | 5225 } |
| 5092 | 5226 |
| 5093 @override | 5227 @override |
| 5094 void visitTopLevelFunctionInvoke( | 5228 void visitTopLevelFunctionInvoke( |
| 5095 ast.Send node, | 5229 ast.Send node, |
| 5096 MethodElement function, | 5230 MethodElement function, |
| 5097 ast.NodeList arguments, | 5231 ast.NodeList arguments, |
| 5098 CallStructure callStructure, | 5232 CallStructure callStructure, |
| 5099 _) { | 5233 _) { |
| 5100 if (backend.isForeign(function)) { | 5234 if (backend.isForeign(function)) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5115 } | 5249 } |
| 5116 | 5250 |
| 5117 @override | 5251 @override |
| 5118 void visitTopLevelGetterInvoke( | 5252 void visitTopLevelGetterInvoke( |
| 5119 ast.Send node, | 5253 ast.Send node, |
| 5120 FunctionElement getter, | 5254 FunctionElement getter, |
| 5121 ast.NodeList arguments, | 5255 ast.NodeList arguments, |
| 5122 CallStructure callStructure, | 5256 CallStructure callStructure, |
| 5123 _) { | 5257 _) { |
| 5124 generateStaticGetterGet(node, getter); | 5258 generateStaticGetterGet(node, getter); |
| 5125 generateCallInvoke(node, pop()); | 5259 generateCallInvoke( |
| 5260 node, |
| 5261 pop(), |
| 5262 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 5126 } | 5263 } |
| 5127 | 5264 |
| 5128 @override | 5265 @override |
| 5129 void visitTopLevelSetterGet( | 5266 void visitTopLevelSetterGet( |
| 5130 ast.Send node, | 5267 ast.Send node, |
| 5131 MethodElement setter, | 5268 MethodElement setter, |
| 5132 _) { | 5269 _) { |
| 5133 handleInvalidStaticGet(node, setter); | 5270 handleInvalidStaticGet(node, setter); |
| 5134 } | 5271 } |
| 5135 | 5272 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5277 stack.add(addConstant(node.selector)); | 5414 stack.add(addConstant(node.selector)); |
| 5278 } else { | 5415 } else { |
| 5279 stack.add(addConstant(node)); | 5416 stack.add(addConstant(node)); |
| 5280 } | 5417 } |
| 5281 } | 5418 } |
| 5282 | 5419 |
| 5283 /// Generate the literal for [typeVariable] in the current context. | 5420 /// Generate the literal for [typeVariable] in the current context. |
| 5284 void generateTypeVariableLiteral(ast.Send node, | 5421 void generateTypeVariableLiteral(ast.Send node, |
| 5285 TypeVariableType typeVariable) { | 5422 TypeVariableType typeVariable) { |
| 5286 DartType type = localsHandler.substInContext(typeVariable); | 5423 DartType type = localsHandler.substInContext(typeVariable); |
| 5287 HInstruction value = analyzeTypeArgument(type); | 5424 HInstruction value = analyzeTypeArgument(type, |
| 5425 sourceInformation: sourceInformationBuilder.buildGet(node)); |
| 5288 pushInvokeStatic(node, | 5426 pushInvokeStatic(node, |
| 5289 backend.getRuntimeTypeToString(), | 5427 backend.getRuntimeTypeToString(), |
| 5290 [value], | 5428 [value], |
| 5291 typeMask: backend.stringType); | 5429 typeMask: backend.stringType); |
| 5292 pushInvokeStatic(node, | 5430 pushInvokeStatic(node, |
| 5293 backend.getCreateRuntimeType(), | 5431 backend.getCreateRuntimeType(), |
| 5294 [pop()]); | 5432 [pop()]); |
| 5295 } | 5433 } |
| 5296 | 5434 |
| 5297 /// Generate a call to a type literal. | 5435 /// Generate a call to a type literal. |
| 5298 void generateTypeLiteralCall(ast.Send node) { | 5436 void generateTypeLiteralCall(ast.Send node) { |
| 5299 // This send is of the form 'e(...)', where e is resolved to a type | 5437 // This send is of the form 'e(...)', where e is resolved to a type |
| 5300 // reference. We create a regular closure call on the result of the type | 5438 // reference. We create a regular closure call on the result of the type |
| 5301 // reference instead of creating a NoSuchMethodError to avoid pulling it | 5439 // reference instead of creating a NoSuchMethodError to avoid pulling it |
| 5302 // in if it is not used (e.g., in a try/catch). | 5440 // in if it is not used (e.g., in a try/catch). |
| 5303 HInstruction target = pop(); | 5441 HInstruction target = pop(); |
| 5304 generateCallInvoke(node, target); | 5442 generateCallInvoke(node, target, |
| 5443 sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
| 5305 } | 5444 } |
| 5306 | 5445 |
| 5307 /// Generate a '.call' invocation on [target]. | 5446 /// Generate a '.call' invocation on [target]. |
| 5308 void generateCallInvoke(ast.Send node, HInstruction target) { | 5447 void generateCallInvoke(ast.Send node, |
| 5448 HInstruction target, |
| 5449 SourceInformation sourceInformation) { |
| 5309 Selector selector = elements.getSelector(node); | 5450 Selector selector = elements.getSelector(node); |
| 5310 List<HInstruction> inputs = <HInstruction>[target]; | 5451 List<HInstruction> inputs = <HInstruction>[target]; |
| 5311 addDynamicSendArgumentsToList(node, inputs); | 5452 addDynamicSendArgumentsToList(node, inputs); |
| 5312 Selector closureSelector = new Selector.callClosureFrom(selector); | 5453 Selector closureSelector = new Selector.callClosureFrom(selector); |
| 5313 pushWithPosition( | 5454 push(new HInvokeClosure(closureSelector, inputs, backend.dynamicType) |
| 5314 new HInvokeClosure(closureSelector, inputs, backend.dynamicType), node); | 5455 ..sourceInformation = sourceInformation); |
| 5315 } | 5456 } |
| 5316 | 5457 |
| 5317 visitGetterSend(ast.Send node) { | 5458 visitGetterSend(ast.Send node) { |
| 5318 internalError(node, "Unexpected visitGetterSend"); | 5459 internalError(node, "Unexpected visitGetterSend"); |
| 5319 } | 5460 } |
| 5320 | 5461 |
| 5321 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. | 5462 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. |
| 5322 internalError(Spannable node, String reason) { | 5463 internalError(Spannable node, String reason) { |
| 5323 compiler.internalError(node, reason); | 5464 compiler.internalError(node, reason); |
| 5324 } | 5465 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5339 void generateAbstractClassInstantiationError(ast.Node node, String message) { | 5480 void generateAbstractClassInstantiationError(ast.Node node, String message) { |
| 5340 generateError(node, | 5481 generateError(node, |
| 5341 message, | 5482 message, |
| 5342 backend.getThrowAbstractClassInstantiationError()); | 5483 backend.getThrowAbstractClassInstantiationError()); |
| 5343 } | 5484 } |
| 5344 | 5485 |
| 5345 void generateThrowNoSuchMethod(ast.Node diagnosticNode, | 5486 void generateThrowNoSuchMethod(ast.Node diagnosticNode, |
| 5346 String methodName, | 5487 String methodName, |
| 5347 {Link<ast.Node> argumentNodes, | 5488 {Link<ast.Node> argumentNodes, |
| 5348 List<HInstruction> argumentValues, | 5489 List<HInstruction> argumentValues, |
| 5349 List<String> existingArguments}) { | 5490 List<String> existingArguments, |
| 5491 SourceInformation sourceInformation}) { |
| 5350 Element helper = backend.getThrowNoSuchMethod(); | 5492 Element helper = backend.getThrowNoSuchMethod(); |
| 5351 ConstantValue receiverConstant = | 5493 ConstantValue receiverConstant = |
| 5352 constantSystem.createString(new ast.DartString.empty()); | 5494 constantSystem.createString(new ast.DartString.empty()); |
| 5353 HInstruction receiver = graph.addConstant(receiverConstant, compiler); | 5495 HInstruction receiver = graph.addConstant(receiverConstant, compiler); |
| 5354 ast.DartString dartString = new ast.DartString.literal(methodName); | 5496 ast.DartString dartString = new ast.DartString.literal(methodName); |
| 5355 ConstantValue nameConstant = constantSystem.createString(dartString); | 5497 ConstantValue nameConstant = constantSystem.createString(dartString); |
| 5356 HInstruction name = graph.addConstant(nameConstant, compiler); | 5498 HInstruction name = graph.addConstant(nameConstant, compiler); |
| 5357 if (argumentValues == null) { | 5499 if (argumentValues == null) { |
| 5358 argumentValues = <HInstruction>[]; | 5500 argumentValues = <HInstruction>[]; |
| 5359 argumentNodes.forEach((argumentNode) { | 5501 argumentNodes.forEach((argumentNode) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5372 graph.addConstantString(new ast.DartString.literal(name), compiler); | 5514 graph.addConstantString(new ast.DartString.literal(name), compiler); |
| 5373 existingNames.add(nameConstant); | 5515 existingNames.add(nameConstant); |
| 5374 } | 5516 } |
| 5375 existingNamesList = buildLiteralList(existingNames); | 5517 existingNamesList = buildLiteralList(existingNames); |
| 5376 add(existingNamesList); | 5518 add(existingNamesList); |
| 5377 } else { | 5519 } else { |
| 5378 existingNamesList = graph.addConstantNull(compiler); | 5520 existingNamesList = graph.addConstantNull(compiler); |
| 5379 } | 5521 } |
| 5380 pushInvokeStatic(diagnosticNode, | 5522 pushInvokeStatic(diagnosticNode, |
| 5381 helper, | 5523 helper, |
| 5382 [receiver, name, arguments, existingNamesList]); | 5524 [receiver, name, arguments, existingNamesList], |
| 5525 sourceInformation: sourceInformation); |
| 5383 } | 5526 } |
| 5384 | 5527 |
| 5385 /** | 5528 /** |
| 5386 * Generate code to throw a [NoSuchMethodError] exception for calling a | 5529 * Generate code to throw a [NoSuchMethodError] exception for calling a |
| 5387 * method with a wrong number of arguments or mismatching named optional | 5530 * method with a wrong number of arguments or mismatching named optional |
| 5388 * arguments. | 5531 * arguments. |
| 5389 */ | 5532 */ |
| 5390 void generateWrongArgumentCountError(ast.Node diagnosticNode, | 5533 void generateWrongArgumentCountError(ast.Node diagnosticNode, |
| 5391 FunctionElement function, | 5534 FunctionElement function, |
| 5392 Link<ast.Node> argumentNodes) { | 5535 Link<ast.Node> argumentNodes) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5434 registry.registerConstSymbol(nameString); | 5577 registry.registerConstSymbol(nameString); |
| 5435 } | 5578 } |
| 5436 } else { | 5579 } else { |
| 5437 handleNewSend(node); | 5580 handleNewSend(node); |
| 5438 } | 5581 } |
| 5439 } | 5582 } |
| 5440 | 5583 |
| 5441 void pushInvokeDynamic(ast.Node node, | 5584 void pushInvokeDynamic(ast.Node node, |
| 5442 Selector selector, | 5585 Selector selector, |
| 5443 List<HInstruction> arguments, | 5586 List<HInstruction> arguments, |
| 5444 {ast.Node location}) { | 5587 {SourceInformation sourceInformation}) { |
| 5445 if (location == null) location = node; | |
| 5446 | 5588 |
| 5447 // We prefer to not inline certain operations on indexables, | 5589 // We prefer to not inline certain operations on indexables, |
| 5448 // because the constant folder will handle them better and turn | 5590 // because the constant folder will handle them better and turn |
| 5449 // them into simpler instructions that allow further | 5591 // them into simpler instructions that allow further |
| 5450 // optimizations. | 5592 // optimizations. |
| 5451 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { | 5593 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { |
| 5452 bool isLength = selector.isGetter | 5594 bool isLength = selector.isGetter |
| 5453 && selector.name == "length"; | 5595 && selector.name == "length"; |
| 5454 if (isLength || selector.isIndex) { | 5596 if (isLength || selector.isIndex) { |
| 5455 TypeMask type = new TypeMask.nonNullExact( | 5597 TypeMask type = new TypeMask.nonNullExact( |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5493 | 5635 |
| 5494 HInstruction receiver = arguments[0]; | 5636 HInstruction receiver = arguments[0]; |
| 5495 List<HInstruction> inputs = <HInstruction>[]; | 5637 List<HInstruction> inputs = <HInstruction>[]; |
| 5496 bool isIntercepted = backend.isInterceptedSelector(selector); | 5638 bool isIntercepted = backend.isInterceptedSelector(selector); |
| 5497 if (isIntercepted) { | 5639 if (isIntercepted) { |
| 5498 inputs.add(invokeInterceptor(receiver)); | 5640 inputs.add(invokeInterceptor(receiver)); |
| 5499 } | 5641 } |
| 5500 inputs.addAll(arguments); | 5642 inputs.addAll(arguments); |
| 5501 TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler); | 5643 TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler); |
| 5502 if (selector.isGetter) { | 5644 if (selector.isGetter) { |
| 5503 pushWithPosition( | 5645 push( |
| 5504 new HInvokeDynamicGetter(selector, null, inputs, type), | 5646 new HInvokeDynamicGetter(selector, null, inputs, type) |
| 5505 location); | 5647 ..sourceInformation = sourceInformation); |
| 5506 } else if (selector.isSetter) { | 5648 } else if (selector.isSetter) { |
| 5507 pushWithPosition( | 5649 push( |
| 5508 new HInvokeDynamicSetter(selector, null, inputs, type), | 5650 new HInvokeDynamicSetter(selector, null, inputs, type) |
| 5509 location); | 5651 ..sourceInformation = sourceInformation); |
| 5510 } else { | 5652 } else { |
| 5511 pushWithPosition( | 5653 push( |
| 5512 new HInvokeDynamicMethod(selector, inputs, type, isIntercepted), | 5654 new HInvokeDynamicMethod(selector, inputs, type, isIntercepted) |
| 5513 location); | 5655 ..sourceInformation = sourceInformation); |
| 5514 } | 5656 } |
| 5515 } | 5657 } |
| 5516 | 5658 |
| 5517 void pushInvokeStatic(ast.Node location, | 5659 void pushInvokeStatic(ast.Node location, |
| 5518 Element element, | 5660 Element element, |
| 5519 List<HInstruction> arguments, | 5661 List<HInstruction> arguments, |
| 5520 {TypeMask typeMask, | 5662 {TypeMask typeMask, |
| 5521 InterfaceType instanceType}) { | 5663 InterfaceType instanceType, |
| 5664 SourceInformation sourceInformation}) { |
| 5665 // TODO(johnniwinther): Use [sourceInformation] instead of [location]. |
| 5522 if (tryInlineMethod(element, null, arguments, location, | 5666 if (tryInlineMethod(element, null, arguments, location, |
| 5523 instanceType: instanceType)) { | 5667 instanceType: instanceType)) { |
| 5524 return; | 5668 return; |
| 5525 } | 5669 } |
| 5526 | 5670 |
| 5527 if (typeMask == null) { | 5671 if (typeMask == null) { |
| 5528 typeMask = | 5672 typeMask = |
| 5529 TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 5673 TypeMaskFactory.inferredReturnTypeForElement(element, compiler); |
| 5530 } | 5674 } |
| 5531 bool targetCanThrow = !compiler.world.getCannotThrow(element); | 5675 bool targetCanThrow = !compiler.world.getCannotThrow(element); |
| 5532 // TODO(5346): Try to avoid the need for calling [declaration] before | 5676 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 5533 // creating an [HInvokeStatic]. | 5677 // creating an [HInvokeStatic]. |
| 5534 HInvokeStatic instruction = new HInvokeStatic( | 5678 HInvokeStatic instruction = new HInvokeStatic( |
| 5535 element.declaration, arguments, typeMask, | 5679 element.declaration, arguments, typeMask, |
| 5536 targetCanThrow: targetCanThrow); | 5680 targetCanThrow: targetCanThrow) |
| 5681 ..sourceInformation = sourceInformation; |
| 5537 if (!currentInlinedInstantiations.isEmpty) { | 5682 if (!currentInlinedInstantiations.isEmpty) { |
| 5538 instruction.instantiatedTypes = new List<DartType>.from( | 5683 instruction.instantiatedTypes = new List<DartType>.from( |
| 5539 currentInlinedInstantiations); | 5684 currentInlinedInstantiations); |
| 5540 } | 5685 } |
| 5541 instruction.sideEffects = compiler.world.getSideEffectsOfElement(element); | 5686 instruction.sideEffects = compiler.world.getSideEffectsOfElement(element); |
| 5542 if (location == null) { | 5687 if (location == null) { |
| 5543 push(instruction); | 5688 push(instruction); |
| 5544 } else { | 5689 } else { |
| 5545 pushWithPosition(instruction, location); | 5690 pushWithPosition(instruction, location); |
| 5546 } | 5691 } |
| 5547 } | 5692 } |
| 5548 | 5693 |
| 5549 HInstruction buildInvokeSuper(Selector selector, | 5694 HInstruction buildInvokeSuper(Selector selector, |
| 5550 Element element, | 5695 Element element, |
| 5551 List<HInstruction> arguments) { | 5696 List<HInstruction> arguments, |
| 5697 [SourceInformation sourceInformation]) { |
| 5552 HInstruction receiver = localsHandler.readThis(); | 5698 HInstruction receiver = localsHandler.readThis(); |
| 5553 // TODO(5346): Try to avoid the need for calling [declaration] before | 5699 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 5554 // creating an [HStatic]. | 5700 // creating an [HStatic]. |
| 5555 List<HInstruction> inputs = <HInstruction>[]; | 5701 List<HInstruction> inputs = <HInstruction>[]; |
| 5556 if (backend.isInterceptedSelector(selector) && | 5702 if (backend.isInterceptedSelector(selector) && |
| 5557 // Fields don't need an interceptor; consider generating HFieldGet/Set | 5703 // Fields don't need an interceptor; consider generating HFieldGet/Set |
| 5558 // instead. | 5704 // instead. |
| 5559 element.kind != ElementKind.FIELD) { | 5705 element.kind != ElementKind.FIELD) { |
| 5560 inputs.add(invokeInterceptor(receiver)); | 5706 inputs.add(invokeInterceptor(receiver)); |
| 5561 } | 5707 } |
| 5562 inputs.add(receiver); | 5708 inputs.add(receiver); |
| 5563 inputs.addAll(arguments); | 5709 inputs.addAll(arguments); |
| 5564 TypeMask type; | 5710 TypeMask type; |
| 5565 if (!element.isGetter && selector.isGetter) { | 5711 if (!element.isGetter && selector.isGetter) { |
| 5566 type = TypeMaskFactory.inferredTypeForElement(element, compiler); | 5712 type = TypeMaskFactory.inferredTypeForElement(element, compiler); |
| 5567 } else { | 5713 } else { |
| 5568 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 5714 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); |
| 5569 } | 5715 } |
| 5570 HInstruction instruction = new HInvokeSuper( | 5716 HInstruction instruction = new HInvokeSuper( |
| 5571 element, | 5717 element, |
| 5572 currentNonClosureClass, | 5718 currentNonClosureClass, |
| 5573 selector, | 5719 selector, |
| 5574 inputs, | 5720 inputs, |
| 5575 type, | 5721 type, |
| 5722 sourceInformation, |
| 5576 isSetter: selector.isSetter || selector.isIndexSet); | 5723 isSetter: selector.isSetter || selector.isIndexSet); |
| 5577 instruction.sideEffects = compiler.world.getSideEffectsOfSelector(selector); | 5724 instruction.sideEffects = compiler.world.getSideEffectsOfSelector(selector); |
| 5578 return instruction; | 5725 return instruction; |
| 5579 } | 5726 } |
| 5580 | 5727 |
| 5581 void handleComplexOperatorSend(ast.SendSet node, | 5728 void handleComplexOperatorSend(ast.SendSet node, |
| 5582 HInstruction receiver, | 5729 HInstruction receiver, |
| 5583 Link<ast.Node> arguments) { | 5730 Link<ast.Node> arguments) { |
| 5584 HInstruction rhs; | 5731 HInstruction rhs; |
| 5585 if (node.isPrefix || node.isPostfix) { | 5732 if (node.isPrefix || node.isPostfix) { |
| 5586 rhs = graph.addConstantInt(1, compiler); | 5733 rhs = graph.addConstantInt(1, compiler); |
| 5587 } else { | 5734 } else { |
| 5588 visit(arguments.head); | 5735 visit(arguments.head); |
| 5589 assert(arguments.tail.isEmpty); | 5736 assert(arguments.tail.isEmpty); |
| 5590 rhs = pop(); | 5737 rhs = pop(); |
| 5591 } | 5738 } |
| 5592 visitBinarySend(receiver, rhs, | 5739 visitBinarySend( |
| 5593 elements.getOperatorSelectorInComplexSendSet(node), | 5740 receiver, |
| 5594 node, | 5741 rhs, |
| 5595 location: node.assignmentOperator); | 5742 elements.getOperatorSelectorInComplexSendSet(node), |
| 5743 node, |
| 5744 sourceInformation: |
| 5745 sourceInformationBuilder.buildGeneric(node.assignmentOperator)); |
| 5596 } | 5746 } |
| 5597 | 5747 |
| 5598 void handleSuperSendSet(ast.SendSet node) { | 5748 void handleSuperSendSet(ast.SendSet node) { |
| 5599 Element element = elements[node]; | 5749 Element element = elements[node]; |
| 5600 List<HInstruction> setterInputs = <HInstruction>[]; | 5750 List<HInstruction> setterInputs = <HInstruction>[]; |
| 5601 void generateSuperSendSet() { | 5751 void generateSuperSendSet() { |
| 5602 Selector setterSelector = elements.getSelector(node); | 5752 Selector setterSelector = elements.getSelector(node); |
| 5603 if (Elements.isUnresolved(element) | 5753 if (Elements.isUnresolved(element) |
| 5604 || !setterSelector.applies(element, compiler.world)) { | 5754 || !setterSelector.applies(element, compiler.world)) { |
| 5605 generateSuperNoSuchMethodSend( | 5755 generateSuperNoSuchMethodSend( |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6038 | 6188 |
| 6039 if (getter.isErroneous) { | 6189 if (getter.isErroneous) { |
| 6040 generateStaticUnresolvedGet(node, getter); | 6190 generateStaticUnresolvedGet(node, getter); |
| 6041 } else if (getter.isField) { | 6191 } else if (getter.isField) { |
| 6042 generateStaticFieldGet(node, getter); | 6192 generateStaticFieldGet(node, getter); |
| 6043 } else if (getter.isGetter) { | 6193 } else if (getter.isGetter) { |
| 6044 generateStaticGetterGet(node, getter); | 6194 generateStaticGetterGet(node, getter); |
| 6045 } else if (getter.isFunction) { | 6195 } else if (getter.isFunction) { |
| 6046 generateStaticFunctionGet(node, getter); | 6196 generateStaticFunctionGet(node, getter); |
| 6047 } else if (getter.isLocal) { | 6197 } else if (getter.isLocal) { |
| 6048 handleLocalGet(getter); | 6198 handleLocalGet(node, getter); |
| 6049 } else { | 6199 } else { |
| 6050 internalError(node, "Unexpected getter: $getter"); | 6200 internalError(node, "Unexpected getter: $getter"); |
| 6051 } | 6201 } |
| 6052 HInstruction getterInstruction = pop(); | 6202 HInstruction getterInstruction = pop(); |
| 6053 if (node.isIfNullAssignment) { | 6203 if (node.isIfNullAssignment) { |
| 6054 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); | 6204 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); |
| 6055 brancher.handleIfNull(() => stack.add(getterInstruction), | 6205 brancher.handleIfNull(() => stack.add(getterInstruction), |
| 6056 () { | 6206 () { |
| 6057 visit(node.arguments.head); | 6207 visit(node.arguments.head); |
| 6058 generateNonInstanceSetter(node, element, pop()); | 6208 generateNonInstanceSetter(node, element, pop()); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6169 } | 6319 } |
| 6170 | 6320 |
| 6171 visitRethrow(ast.Rethrow node) { | 6321 visitRethrow(ast.Rethrow node) { |
| 6172 HInstruction exception = rethrowableException; | 6322 HInstruction exception = rethrowableException; |
| 6173 if (exception == null) { | 6323 if (exception == null) { |
| 6174 exception = graph.addConstantNull(compiler); | 6324 exception = graph.addConstantNull(compiler); |
| 6175 compiler.internalError(node, | 6325 compiler.internalError(node, |
| 6176 'rethrowableException should not be null.'); | 6326 'rethrowableException should not be null.'); |
| 6177 } | 6327 } |
| 6178 handleInTryStatement(); | 6328 handleInTryStatement(); |
| 6179 closeAndGotoExit(new HThrow(exception, isRethrow: true)); | 6329 closeAndGotoExit( |
| 6330 new HThrow(exception, |
| 6331 sourceInformationBuilder.buildThrow(node), |
| 6332 isRethrow: true)); |
| 6180 } | 6333 } |
| 6181 | 6334 |
| 6182 visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { | 6335 visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { |
| 6183 ConstructorElement targetConstructor = | 6336 ConstructorElement targetConstructor = |
| 6184 elements.getRedirectingTargetConstructor(node).implementation; | 6337 elements.getRedirectingTargetConstructor(node).implementation; |
| 6185 ConstructorElement redirectingConstructor = sourceElement.implementation; | 6338 ConstructorElement redirectingConstructor = sourceElement.implementation; |
| 6186 List<HInstruction> inputs = <HInstruction>[]; | 6339 List<HInstruction> inputs = <HInstruction>[]; |
| 6187 FunctionSignature targetSignature = targetConstructor.functionSignature; | 6340 FunctionSignature targetSignature = targetConstructor.functionSignature; |
| 6188 FunctionSignature redirectingSignature = | 6341 FunctionSignature redirectingSignature = |
| 6189 redirectingConstructor.functionSignature; | 6342 redirectingConstructor.functionSignature; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6266 } | 6419 } |
| 6267 | 6420 |
| 6268 handleInTryStatement(); | 6421 handleInTryStatement(); |
| 6269 emitReturn(value, node); | 6422 emitReturn(value, node); |
| 6270 } | 6423 } |
| 6271 | 6424 |
| 6272 visitThrow(ast.Throw node) { | 6425 visitThrow(ast.Throw node) { |
| 6273 visitThrowExpression(node.expression); | 6426 visitThrowExpression(node.expression); |
| 6274 if (isReachable) { | 6427 if (isReachable) { |
| 6275 handleInTryStatement(); | 6428 handleInTryStatement(); |
| 6276 push(new HThrowExpression(pop())); | 6429 push(new HThrowExpression( |
| 6430 pop(), sourceInformationBuilder.buildThrow(node))); |
| 6277 isReachable = false; | 6431 isReachable = false; |
| 6278 } | 6432 } |
| 6279 } | 6433 } |
| 6280 | 6434 |
| 6281 visitYield(ast.Yield node) { | 6435 visitYield(ast.Yield node) { |
| 6282 visit(node.expression); | 6436 visit(node.expression); |
| 6283 HInstruction yielded = pop(); | 6437 HInstruction yielded = pop(); |
| 6284 add(new HYield(yielded, node.hasStar)); | 6438 add(new HYield(yielded, node.hasStar)); |
| 6285 } | 6439 } |
| 6286 | 6440 |
| (...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7030 // If the switch statement has no default case, surround the loop with | 7184 // If the switch statement has no default case, surround the loop with |
| 7031 // a test of the target. | 7185 // a test of the target. |
| 7032 void buildCondition() { | 7186 void buildCondition() { |
| 7033 js.Template code = js.js.parseForeignJS('#'); | 7187 js.Template code = js.js.parseForeignJS('#'); |
| 7034 push(new HForeignCode( | 7188 push(new HForeignCode( |
| 7035 code, | 7189 code, |
| 7036 backend.boolType, | 7190 backend.boolType, |
| 7037 [localsHandler.readLocal(switchTarget)], | 7191 [localsHandler.readLocal(switchTarget)], |
| 7038 nativeBehavior: native.NativeBehavior.PURE)); | 7192 nativeBehavior: native.NativeBehavior.PURE)); |
| 7039 } | 7193 } |
| 7040 handleIf(node, buildCondition, buildLoop, () => {}); | 7194 handleIf(node, |
| 7195 visitCondition: buildCondition, |
| 7196 visitThen: buildLoop, |
| 7197 visitElse: () => {}); |
| 7041 } | 7198 } |
| 7042 } | 7199 } |
| 7043 | 7200 |
| 7044 /** | 7201 /** |
| 7045 * Creates a switch statement. | 7202 * Creates a switch statement. |
| 7046 * | 7203 * |
| 7047 * [jumpHandler] is the [JumpHandler] for the created switch statement. | 7204 * [jumpHandler] is the [JumpHandler] for the created switch statement. |
| 7048 * [buildExpression] creates the switch expression. | 7205 * [buildExpression] creates the switch expression. |
| 7049 * [switchCases] must be either an [Iterable] of [ast.SwitchCase] nodes or | 7206 * [switchCases] must be either an [Iterable] of [ast.SwitchCase] nodes or |
| 7050 * a [Link] or a [ast.NodeList] of [ast.SwitchCase] nodes. | 7207 * a [Link] or a [ast.NodeList] of [ast.SwitchCase] nodes. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7093 expressionEnd.addSuccessor(block); | 7250 expressionEnd.addSuccessor(block); |
| 7094 hasDefault = true; | 7251 hasDefault = true; |
| 7095 } | 7252 } |
| 7096 open(block); | 7253 open(block); |
| 7097 localsHandler = new LocalsHandler.from(savedLocals); | 7254 localsHandler = new LocalsHandler.from(savedLocals); |
| 7098 buildSwitchCase(switchCase); | 7255 buildSwitchCase(switchCase); |
| 7099 if (!isAborted()) { | 7256 if (!isAborted()) { |
| 7100 if (caseIterator.hasNext) { | 7257 if (caseIterator.hasNext) { |
| 7101 pushInvokeStatic(switchCase, getFallThroughErrorElement, []); | 7258 pushInvokeStatic(switchCase, getFallThroughErrorElement, []); |
| 7102 HInstruction error = pop(); | 7259 HInstruction error = pop(); |
| 7103 closeAndGotoExit(new HThrow(error)); | 7260 closeAndGotoExit(new HThrow(error, error.sourceInformation)); |
| 7104 } else if (!isDefaultCase(switchCase)) { | 7261 } else if (!isDefaultCase(switchCase)) { |
| 7105 // If there is no default, we will add one later to avoid | 7262 // If there is no default, we will add one later to avoid |
| 7106 // the critical edge. So we generate a break statement to make | 7263 // the critical edge. So we generate a break statement to make |
| 7107 // sure the last case does not fall through to the default case. | 7264 // sure the last case does not fall through to the default case. |
| 7108 jumpHandler.generateBreak(); | 7265 jumpHandler.generateBreak(); |
| 7109 } | 7266 } |
| 7110 } | 7267 } |
| 7111 statements.add( | 7268 statements.add( |
| 7112 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock))); | 7269 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock))); |
| 7113 } | 7270 } |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7369 pushInvokeStatic(trace, backend.getTraceFromException(), [exception]); | 7526 pushInvokeStatic(trace, backend.getTraceFromException(), [exception]); |
| 7370 HInstruction traceInstruction = pop(); | 7527 HInstruction traceInstruction = pop(); |
| 7371 LocalVariableElement traceVariable = elements[trace]; | 7528 LocalVariableElement traceVariable = elements[trace]; |
| 7372 localsHandler.updateLocal(traceVariable, traceInstruction); | 7529 localsHandler.updateLocal(traceVariable, traceInstruction); |
| 7373 } | 7530 } |
| 7374 visit(catchBlock); | 7531 visit(catchBlock); |
| 7375 } | 7532 } |
| 7376 | 7533 |
| 7377 void visitElse() { | 7534 void visitElse() { |
| 7378 if (link.isEmpty) { | 7535 if (link.isEmpty) { |
| 7379 closeAndGotoExit(new HThrow(exception, isRethrow: true)); | 7536 closeAndGotoExit( |
| 7537 new HThrow(exception, |
| 7538 exception.sourceInformation, |
| 7539 isRethrow: true)); |
| 7380 } else { | 7540 } else { |
| 7381 ast.CatchBlock newBlock = link.head; | 7541 ast.CatchBlock newBlock = link.head; |
| 7382 handleIf(node, | 7542 handleIf(node, |
| 7383 () { pushCondition(newBlock); }, | 7543 visitCondition: () { pushCondition(newBlock); }, |
| 7384 visitThen, visitElse); | 7544 visitThen: visitThen, |
| 7545 visitElse: visitElse); |
| 7385 } | 7546 } |
| 7386 } | 7547 } |
| 7387 | 7548 |
| 7388 ast.CatchBlock firstBlock = link.head; | 7549 ast.CatchBlock firstBlock = link.head; |
| 7389 handleIf(node, () { pushCondition(firstBlock); }, visitThen, visitElse); | 7550 handleIf(node, |
| 7551 visitCondition: () { pushCondition(firstBlock); }, |
| 7552 visitThen: visitThen, |
| 7553 visitElse: visitElse); |
| 7390 if (!isAborted()) endCatchBlock = close(new HGoto()); | 7554 if (!isAborted()) endCatchBlock = close(new HGoto()); |
| 7391 | 7555 |
| 7392 rethrowableException = oldRethrowableException; | 7556 rethrowableException = oldRethrowableException; |
| 7393 tryInstruction.catchBlock = startCatchBlock; | 7557 tryInstruction.catchBlock = startCatchBlock; |
| 7394 catchGraph = new SubGraph(startCatchBlock, lastOpenedBlock); | 7558 catchGraph = new SubGraph(startCatchBlock, lastOpenedBlock); |
| 7395 } | 7559 } |
| 7396 | 7560 |
| 7397 SubGraph finallyGraph = null; | 7561 SubGraph finallyGraph = null; |
| 7398 if (node.finallyBlock != null) { | 7562 if (node.finallyBlock != null) { |
| 7399 localsHandler = new LocalsHandler.from(savedLocals); | 7563 localsHandler = new LocalsHandler.from(savedLocals); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7510 restoreState(state); | 7674 restoreState(state); |
| 7511 stack.add(result); | 7675 stack.add(result); |
| 7512 } | 7676 } |
| 7513 | 7677 |
| 7514 void doInline(FunctionElement function) { | 7678 void doInline(FunctionElement function) { |
| 7515 visitInlinedFunction(function); | 7679 visitInlinedFunction(function); |
| 7516 } | 7680 } |
| 7517 | 7681 |
| 7518 void emitReturn(HInstruction value, ast.Node node) { | 7682 void emitReturn(HInstruction value, ast.Node node) { |
| 7519 if (inliningStack.isEmpty) { | 7683 if (inliningStack.isEmpty) { |
| 7520 closeAndGotoExit(attachPosition(new HReturn(value), node)); | 7684 closeAndGotoExit(new HReturn(value, |
| 7685 sourceInformationBuilder.buildReturn(node))); |
| 7521 } else { | 7686 } else { |
| 7522 localsHandler.updateLocal(returnLocal, value); | 7687 localsHandler.updateLocal(returnLocal, value); |
| 7523 } | 7688 } |
| 7524 } | 7689 } |
| 7525 } | 7690 } |
| 7526 | 7691 |
| 7527 /** | 7692 /** |
| 7528 * Visitor that handles generation of string literals (LiteralString, | 7693 * Visitor that handles generation of string literals (LiteralString, |
| 7529 * StringInterpolation), and otherwise delegates to the given visitor for | 7694 * StringInterpolation), and otherwise delegates to the given visitor for |
| 7530 * non-literal subexpressions. | 7695 * non-literal subexpressions. |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7795 | 7960 |
| 7796 void checkNotAborted() { | 7961 void checkNotAborted() { |
| 7797 if (builder.isAborted()) { | 7962 if (builder.isAborted()) { |
| 7798 compiler.unimplemented(diagnosticNode, "aborted control flow"); | 7963 compiler.unimplemented(diagnosticNode, "aborted control flow"); |
| 7799 } | 7964 } |
| 7800 } | 7965 } |
| 7801 | 7966 |
| 7802 void buildCondition(void visitCondition(), | 7967 void buildCondition(void visitCondition(), |
| 7803 SsaBranch conditionBranch, | 7968 SsaBranch conditionBranch, |
| 7804 SsaBranch thenBranch, | 7969 SsaBranch thenBranch, |
| 7805 SsaBranch elseBranch) { | 7970 SsaBranch elseBranch, |
| 7971 SourceInformation sourceInformation) { |
| 7806 startBranch(conditionBranch); | 7972 startBranch(conditionBranch); |
| 7807 visitCondition(); | 7973 visitCondition(); |
| 7808 checkNotAborted(); | 7974 checkNotAborted(); |
| 7809 assert(identical(builder.current, builder.lastOpenedBlock)); | 7975 assert(identical(builder.current, builder.lastOpenedBlock)); |
| 7810 HInstruction conditionValue = builder.popBoolified(); | 7976 HInstruction conditionValue = builder.popBoolified(); |
| 7811 HIf branch = new HIf(conditionValue); | 7977 HIf branch = new HIf(conditionValue)..sourceInformation = sourceInformation; |
| 7812 HBasicBlock conditionExitBlock = builder.current; | 7978 HBasicBlock conditionExitBlock = builder.current; |
| 7813 builder.close(branch); | 7979 builder.close(branch); |
| 7814 conditionBranch.exitLocals = builder.localsHandler; | 7980 conditionBranch.exitLocals = builder.localsHandler; |
| 7815 conditionExitBlock.addSuccessor(thenBranch.block); | 7981 conditionExitBlock.addSuccessor(thenBranch.block); |
| 7816 conditionExitBlock.addSuccessor(elseBranch.block); | 7982 conditionExitBlock.addSuccessor(elseBranch.block); |
| 7817 bool conditionBranchLocalsCanBeReused = | 7983 bool conditionBranchLocalsCanBeReused = |
| 7818 mergeLocals(conditionBranch, thenBranch, mayReuseFromLocals: true); | 7984 mergeLocals(conditionBranch, thenBranch, mayReuseFromLocals: true); |
| 7819 mergeLocals(conditionBranch, elseBranch, | 7985 mergeLocals(conditionBranch, elseBranch, |
| 7820 mayReuseFromLocals: conditionBranchLocalsCanBeReused); | 7986 mayReuseFromLocals: conditionBranchLocalsCanBeReused); |
| 7821 | 7987 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7862 builder.goto(builder.current, joinBranch.block); | 8028 builder.goto(builder.current, joinBranch.block); |
| 7863 mergeLocals(branch, joinBranch, mayReuseFromLocals: true); | 8029 mergeLocals(branch, joinBranch, mayReuseFromLocals: true); |
| 7864 } | 8030 } |
| 7865 if (isExpression) { | 8031 if (isExpression) { |
| 7866 checkNotAborted(); | 8032 checkNotAborted(); |
| 7867 return builder.pop(); | 8033 return builder.pop(); |
| 7868 } | 8034 } |
| 7869 return null; | 8035 return null; |
| 7870 } | 8036 } |
| 7871 | 8037 |
| 7872 handleIf(void visitCondition(), void visitThen(), void visitElse()) { | 8038 handleIf(void visitCondition(), |
| 8039 void visitThen(), |
| 8040 void visitElse(), |
| 8041 {SourceInformation sourceInformation}) { |
| 7873 if (visitElse == null) { | 8042 if (visitElse == null) { |
| 7874 // Make sure to have an else part to avoid a critical edge. A | 8043 // Make sure to have an else part to avoid a critical edge. A |
| 7875 // critical edge is an edge that connects a block with multiple | 8044 // critical edge is an edge that connects a block with multiple |
| 7876 // successors to a block with multiple predecessors. We avoid | 8045 // successors to a block with multiple predecessors. We avoid |
| 7877 // such edges because they prevent inserting copies during code | 8046 // such edges because they prevent inserting copies during code |
| 7878 // generation of phi instructions. | 8047 // generation of phi instructions. |
| 7879 visitElse = () {}; | 8048 visitElse = () {}; |
| 7880 } | 8049 } |
| 7881 | 8050 |
| 7882 _handleDiamondBranch(visitCondition, visitThen, visitElse, false); | 8051 _handleDiamondBranch( |
| 8052 visitCondition, visitThen, visitElse, isExpression: false, |
| 8053 sourceInformation: sourceInformation); |
| 7883 } | 8054 } |
| 7884 | 8055 |
| 7885 handleConditional(void visitCondition(), void visitThen(), void visitElse()) { | 8056 handleConditional(void visitCondition(), |
| 8057 void visitThen(), |
| 8058 void visitElse()) { |
| 7886 assert(visitElse != null); | 8059 assert(visitElse != null); |
| 7887 _handleDiamondBranch(visitCondition, visitThen, visitElse, true); | 8060 _handleDiamondBranch( |
| 8061 visitCondition, visitThen, visitElse, isExpression: true); |
| 7888 } | 8062 } |
| 7889 | 8063 |
| 7890 handleIfNull(void left(), void right()) { | 8064 handleIfNull(void left(), void right()) { |
| 7891 // x ?? y is transformed into: x == null ? y : x | 8065 // x ?? y is transformed into: x == null ? y : x |
| 7892 HInstruction leftExpression; | 8066 HInstruction leftExpression; |
| 7893 handleConditional( | 8067 handleConditional( |
| 7894 () { | 8068 () { |
| 7895 left(); | 8069 left(); |
| 7896 leftExpression = builder.pop(); | 8070 leftExpression = builder.pop(); |
| 7897 builder.pushCheckNull(leftExpression); | 8071 builder.pushCheckNull(leftExpression); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7972 isAnd: isAnd), | 8146 isAnd: isAnd), |
| 7973 isAnd: isAnd); | 8147 isAnd: isAnd); |
| 7974 } else { | 8148 } else { |
| 7975 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd: isAnd); | 8149 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd: isAnd); |
| 7976 } | 8150 } |
| 7977 } | 8151 } |
| 7978 | 8152 |
| 7979 void _handleDiamondBranch(void visitCondition(), | 8153 void _handleDiamondBranch(void visitCondition(), |
| 7980 void visitThen(), | 8154 void visitThen(), |
| 7981 void visitElse(), | 8155 void visitElse(), |
| 7982 bool isExpression) { | 8156 {bool isExpression, |
| 8157 SourceInformation sourceInformation}) { |
| 7983 SsaBranch conditionBranch = new SsaBranch(this); | 8158 SsaBranch conditionBranch = new SsaBranch(this); |
| 7984 SsaBranch thenBranch = new SsaBranch(this); | 8159 SsaBranch thenBranch = new SsaBranch(this); |
| 7985 SsaBranch elseBranch = new SsaBranch(this); | 8160 SsaBranch elseBranch = new SsaBranch(this); |
| 7986 SsaBranch joinBranch = new SsaBranch(this); | 8161 SsaBranch joinBranch = new SsaBranch(this); |
| 7987 | 8162 |
| 7988 conditionBranch.startLocals = builder.localsHandler; | 8163 conditionBranch.startLocals = builder.localsHandler; |
| 7989 builder.goto(builder.current, conditionBranch.block); | 8164 builder.goto(builder.current, conditionBranch.block); |
| 7990 | 8165 |
| 7991 buildCondition(visitCondition, conditionBranch, thenBranch, elseBranch); | 8166 buildCondition(visitCondition, conditionBranch, thenBranch, elseBranch, |
| 8167 sourceInformation); |
| 7992 HInstruction thenValue = | 8168 HInstruction thenValue = |
| 7993 buildBranch(thenBranch, visitThen, joinBranch, isExpression); | 8169 buildBranch(thenBranch, visitThen, joinBranch, isExpression); |
| 7994 HInstruction elseValue = | 8170 HInstruction elseValue = |
| 7995 buildBranch(elseBranch, visitElse, joinBranch, isExpression); | 8171 buildBranch(elseBranch, visitElse, joinBranch, isExpression); |
| 7996 | 8172 |
| 7997 if (isExpression) { | 8173 if (isExpression) { |
| 7998 assert(thenValue != null && elseValue != null); | 8174 assert(thenValue != null && elseValue != null); |
| 7999 JavaScriptBackend backend = builder.backend; | 8175 JavaScriptBackend backend = builder.backend; |
| 8000 HPhi phi = new HPhi.manyInputs( | 8176 HPhi phi = new HPhi.manyInputs( |
| 8001 null, <HInstruction>[thenValue, elseValue], backend.dynamicType); | 8177 null, <HInstruction>[thenValue, elseValue], backend.dynamicType); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8111 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 8287 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 8112 unaliased.accept(this, builder); | 8288 unaliased.accept(this, builder); |
| 8113 } | 8289 } |
| 8114 | 8290 |
| 8115 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 8291 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 8116 JavaScriptBackend backend = builder.compiler.backend; | 8292 JavaScriptBackend backend = builder.compiler.backend; |
| 8117 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 8293 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 8118 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 8294 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 8119 } | 8295 } |
| 8120 } | 8296 } |
| OLD | NEW |