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