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