Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: pkg/compiler/lib/src/ssa/builder.dart

Issue 1196433002: Create and test source mapping for invocations. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Update comments. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698