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

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

Issue 1196433002: Create and test source mapping for invocations. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Rebased 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
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder.dart ('k') | pkg/compiler/lib/src/ssa/nodes.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 SsaCodeGeneratorTask extends CompilerTask { 7 class SsaCodeGeneratorTask extends CompilerTask {
8 8
9 final JavaScriptBackend backend; 9 final JavaScriptBackend backend;
10 final SourceInformationFactory sourceInformationFactory; 10 final SourceInformationStrategy sourceInformationFactory;
11 11
12 SsaCodeGeneratorTask(JavaScriptBackend backend, 12 SsaCodeGeneratorTask(JavaScriptBackend backend,
13 this.sourceInformationFactory) 13 this.sourceInformationFactory)
14 : this.backend = backend, 14 : this.backend = backend,
15 super(backend.compiler); 15 super(backend.compiler);
16 16
17 String get name => 'SSA code generator'; 17 String get name => 'SSA code generator';
18 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; 18 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter;
19 19
20
21 js.Node attachPosition(js.Node node, AstElement element) {
22 return node.withSourceInformation(
23 StartEndSourceInformation.computeSourceInformation(element));
24 }
25
26 js.Fun buildJavaScriptFunction(FunctionElement element, 20 js.Fun buildJavaScriptFunction(FunctionElement element,
27 List<js.Parameter> parameters, 21 List<js.Parameter> parameters,
28 js.Block body) { 22 js.Block body) {
29 js.AsyncModifier asyncModifier = element.asyncMarker.isAsync 23 js.AsyncModifier asyncModifier = element.asyncMarker.isAsync
30 ? (element.asyncMarker.isYielding 24 ? (element.asyncMarker.isYielding
31 ? const js.AsyncModifier.asyncStar() 25 ? const js.AsyncModifier.asyncStar()
32 : const js.AsyncModifier.async()) 26 : const js.AsyncModifier.async())
33 : (element.asyncMarker.isYielding 27 : (element.asyncMarker.isYielding
34 ? const js.AsyncModifier.syncStar() 28 ? const js.AsyncModifier.syncStar()
35 : const js.AsyncModifier.sync()); 29 : const js.AsyncModifier.sync());
36 30
37 return new js.Fun(parameters, body, asyncModifier: asyncModifier) 31 return new js.Fun(parameters, body, asyncModifier: asyncModifier)
38 .withSourceInformation(sourceInformationFactory.forContext(element) 32 .withSourceInformation(
39 .buildDeclaration(element)); 33 sourceInformationFactory.createBuilderForContext(element)
34 .buildDeclaration(element));
40 } 35 }
41 36
42 js.Expression generateCode(CodegenWorkItem work, HGraph graph) { 37 js.Expression generateCode(CodegenWorkItem work, HGraph graph) {
43 if (work.element.isField) { 38 if (work.element.isField) {
44 return generateLazyInitializer(work, graph); 39 return generateLazyInitializer(work, graph);
45 } else { 40 } else {
46 return generateMethod(work, graph); 41 return generateMethod(work, graph);
47 } 42 }
48 } 43 }
49 44
50 js.Expression generateLazyInitializer(work, graph) { 45 js.Expression generateLazyInitializer(work, graph) {
51 return measure(() { 46 return measure(() {
52 compiler.tracer.traceGraph("codegen", graph); 47 compiler.tracer.traceGraph("codegen", graph);
53 SourceInformation sourceInformation = 48 SourceInformation sourceInformation =
54 sourceInformationFactory.forContext(work.element) 49 sourceInformationFactory.createBuilderForContext(work.element)
55 .buildDeclaration(work.element); 50 .buildDeclaration(work.element);
56 SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work); 51 SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work);
57 codegen.visitGraph(graph); 52 codegen.visitGraph(graph);
58 return new js.Fun(codegen.parameters, codegen.body) 53 return new js.Fun(codegen.parameters, codegen.body)
59 .withSourceInformation(sourceInformation); 54 .withSourceInformation(sourceInformation);
60 }); 55 });
61 } 56 }
62 57
63 js.Expression generateMethod(CodegenWorkItem work, HGraph graph) { 58 js.Expression generateMethod(CodegenWorkItem work, HGraph graph) {
64 return measure(() { 59 return measure(() {
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 if (instruction.isUInt31(compiler)) return false; 177 if (instruction.isUInt31(compiler)) return false;
183 // If the result of a bit-operation is only used by other bit 178 // If the result of a bit-operation is only used by other bit
184 // operations, we do not have to convert to an unsigned integer. 179 // operations, we do not have to convert to an unsigned integer.
185 return hasNonBitOpUser(instruction, new Set<HPhi>()); 180 return hasNonBitOpUser(instruction, new Set<HPhi>());
186 } 181 }
187 182
188 /** 183 /**
189 * If the [instruction] is not `null` it will be used to attach the position 184 * If the [instruction] is not `null` it will be used to attach the position
190 * to the [statement]. 185 * to the [statement].
191 */ 186 */
192 void pushStatement(js.Statement statement, [HInstruction instruction]) { 187 void pushStatement(js.Statement statement) {
193 assert(expressionStack.isEmpty); 188 assert(expressionStack.isEmpty);
194 if (instruction != null) {
195 statement = attachLocation(statement, instruction);
196 }
197 currentContainer.statements.add(statement); 189 currentContainer.statements.add(statement);
198 } 190 }
199 191
200 void insertStatementAtStart(js.Statement statement) { 192 void insertStatementAtStart(js.Statement statement) {
201 currentContainer.statements.insert(0, statement); 193 currentContainer.statements.insert(0, statement);
202 } 194 }
203 195
204 /** 196 /**
205 * If the [instruction] is not `null` it will be used to attach the position 197 * If the [instruction] is not `null` it will be used to attach the position
206 * to the [expression]. 198 * to the [expression].
207 */ 199 */
208 pushExpressionAsStatement(js.Expression expression, 200 pushExpressionAsStatement(js.Expression expression,
209 [HInstruction instruction]) { 201 SourceInformation sourceInformation) {
210 pushStatement(new js.ExpressionStatement(expression), instruction); 202 pushStatement(new js.ExpressionStatement(expression)
203 .withSourceInformation(sourceInformation));
211 } 204 }
212 205
213 /** 206 /**
214 * If the [instruction] is not `null` it will be used to attach the position 207 * If the [instruction] is not `null` it will be used to attach the position
215 * to the [expression]. 208 * to the [expression].
216 */ 209 */
217 push(js.Expression expression, [HInstruction instruction]) { 210 push(js.Expression expression) {
218 if (instruction != null) {
219 expression = attachLocation(expression, instruction);
220 }
221 expressionStack.add(expression); 211 expressionStack.add(expression);
222 } 212 }
223 213
224 js.Expression pop() { 214 js.Expression pop() {
225 return expressionStack.removeLast(); 215 return expressionStack.removeLast();
226 } 216 }
227 217
228 attachLocationToLast(HInstruction instruction) {
229 int index = expressionStack.length - 1;
230 expressionStack[index] =
231 attachLocation(expressionStack[index], instruction);
232 }
233
234 js.Node attachLocation(js.Node jsNode, HInstruction instruction) {
235 return attachSourceInformation(jsNode, instruction.sourceInformation);
236 }
237
238 js.Node attachSourceInformation(js.Node jsNode,
239 SourceInformation sourceInformation) {
240 return jsNode.withSourceInformation(sourceInformation);
241 }
242
243 void preGenerateMethod(HGraph graph) { 218 void preGenerateMethod(HGraph graph) {
244 new SsaInstructionSelection(compiler).visitGraph(graph); 219 new SsaInstructionSelection(compiler).visitGraph(graph);
245 new SsaTypeKnownRemover().visitGraph(graph); 220 new SsaTypeKnownRemover().visitGraph(graph);
246 new SsaTrustedCheckRemover(compiler).visitGraph(graph); 221 new SsaTrustedCheckRemover(compiler).visitGraph(graph);
247 new SsaInstructionMerger(generateAtUseSite, compiler).visitGraph(graph); 222 new SsaInstructionMerger(generateAtUseSite, compiler).visitGraph(graph);
248 new SsaConditionMerger( 223 new SsaConditionMerger(
249 generateAtUseSite, controlFlowOperators).visitGraph(graph); 224 generateAtUseSite, controlFlowOperators).visitGraph(graph);
250 SsaLiveIntervalBuilder intervalBuilder = new SsaLiveIntervalBuilder( 225 SsaLiveIntervalBuilder intervalBuilder = new SsaLiveIntervalBuilder(
251 compiler, generateAtUseSite, controlFlowOperators); 226 compiler, generateAtUseSite, controlFlowOperators);
252 intervalBuilder.visitGraph(graph); 227 intervalBuilder.visitGraph(graph);
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 // Also check for the shortcut where y equals 1: x++ and x--. 467 // Also check for the shortcut where y equals 1: x++ and x--.
493 if ((op == '+' || op == '-') && 468 if ((op == '+' || op == '-') &&
494 binary.right is js.LiteralNumber && 469 binary.right is js.LiteralNumber &&
495 (binary.right as js.LiteralNumber).value == "1") { 470 (binary.right as js.LiteralNumber).value == "1") {
496 return new js.Prefix(op == '+' ? '++' : '--', binary.left); 471 return new js.Prefix(op == '+' ? '++' : '--', binary.left);
497 } 472 }
498 return new js.Assignment.compound(binary.left, op, binary.right); 473 return new js.Assignment.compound(binary.left, op, binary.right);
499 } 474 }
500 } 475 }
501 } 476 }
502 return new js.Assignment(new js.VariableUse(variableName), value); 477 return new js.Assignment(new js.VariableUse(variableName), value)
478 .withSourceInformation(value.sourceInformation);
503 } 479 }
504 480
505 void assignVariable(String variableName, js.Expression value) { 481 void assignVariable(String variableName,
482 js.Expression value,
483 SourceInformation sourceInformation) {
506 if (isGeneratingExpression) { 484 if (isGeneratingExpression) {
507 // If we are in an expression then we can't declare the variable here. 485 // If we are in an expression then we can't declare the variable here.
508 // We have no choice, but to use it and then declare it separately. 486 // We have no choice, but to use it and then declare it separately.
509 if (!isVariableDeclared(variableName)) { 487 if (!isVariableDeclared(variableName)) {
510 collectedVariableDeclarations.add(variableName); 488 collectedVariableDeclarations.add(variableName);
511 } 489 }
512 push(generateExpressionAssignment(variableName, value)); 490 push(generateExpressionAssignment(variableName, value));
513 // Otherwise if we are trying to declare inline and we are in a statement 491 // Otherwise if we are trying to declare inline and we are in a statement
514 // then we declare (unless it was already declared). 492 // then we declare (unless it was already declared).
515 } else if (!shouldGroupVarDeclarations && 493 } else if (!shouldGroupVarDeclarations &&
516 !declaredLocals.contains(variableName)) { 494 !declaredLocals.contains(variableName)) {
517 // It may be necessary to remove it from the ones to be declared later. 495 // It may be necessary to remove it from the ones to be declared later.
518 collectedVariableDeclarations.remove(variableName); 496 collectedVariableDeclarations.remove(variableName);
519 declaredLocals.add(variableName); 497 declaredLocals.add(variableName);
520 js.VariableDeclaration decl = new js.VariableDeclaration(variableName); 498 js.VariableDeclaration decl = new js.VariableDeclaration(variableName);
521 js.VariableInitialization initialization = 499 js.VariableInitialization initialization =
522 new js.VariableInitialization(decl, value); 500 new js.VariableInitialization(decl, value);
523 501
524 pushExpressionAsStatement(new js.VariableDeclarationList( 502 pushExpressionAsStatement(new js.VariableDeclarationList(
525 <js.VariableInitialization>[initialization])); 503 <js.VariableInitialization>[initialization]),
504 sourceInformation);
526 } else { 505 } else {
527 // Otherwise we are just going to use it. If we have not already declared 506 // Otherwise we are just going to use it. If we have not already declared
528 // it then we make sure we will declare it later. 507 // it then we make sure we will declare it later.
529 if (!declaredLocals.contains(variableName)) { 508 if (!declaredLocals.contains(variableName)) {
530 collectedVariableDeclarations.add(variableName); 509 collectedVariableDeclarations.add(variableName);
531 } 510 }
532 pushExpressionAsStatement( 511 pushExpressionAsStatement(
533 generateExpressionAssignment(variableName, value)); 512 generateExpressionAssignment(variableName, value),
513 sourceInformation);
534 } 514 }
535 } 515 }
536 516
537 void define(HInstruction instruction) { 517 void define(HInstruction instruction) {
538 // For simple type checks like i = intTypeCheck(i), we don't have to 518 // For simple type checks like i = intTypeCheck(i), we don't have to
539 // emit an assignment, because the intTypeCheck just returns its 519 // emit an assignment, because the intTypeCheck just returns its
540 // argument. 520 // argument.
541 bool needsAssignment = true; 521 bool needsAssignment = true;
542 if (instruction is HTypeConversion) { 522 if (instruction is HTypeConversion) {
543 HTypeConversion typeConversion = instruction; 523 HTypeConversion typeConversion = instruction;
544 String inputName = variableNames.getName(typeConversion.checkedInput); 524 String inputName = variableNames.getName(typeConversion.checkedInput);
545 if (variableNames.getName(instruction) == inputName) { 525 if (variableNames.getName(instruction) == inputName) {
546 needsAssignment = false; 526 needsAssignment = false;
547 } 527 }
548 } 528 }
549 if (instruction is HLocalValue) { 529 if (instruction is HLocalValue) {
550 needsAssignment = false; 530 needsAssignment = false;
551 } 531 }
552 532
553 if (needsAssignment && 533 if (needsAssignment &&
554 !instruction.isControlFlow() && variableNames.hasName(instruction)) { 534 !instruction.isControlFlow() && variableNames.hasName(instruction)) {
555 visitExpression(instruction); 535 visitExpression(instruction);
556 assignVariable(variableNames.getName(instruction), pop()); 536 assignVariable(variableNames.getName(instruction), pop(),
537 instruction.sourceInformation);
557 return; 538 return;
558 } 539 }
559 540
560 if (isGeneratingExpression) { 541 if (isGeneratingExpression) {
561 visitExpression(instruction); 542 visitExpression(instruction);
562 } else { 543 } else {
563 visitStatement(instruction); 544 visitStatement(instruction);
564 } 545 }
565 } 546 }
566 547
(...skipping 20 matching lines...) Expand all
587 isGeneratingExpression = true; 568 isGeneratingExpression = true;
588 visit(node); 569 visit(node);
589 isGeneratingExpression = oldIsGeneratingExpression; 570 isGeneratingExpression = oldIsGeneratingExpression;
590 } 571 }
591 572
592 visitStatement(HInstruction node) { 573 visitStatement(HInstruction node) {
593 assert(!isGeneratingExpression); 574 assert(!isGeneratingExpression);
594 visit(node); 575 visit(node);
595 if (!expressionStack.isEmpty) { 576 if (!expressionStack.isEmpty) {
596 assert(expressionStack.length == 1); 577 assert(expressionStack.length == 1);
597 pushExpressionAsStatement(pop()); 578 js.Expression expression = pop();
579 pushExpressionAsStatement(expression, node.sourceInformation);
598 } 580 }
599 } 581 }
600 582
601 void continueAsBreak(LabelDefinition target) { 583 void continueAsBreak(LabelDefinition target) {
602 pushStatement(new js.Break(backend.namer.continueLabelName(target))); 584 pushStatement(new js.Break(backend.namer.continueLabelName(target)));
603 } 585 }
604 586
605 void implicitContinueAsBreak(JumpTarget target) { 587 void implicitContinueAsBreak(JumpTarget target) {
606 pushStatement(new js.Break( 588 pushStatement(new js.Break(
607 backend.namer.implicitContinueLabelName(target))); 589 backend.namer.implicitContinueLabelName(target)));
608 } 590 }
609 591
610 void implicitBreakWithLabel(JumpTarget target) { 592 void implicitBreakWithLabel(JumpTarget target) {
611 pushStatement(new js.Break(backend.namer.implicitBreakLabelName(target))); 593 pushStatement(new js.Break(backend.namer.implicitBreakLabelName(target)));
612 } 594 }
613 595
614 js.Statement wrapIntoLabels(js.Statement result, List<LabelDefinition> labels) { 596 js.Statement wrapIntoLabels(js.Statement result,
597 List<LabelDefinition> labels) {
615 for (LabelDefinition label in labels) { 598 for (LabelDefinition label in labels) {
616 if (label.isTarget) { 599 if (label.isTarget) {
617 String breakLabelString = backend.namer.breakLabelName(label); 600 String breakLabelString = backend.namer.breakLabelName(label);
618 result = new js.LabeledStatement(breakLabelString, result); 601 result = new js.LabeledStatement(breakLabelString, result);
619 } 602 }
620 } 603 }
621 return result; 604 return result;
622 } 605 }
623 606
624 607
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 // The body might be labeled. Ignore this when recursing on the 810 // The body might be labeled. Ignore this when recursing on the
828 // subgraph. 811 // subgraph.
829 // TODO(lrn): Remove this extra labeling when handling all loops 812 // TODO(lrn): Remove this extra labeling when handling all loops
830 // using subgraphs. 813 // using subgraphs.
831 oldContainer = currentContainer; 814 oldContainer = currentContainer;
832 js.Statement body = new js.Block.empty(); 815 js.Statement body = new js.Block.empty();
833 currentContainer = body; 816 currentContainer = body;
834 visitBodyIgnoreLabels(info); 817 visitBodyIgnoreLabels(info);
835 currentContainer = oldContainer; 818 currentContainer = oldContainer;
836 body = unwrapStatement(body); 819 body = unwrapStatement(body);
837 loop = new js.For(jsInitialization, jsCondition, jsUpdates, body); 820 loop = new js.For(jsInitialization, jsCondition, jsUpdates, body)
821 .withSourceInformation(info.sourceInformation);
838 } else { 822 } else {
839 // We have either no update graph, or it's too complex to 823 // We have either no update graph, or it's too complex to
840 // put in an expression. 824 // put in an expression.
841 if (initialization != null) { 825 if (initialization != null) {
842 generateStatements(initialization); 826 generateStatements(initialization);
843 } 827 }
844 js.Expression jsCondition; 828 js.Expression jsCondition;
845 js.Block oldContainer = currentContainer; 829 js.Block oldContainer = currentContainer;
846 js.Statement body = new js.Block.empty(); 830 js.Statement body = new js.Block.empty();
847 if (isConditionExpression && !hasPhiUpdates) { 831 if (isConditionExpression && !hasPhiUpdates) {
848 jsCondition = generateExpression(condition); 832 jsCondition = generateExpression(condition);
849 currentContainer = body; 833 currentContainer = body;
850 } else { 834 } else {
851 jsCondition = newLiteralBool(true); 835 jsCondition = newLiteralBool(true, info.sourceInformation);
852 currentContainer = body; 836 currentContainer = body;
853 generateStatements(condition); 837 generateStatements(condition);
854 use(condition.conditionExpression); 838 use(condition.conditionExpression);
855 js.Expression ifTest = new js.Prefix("!", pop()); 839 js.Expression ifTest = new js.Prefix("!", pop());
856 js.Statement jsBreak = new js.Break(null); 840 js.Statement jsBreak = new js.Break(null);
857 js.Statement exitLoop; 841 js.Statement exitLoop;
858 if (avoidContainer.statements.isEmpty) { 842 if (avoidContainer.statements.isEmpty) {
859 exitLoop = jsBreak; 843 exitLoop = jsBreak;
860 } else { 844 } else {
861 avoidContainer.statements.add(jsBreak); 845 avoidContainer.statements.add(jsBreak);
862 exitLoop = avoidContainer; 846 exitLoop = avoidContainer;
863 } 847 }
864 pushStatement(new js.If.noElse(ifTest, exitLoop)); 848 pushStatement(new js.If.noElse(ifTest, exitLoop));
865 } 849 }
866 if (info.updates != null) { 850 if (info.updates != null) {
867 wrapLoopBodyForContinue(info); 851 wrapLoopBodyForContinue(info);
868 generateStatements(info.updates); 852 generateStatements(info.updates);
869 } else { 853 } else {
870 visitBodyIgnoreLabels(info); 854 visitBodyIgnoreLabels(info);
871 } 855 }
872 currentContainer = oldContainer; 856 currentContainer = oldContainer;
873 body = unwrapStatement(body); 857 body = unwrapStatement(body);
874 loop = new js.While(jsCondition, body); 858 loop = new js.While(jsCondition, body)
859 .withSourceInformation(info.sourceInformation);
875 } 860 }
876 break; 861 break;
877 case HLoopBlockInformation.DO_WHILE_LOOP: 862 case HLoopBlockInformation.DO_WHILE_LOOP:
878 if (info.initializer != null) { 863 if (info.initializer != null) {
879 generateStatements(info.initializer); 864 generateStatements(info.initializer);
880 } 865 }
881 // We inserted a basic block to avoid critical edges. This block is 866 // We inserted a basic block to avoid critical edges. This block is
882 // part of the LoopBlockInformation and must therefore be handled here. 867 // part of the LoopBlockInformation and must therefore be handled here.
883 js.Block oldContainer = currentContainer; 868 js.Block oldContainer = currentContainer;
884 js.Block exitAvoidContainer = new js.Block.empty(); 869 js.Block exitAvoidContainer = new js.Block.empty();
(...skipping 30 matching lines...) Expand all
915 push(generateExpression(condition)); 900 push(generateExpression(condition));
916 } else { 901 } else {
917 generateStatements(condition); 902 generateStatements(condition);
918 use(condition.conditionExpression); 903 use(condition.conditionExpression);
919 } 904 }
920 js.Expression jsCondition = pop(); 905 js.Expression jsCondition = pop();
921 if (jsCondition == null) { 906 if (jsCondition == null) {
922 // If the condition is dead code, we turn the do-while into 907 // If the condition is dead code, we turn the do-while into
923 // a simpler while because we will never reach the condition 908 // a simpler while because we will never reach the condition
924 // at the end of the loop anyway. 909 // at the end of the loop anyway.
925 loop = new js.While(newLiteralBool(true), unwrapStatement(body)); 910 loop = new js.While(
911 newLiteralBool(true, info.sourceInformation),
912 unwrapStatement(body))
913 .withSourceInformation(info.sourceInformation);
926 } else { 914 } else {
927 if (hasPhiUpdates || hasExitPhiUpdates) { 915 if (hasPhiUpdates || hasExitPhiUpdates) {
928 updateBody.statements.add(new js.Continue(null)); 916 updateBody.statements.add(new js.Continue(null));
929 js.Statement jsBreak = new js.Break(null); 917 js.Statement jsBreak = new js.Break(null);
930 js.Statement exitLoop; 918 js.Statement exitLoop;
931 if (exitAvoidContainer.statements.isEmpty) { 919 if (exitAvoidContainer.statements.isEmpty) {
932 exitLoop = jsBreak; 920 exitLoop = jsBreak;
933 } else { 921 } else {
934 exitAvoidContainer.statements.add(jsBreak); 922 exitAvoidContainer.statements.add(jsBreak);
935 exitLoop = exitAvoidContainer; 923 exitLoop = exitAvoidContainer;
936 } 924 }
937 body.statements.add( 925 body.statements.add(
938 new js.If(jsCondition, updateBody, exitLoop)); 926 new js.If(jsCondition, updateBody, exitLoop));
939 jsCondition = newLiteralBool(true); 927 jsCondition = newLiteralBool(true, info.sourceInformation);
940 } 928 }
941 loop = new js.Do(unwrapStatement(body), jsCondition); 929 loop = new js.Do(unwrapStatement(body), jsCondition)
930 .withSourceInformation(info.sourceInformation);
942 } 931 }
943 currentContainer = oldContainer; 932 currentContainer = oldContainer;
944 break; 933 break;
945 default: 934 default:
946 compiler.internalError(condition.conditionExpression, 935 compiler.internalError(condition.conditionExpression,
947 'Unexpected loop kind: ${info.kind}.'); 936 'Unexpected loop kind: ${info.kind}.');
948 } 937 }
949 js.Statement result = attachSourceInformation(loop, info.sourceInformation); 938 js.Statement result = loop;
950 if (info.kind == HLoopBlockInformation.SWITCH_CONTINUE_LOOP) { 939 if (info.kind == HLoopBlockInformation.SWITCH_CONTINUE_LOOP) {
951 String continueLabelString = 940 String continueLabelString =
952 backend.namer.implicitContinueLabelName(info.target); 941 backend.namer.implicitContinueLabelName(info.target);
953 result = new js.LabeledStatement(continueLabelString, result); 942 result = new js.LabeledStatement(continueLabelString, result);
954 } 943 }
955 pushStatement(wrapIntoLabels(result, info.labels)); 944 pushStatement(wrapIntoLabels(result, info.labels));
956 return true; 945 return true;
957 } 946 }
958 947
959 bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) { 948 bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) {
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1086 1075
1087 // If this node has block-structure based information attached, 1076 // If this node has block-structure based information attached,
1088 // try using that to traverse from here. 1077 // try using that to traverse from here.
1089 if (node.blockFlow != null && handleBlockFlow(node.blockFlow)) { 1078 if (node.blockFlow != null && handleBlockFlow(node.blockFlow)) {
1090 return; 1079 return;
1091 } 1080 }
1092 iterateBasicBlock(node); 1081 iterateBasicBlock(node);
1093 } 1082 }
1094 1083
1095 void emitAssignment(String destination, String source) { 1084 void emitAssignment(String destination, String source) {
1096 assignVariable(destination, new js.VariableUse(source)); 1085 assignVariable(destination, new js.VariableUse(source), null);
1097 } 1086 }
1098 1087
1099 /** 1088 /**
1100 * Sequentialize a list of conceptually parallel copies. Parallel 1089 * Sequentialize a list of conceptually parallel copies. Parallel
1101 * copies may contain cycles, that this method breaks. 1090 * copies may contain cycles, that this method breaks.
1102 */ 1091 */
1103 void sequentializeCopies(Iterable<Copy> copies, 1092 void sequentializeCopies(Iterable<Copy> copies,
1104 String tempName, 1093 String tempName,
1105 void doAssignment(String target, String source)) { 1094 void doAssignment(String target, String source)) {
1106 // Map to keep track of the current location (ie the variable that 1095 // Map to keep track of the current location (ie the variable that
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1186 Iterable<Copy> copies = handler.copies.map((Copy copy) { 1175 Iterable<Copy> copies = handler.copies.map((Copy copy) {
1187 return new Copy(variableNames.getName(copy.source), 1176 return new Copy(variableNames.getName(copy.source),
1188 variableNames.getName(copy.destination)); 1177 variableNames.getName(copy.destination));
1189 }); 1178 });
1190 1179
1191 sequentializeCopies(copies, variableNames.getSwapTemp(), emitAssignment); 1180 sequentializeCopies(copies, variableNames.getSwapTemp(), emitAssignment);
1192 1181
1193 for (Copy copy in handler.assignments) { 1182 for (Copy copy in handler.assignments) {
1194 String name = variableNames.getName(copy.destination); 1183 String name = variableNames.getName(copy.destination);
1195 use(copy.source); 1184 use(copy.source);
1196 assignVariable(name, pop()); 1185 assignVariable(name, pop(), null);
1197 } 1186 }
1198 } 1187 }
1199 1188
1200 void iterateBasicBlock(HBasicBlock node) { 1189 void iterateBasicBlock(HBasicBlock node) {
1201 HInstruction instruction = node.first; 1190 HInstruction instruction = node.first;
1202 while (!identical(instruction, node.last)) { 1191 while (!identical(instruction, node.last)) {
1203 if (!isGenerateAtUseSite(instruction)) { 1192 if (!isGenerateAtUseSite(instruction)) {
1204 define(instruction); 1193 define(instruction);
1205 } 1194 }
1206 instruction = instruction.next; 1195 instruction = instruction.next;
1207 } 1196 }
1208 assignPhisOfSuccessors(node); 1197 assignPhisOfSuccessors(node);
1209 visit(instruction); 1198 visit(instruction);
1210 } 1199 }
1211 1200
1212 visitInvokeBinary(HInvokeBinary node, String op) { 1201 void handleInvokeBinary(HInvokeBinary node,
1202 String op,
1203 SourceInformation sourceInformation) {
1213 use(node.left); 1204 use(node.left);
1214 js.Expression jsLeft = pop(); 1205 js.Expression jsLeft = pop();
1215 use(node.right); 1206 use(node.right);
1216 push(new js.Binary(op, jsLeft, pop()), node); 1207 push(new js.Binary(op, jsLeft, pop())
1208 .withSourceInformation(sourceInformation));
1217 } 1209 }
1218 1210
1219 visitRelational(HRelational node, String op) => visitInvokeBinary(node, op); 1211 visitInvokeBinary(HInvokeBinary node, String op) {
1212 handleInvokeBinary(node, op, node.sourceInformation);
1213 }
1214
1215 visitRelational(HRelational node, String op) {
1216 handleInvokeBinary(node, op, node.sourceInformation);
1217 }
1220 1218
1221 // We want the outcome of bit-operations to be positive. We use the unsigned 1219 // We want the outcome of bit-operations to be positive. We use the unsigned
1222 // shift operator to achieve this. 1220 // shift operator to achieve this.
1223 visitBitInvokeBinary(HBinaryBitOp node, String op) { 1221 visitBitInvokeBinary(HBinaryBitOp node, String op) {
1224 visitInvokeBinary(node, op); 1222 visitInvokeBinary(node, op);
1225 if (op != '>>>' && requiresUintConversion(node)) { 1223 if (op != '>>>' && requiresUintConversion(node)) {
1226 push(new js.Binary(">>>", pop(), new js.LiteralNumber("0")), node); 1224 push(new js.Binary(">>>", pop(), new js.LiteralNumber("0"))
1225 .withSourceInformation(node.sourceInformation));
1227 } 1226 }
1228 } 1227 }
1229 1228
1230 visitInvokeUnary(HInvokeUnary node, String op) { 1229 visitInvokeUnary(HInvokeUnary node, String op) {
1231 use(node.operand); 1230 use(node.operand);
1232 push(new js.Prefix(op, pop()), node); 1231 push(new js.Prefix(op, pop())
1232 .withSourceInformation(node.sourceInformation));
1233 } 1233 }
1234 1234
1235 // We want the outcome of bit-operations to be positive. We use the unsigned 1235 // We want the outcome of bit-operations to be positive. We use the unsigned
1236 // shift operator to achieve this. 1236 // shift operator to achieve this.
1237 visitBitInvokeUnary(HInvokeUnary node, String op) { 1237 visitBitInvokeUnary(HInvokeUnary node, String op) {
1238 visitInvokeUnary(node, op); 1238 visitInvokeUnary(node, op);
1239 if (requiresUintConversion(node)) { 1239 if (requiresUintConversion(node)) {
1240 push(new js.Binary(">>>", pop(), new js.LiteralNumber("0")), node); 1240 push(new js.Binary(">>>", pop(), new js.LiteralNumber("0"))
1241 .withSourceInformation(node.sourceInformation));
1241 } 1242 }
1242 } 1243 }
1243 1244
1244 void emitIdentityComparison(HIdentity instruction, bool inverse) { 1245 void emitIdentityComparison(HIdentity instruction,
1246 SourceInformation sourceInformation,
1247 {bool inverse: false}) {
1245 String op = instruction.singleComparisonOp; 1248 String op = instruction.singleComparisonOp;
1246 HInstruction left = instruction.left; 1249 HInstruction left = instruction.left;
1247 HInstruction right = instruction.right; 1250 HInstruction right = instruction.right;
1248 if (op != null) { 1251 if (op != null) {
1249 use(left); 1252 use(left);
1250 js.Expression jsLeft = pop(); 1253 js.Expression jsLeft = pop();
1251 use(right); 1254 use(right);
1252 push(new js.Binary(mapRelationalOperator(op, inverse), jsLeft, pop())); 1255 push(new js.Binary(mapRelationalOperator(op, inverse), jsLeft, pop())
1256 .withSourceInformation(sourceInformation));
1253 } else { 1257 } else {
1254 assert(NullConstantValue.JsNull == 'null'); 1258 assert(NullConstantValue.JsNull == 'null');
1255 use(left); 1259 use(left);
1256 js.Binary leftEqualsNull = 1260 js.Binary leftEqualsNull =
1257 new js.Binary("==", pop(), new js.LiteralNull()); 1261 new js.Binary("==", pop(), new js.LiteralNull());
1258 use(right); 1262 use(right);
1259 js.Binary rightEqualsNull = 1263 js.Binary rightEqualsNull =
1260 new js.Binary(mapRelationalOperator("==", inverse), 1264 new js.Binary(mapRelationalOperator("==", inverse),
1261 pop(), new js.LiteralNull()); 1265 pop(), new js.LiteralNull());
1262 use(right); 1266 use(right);
1263 use(left); 1267 use(left);
1264 js.Binary tripleEq = new js.Binary(mapRelationalOperator("===", inverse), 1268 js.Binary tripleEq = new js.Binary(mapRelationalOperator("===", inverse),
1265 pop(), pop()); 1269 pop(), pop());
1266 1270
1267 push(new js.Conditional(leftEqualsNull, rightEqualsNull, tripleEq)); 1271 push(new js.Conditional(leftEqualsNull, rightEqualsNull, tripleEq)
1272 .withSourceInformation(sourceInformation));
1268 } 1273 }
1269 } 1274 }
1270 1275
1271 visitIdentity(HIdentity node) { 1276 visitIdentity(HIdentity node) {
1272 emitIdentityComparison(node, false); 1277 emitIdentityComparison(node, node.sourceInformation, inverse: false);
1273 } 1278 }
1274 1279
1275 visitAdd(HAdd node) => visitInvokeBinary(node, '+'); 1280 visitAdd(HAdd node) => visitInvokeBinary(node, '+');
1276 visitDivide(HDivide node) => visitInvokeBinary(node, '/'); 1281 visitDivide(HDivide node) => visitInvokeBinary(node, '/');
1277 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*'); 1282 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*');
1278 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-'); 1283 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-');
1279 visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&'); 1284 visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&');
1280 visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~'); 1285 visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~');
1281 visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|'); 1286 visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|');
1282 visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^'); 1287 visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^');
1283 visitShiftLeft(HShiftLeft node) => visitBitInvokeBinary(node, '<<'); 1288 visitShiftLeft(HShiftLeft node) => visitBitInvokeBinary(node, '<<');
1284 visitShiftRight(HShiftRight node) => visitBitInvokeBinary(node, '>>>'); 1289 visitShiftRight(HShiftRight node) => visitBitInvokeBinary(node, '>>>');
1285 1290
1286 visitTruncatingDivide(HTruncatingDivide node) { 1291 visitTruncatingDivide(HTruncatingDivide node) {
1287 assert(node.isUInt31(compiler)); 1292 assert(node.isUInt31(compiler));
1288 // TODO(karlklose): Enable this assertion again when type propagation is 1293 // TODO(karlklose): Enable this assertion again when type propagation is
1289 // fixed. Issue 23555. 1294 // fixed. Issue 23555.
1290 // assert(node.left.isUInt32(compiler)); 1295 // assert(node.left.isUInt32(compiler));
1291 assert(node.right.isPositiveInteger(compiler)); 1296 assert(node.right.isPositiveInteger(compiler));
1292 use(node.left); 1297 use(node.left);
1293 js.Expression jsLeft = pop(); 1298 js.Expression jsLeft = pop();
1294 use(node.right); 1299 use(node.right);
1295 push(new js.Binary('/', jsLeft, pop()), node); 1300 push(new js.Binary('/', jsLeft, pop())
1296 push(new js.Binary('|', pop(), new js.LiteralNumber("0")), node); 1301 .withSourceInformation(node.sourceInformation));
1302 push(new js.Binary('|', pop(), new js.LiteralNumber("0"))
1303 .withSourceInformation(node.sourceInformation));
1297 } 1304 }
1298 1305
1299 visitNegate(HNegate node) => visitInvokeUnary(node, '-'); 1306 visitNegate(HNegate node) => visitInvokeUnary(node, '-');
1300 1307
1301 visitLess(HLess node) => visitRelational(node, '<'); 1308 visitLess(HLess node) => visitRelational(node, '<');
1302 visitLessEqual(HLessEqual node) => visitRelational(node, '<='); 1309 visitLessEqual(HLessEqual node) => visitRelational(node, '<=');
1303 visitGreater(HGreater node) => visitRelational(node, '>'); 1310 visitGreater(HGreater node) => visitRelational(node, '>');
1304 visitGreaterEqual(HGreaterEqual node) => visitRelational(node, '>='); 1311 visitGreaterEqual(HGreaterEqual node) => visitRelational(node, '>=');
1305 1312
1306 visitBoolify(HBoolify node) { 1313 visitBoolify(HBoolify node) {
1307 assert(node.inputs.length == 1); 1314 assert(node.inputs.length == 1);
1308 use(node.inputs[0]); 1315 use(node.inputs[0]);
1309 push(new js.Binary('===', pop(), newLiteralBool(true)), node); 1316 push(new js.Binary('===', pop(),
1317 newLiteralBool(true, node.sourceInformation))
1318 .withSourceInformation(node.sourceInformation));
1310 } 1319 }
1311 1320
1312 visitExit(HExit node) { 1321 visitExit(HExit node) {
1313 // Don't do anything. 1322 // Don't do anything.
1314 } 1323 }
1315 1324
1316 visitGoto(HGoto node) { 1325 visitGoto(HGoto node) {
1317 HBasicBlock block = node.block; 1326 HBasicBlock block = node.block;
1318 assert(block.successors.length == 1); 1327 assert(block.successors.length == 1);
1319 List<HBasicBlock> dominated = block.dominatedBlocks; 1328 List<HBasicBlock> dominated = block.dominatedBlocks;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1355 if (action == null) return false; 1364 if (action == null) return false;
1356 action(entity); 1365 action(entity);
1357 return true; 1366 return true;
1358 } 1367 }
1359 1368
1360 visitBreak(HBreak node) { 1369 visitBreak(HBreak node) {
1361 assert(node.block.successors.length == 1); 1370 assert(node.block.successors.length == 1);
1362 if (node.label != null) { 1371 if (node.label != null) {
1363 LabelDefinition label = node.label; 1372 LabelDefinition label = node.label;
1364 if (!tryCallAction(breakAction, label)) { 1373 if (!tryCallAction(breakAction, label)) {
1365 pushStatement(new js.Break(backend.namer.breakLabelName(label)), node); 1374 pushStatement(
1375 new js.Break(backend.namer.breakLabelName(label))
1376 .withSourceInformation(node.sourceInformation));
1366 } 1377 }
1367 } else { 1378 } else {
1368 JumpTarget target = node.target; 1379 JumpTarget target = node.target;
1369 if (!tryCallAction(breakAction, target)) { 1380 if (!tryCallAction(breakAction, target)) {
1370 if (node.breakSwitchContinueLoop) { 1381 if (node.breakSwitchContinueLoop) {
1371 pushStatement(new js.Break( 1382 pushStatement(
1372 backend.namer.implicitContinueLabelName(target)), node); 1383 new js.Break(backend.namer.implicitContinueLabelName(target))
1384 .withSourceInformation(node.sourceInformation));
1373 } else { 1385 } else {
1374 pushStatement(new js.Break(null), node); 1386 pushStatement(new js.Break(null)
1387 .withSourceInformation(node.sourceInformation));
1375 } 1388 }
1376 } 1389 }
1377 } 1390 }
1378 } 1391 }
1379 1392
1380 visitContinue(HContinue node) { 1393 visitContinue(HContinue node) {
1381 assert(node.block.successors.length == 1); 1394 assert(node.block.successors.length == 1);
1382 if (node.label != null) { 1395 if (node.label != null) {
1383 LabelDefinition label = node.label; 1396 LabelDefinition label = node.label;
1384 if (!tryCallAction(continueAction, label)) { 1397 if (!tryCallAction(continueAction, label)) {
1385 // TODO(floitsch): should this really be the breakLabelName? 1398 // TODO(floitsch): should this really be the breakLabelName?
1386 pushStatement(new js.Continue(backend.namer.breakLabelName(label)), 1399 pushStatement(
1387 node); 1400 new js.Continue(backend.namer.breakLabelName(label))
1401 .withSourceInformation(node.sourceInformation));
1388 } 1402 }
1389 } else { 1403 } else {
1390 JumpTarget target = node.target; 1404 JumpTarget target = node.target;
1391 if (!tryCallAction(continueAction, target)) { 1405 if (!tryCallAction(continueAction, target)) {
1392 if (target.statement is ast.SwitchStatement) { 1406 if (target.statement is ast.SwitchStatement) {
1393 pushStatement(new js.Continue( 1407 pushStatement(
1394 backend.namer.implicitContinueLabelName(target)), node); 1408 new js.Continue(backend.namer.implicitContinueLabelName(target))
1409 .withSourceInformation(node.sourceInformation));
1395 } else { 1410 } else {
1396 pushStatement(new js.Continue(null), node); 1411 pushStatement(new js.Continue(null)
1412 .withSourceInformation(node.sourceInformation));
1397 } 1413 }
1398 } 1414 }
1399 } 1415 }
1400 } 1416 }
1401 1417
1402 visitExitTry(HExitTry node) { 1418 visitExitTry(HExitTry node) {
1403 // An [HExitTry] is used to represent the control flow graph of a 1419 // An [HExitTry] is used to represent the control flow graph of a
1404 // try/catch block, ie the try body is always a predecessor 1420 // try/catch block, ie the try body is always a predecessor
1405 // of the catch and finally. Here, we continue visiting the try 1421 // of the catch and finally. Here, we continue visiting the try
1406 // body by visiting the block that contains the user-level control 1422 // body by visiting the block that contains the user-level control
(...skipping 30 matching lines...) Expand all
1437 use(node.inputs[0]); 1453 use(node.inputs[0]);
1438 js.Expression test = pop(); 1454 js.Expression test = pop();
1439 1455
1440 HStatementInformation thenGraph = info.thenGraph; 1456 HStatementInformation thenGraph = info.thenGraph;
1441 HStatementInformation elseGraph = info.elseGraph; 1457 HStatementInformation elseGraph = info.elseGraph;
1442 js.Statement thenPart = 1458 js.Statement thenPart =
1443 unwrapStatement(generateStatementsInNewBlock(thenGraph)); 1459 unwrapStatement(generateStatementsInNewBlock(thenGraph));
1444 js.Statement elsePart = 1460 js.Statement elsePart =
1445 unwrapStatement(generateStatementsInNewBlock(elseGraph)); 1461 unwrapStatement(generateStatementsInNewBlock(elseGraph));
1446 1462
1447 pushStatement(new js.If(test, thenPart, elsePart), node); 1463 pushStatement(new js.If(test, thenPart, elsePart)
1464 .withSourceInformation(node.sourceInformation));
1448 } 1465 }
1449 1466
1450 visitIf(HIf node) { 1467 visitIf(HIf node) {
1451 if (tryControlFlowOperation(node)) return; 1468 if (tryControlFlowOperation(node)) return;
1452 1469
1453 HInstruction condition = node.inputs[0]; 1470 HInstruction condition = node.inputs[0];
1454 HIfBlockInformation info = node.blockInformation.body; 1471 HIfBlockInformation info = node.blockInformation.body;
1455 1472
1456 if (condition.isConstant()) { 1473 if (condition.isConstant()) {
1457 HConstant constant = condition; 1474 HConstant constant = condition;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1492 push(js.js('# && #', [receiverExpression, constant])); 1509 push(js.js('# && #', [receiverExpression, constant]));
1493 } else { 1510 } else {
1494 assert(node.inputs.length == 1); 1511 assert(node.inputs.length == 1);
1495 registry.registerSpecializedGetInterceptor(node.interceptedClasses); 1512 registry.registerSpecializedGetInterceptor(node.interceptedClasses);
1496 js.Name name = 1513 js.Name name =
1497 backend.namer.nameForGetInterceptor(node.interceptedClasses); 1514 backend.namer.nameForGetInterceptor(node.interceptedClasses);
1498 var isolate = new js.VariableUse( 1515 var isolate = new js.VariableUse(
1499 backend.namer.globalObjectFor(backend.interceptorsLibrary)); 1516 backend.namer.globalObjectFor(backend.interceptorsLibrary));
1500 use(node.receiver); 1517 use(node.receiver);
1501 List<js.Expression> arguments = <js.Expression>[pop()]; 1518 List<js.Expression> arguments = <js.Expression>[pop()];
1502 push(js.propertyCall(isolate, name, arguments), node); 1519 push(js.propertyCall(isolate, name, arguments)
1520 .withSourceInformation(node.sourceInformation));
1503 registry.registerUseInterceptor(); 1521 registry.registerUseInterceptor();
1504 } 1522 }
1505 } 1523 }
1506 1524
1507 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { 1525 visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
1508 use(node.receiver); 1526 use(node.receiver);
1509 js.Expression object = pop(); 1527 js.Expression object = pop();
1510 String methodName; 1528 String methodName;
1511 List<js.Expression> arguments = visitArguments(node.inputs); 1529 List<js.Expression> arguments = visitArguments(node.inputs);
1512 Element target = node.element; 1530 Element target = node.element;
(...skipping 18 matching lines...) Expand all
1531 } 1549 }
1532 } 1550 }
1533 1551
1534 js.Name methodLiteral; 1552 js.Name methodLiteral;
1535 if (methodName == null) { 1553 if (methodName == null) {
1536 methodLiteral = backend.namer.invocationName(node.selector); 1554 methodLiteral = backend.namer.invocationName(node.selector);
1537 registerMethodInvoke(node); 1555 registerMethodInvoke(node);
1538 } else { 1556 } else {
1539 methodLiteral = backend.namer.asName(methodName); 1557 methodLiteral = backend.namer.asName(methodName);
1540 } 1558 }
1541 push(js.propertyCall(object, methodLiteral, arguments), node); 1559 push(js.propertyCall(object, methodLiteral, arguments)
1560 .withSourceInformation(node.sourceInformation));
1542 } 1561 }
1543 1562
1544 void visitInvokeConstructorBody(HInvokeConstructorBody node) { 1563 void visitInvokeConstructorBody(HInvokeConstructorBody node) {
1545 use(node.inputs[0]); 1564 use(node.inputs[0]);
1546 js.Expression object = pop(); 1565 js.Expression object = pop();
1547 js.Name methodName = backend.namer.instanceMethodName(node.element); 1566 js.Name methodName = backend.namer.instanceMethodName(node.element);
1548 List<js.Expression> arguments = visitArguments(node.inputs); 1567 List<js.Expression> arguments = visitArguments(node.inputs);
1549 push(js.propertyCall(object, methodName, arguments), node); 1568 push(js.propertyCall(object, methodName, arguments)
1569 .withSourceInformation(node.sourceInformation));
1550 registry.registerStaticUse(node.element); 1570 registry.registerStaticUse(node.element);
1551 } 1571 }
1552 1572
1553 void visitOneShotInterceptor(HOneShotInterceptor node) { 1573 void visitOneShotInterceptor(HOneShotInterceptor node) {
1554 List<js.Expression> arguments = visitArguments(node.inputs); 1574 List<js.Expression> arguments = visitArguments(node.inputs);
1555 var isolate = new js.VariableUse( 1575 var isolate = new js.VariableUse(
1556 backend.namer.globalObjectFor(backend.interceptorsLibrary)); 1576 backend.namer.globalObjectFor(backend.interceptorsLibrary));
1557 Selector selector = node.selector; 1577 Selector selector = node.selector;
1558 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask); 1578 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
1559 js.Name methodName = backend.registerOneShotInterceptor(selector); 1579 js.Name methodName = backend.registerOneShotInterceptor(selector);
1560 push(js.propertyCall(isolate, methodName, arguments), node); 1580 push(js.propertyCall(isolate, methodName, arguments)
1581 .withSourceInformation(node.sourceInformation));
1561 if (selector.isGetter) { 1582 if (selector.isGetter) {
1562 registerGetter(node); 1583 registerGetter(node);
1563 } else if (selector.isSetter) { 1584 } else if (selector.isSetter) {
1564 registerSetter(node); 1585 registerSetter(node);
1565 } else { 1586 } else {
1566 registerMethodInvoke(node); 1587 registerMethodInvoke(node);
1567 } 1588 }
1568 registry.registerUseInterceptor(); 1589 registry.registerUseInterceptor();
1569 } 1590 }
1570 1591
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1615 void registerGetter(HInvokeDynamic node) { 1636 void registerGetter(HInvokeDynamic node) {
1616 Selector selector = node.selector; 1637 Selector selector = node.selector;
1617 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask); 1638 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
1618 registry.registerDynamicGetter( 1639 registry.registerDynamicGetter(
1619 new UniverseSelector(selector, mask)); 1640 new UniverseSelector(selector, mask));
1620 } 1641 }
1621 1642
1622 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { 1643 visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
1623 use(node.receiver); 1644 use(node.receiver);
1624 js.Name name = backend.namer.invocationName(node.selector); 1645 js.Name name = backend.namer.invocationName(node.selector);
1625 push(js.propertyCall(pop(), name, visitArguments(node.inputs)), node); 1646 push(js.propertyCall(pop(), name, visitArguments(node.inputs))
1647 .withSourceInformation(node.sourceInformation));
1626 registerSetter(node); 1648 registerSetter(node);
1627 } 1649 }
1628 1650
1629 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { 1651 visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
1630 use(node.receiver); 1652 use(node.receiver);
1631 js.Name name = backend.namer.invocationName(node.selector); 1653 js.Name name = backend.namer.invocationName(node.selector);
1632 push(js.propertyCall(pop(), name, visitArguments(node.inputs)), node); 1654 push(js.propertyCall(pop(), name, visitArguments(node.inputs))
1655 .withSourceInformation(node.sourceInformation));
1633 registerGetter(node); 1656 registerGetter(node);
1634 } 1657 }
1635 1658
1636 visitInvokeClosure(HInvokeClosure node) { 1659 visitInvokeClosure(HInvokeClosure node) {
1637 Selector call = new Selector.callClosureFrom(node.selector); 1660 Selector call = new Selector.callClosureFrom(node.selector);
1638 use(node.receiver); 1661 use(node.receiver);
1639 push(js.propertyCall(pop(), 1662 push(js.propertyCall(pop(),
1640 backend.namer.invocationName(call), 1663 backend.namer.invocationName(call),
1641 visitArguments(node.inputs)), 1664 visitArguments(node.inputs))
1642 node); 1665 .withSourceInformation(node.sourceInformation));
1643 registry.registerDynamicInvocation( 1666 registry.registerDynamicInvocation(
1644 new UniverseSelector(call, null)); 1667 new UniverseSelector(call, null));
1645 } 1668 }
1646 1669
1647 visitInvokeStatic(HInvokeStatic node) { 1670 visitInvokeStatic(HInvokeStatic node) {
1648 Element element = node.element; 1671 Element element = node.element;
1649 List<DartType> instantiatedTypes = node.instantiatedTypes; 1672 List<DartType> instantiatedTypes = node.instantiatedTypes;
1650 1673
1651 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) { 1674 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) {
1652 instantiatedTypes.forEach((type) { 1675 instantiatedTypes.forEach((type) {
(...skipping 21 matching lines...) Expand all
1674 // more optimizations available to the loop. This form is 50% faster on 1697 // more optimizations available to the loop. This form is 50% faster on
1675 // some small loop, almost as fast as loops with no concurrent 1698 // some small loop, almost as fast as loops with no concurrent
1676 // modification check. 1699 // modification check.
1677 push(js.js('# || (0, #)(#)',[ 1700 push(js.js('# || (0, #)(#)',[
1678 arguments[0], 1701 arguments[0],
1679 backend.emitter.staticFunctionAccess(throwFunction), 1702 backend.emitter.staticFunctionAccess(throwFunction),
1680 arguments[1]])); 1703 arguments[1]]));
1681 } else { 1704 } else {
1682 registry.registerStaticInvocation(element); 1705 registry.registerStaticInvocation(element);
1683 push(backend.emitter.staticFunctionAccess(element)); 1706 push(backend.emitter.staticFunctionAccess(element));
1684 push(new js.Call(pop(), arguments), node); 1707 push(new js.Call(pop(), arguments,
1708 sourceInformation: node.sourceInformation));
1685 } 1709 }
1686 1710
1687 } 1711 }
1688 1712
1689 visitInvokeSuper(HInvokeSuper node) { 1713 visitInvokeSuper(HInvokeSuper node) {
1690 Element superMethod = node.element; 1714 Element superMethod = node.element;
1691 registry.registerSuperInvocation(superMethod); 1715 registry.registerSuperInvocation(superMethod);
1692 ClassElement superClass = superMethod.enclosingClass; 1716 ClassElement superClass = superMethod.enclosingClass;
1693 if (superMethod.kind == ElementKind.FIELD) { 1717 if (superMethod.kind == ElementKind.FIELD) {
1694 js.Name fieldName = 1718 js.Name fieldName =
1695 backend.namer.instanceFieldPropertyName(superMethod); 1719 backend.namer.instanceFieldPropertyName(superMethod);
1696 use(node.inputs[0]); 1720 use(node.inputs[0]);
1697 js.PropertyAccess access = new js.PropertyAccess(pop(), fieldName); 1721 js.PropertyAccess access =
1722 new js.PropertyAccess(pop(), fieldName)
1723 .withSourceInformation(node.sourceInformation);
1698 if (node.isSetter) { 1724 if (node.isSetter) {
1699 use(node.value); 1725 use(node.value);
1700 push(new js.Assignment(access, pop()), node); 1726 push(new js.Assignment(access, pop())
1727 .withSourceInformation(node.sourceInformation));
1701 } else { 1728 } else {
1702 push(access, node); 1729 push(access);
1703 } 1730 }
1704 } else { 1731 } else {
1705 Selector selector = node.selector; 1732 Selector selector = node.selector;
1706 1733
1707 if (!backend.maybeRegisterAliasedSuperMember(superMethod, selector)) { 1734 if (!backend.maybeRegisterAliasedSuperMember(superMethod, selector)) {
1708 js.Name methodName; 1735 js.Name methodName;
1709 if (selector.isGetter) { 1736 if (selector.isGetter) {
1710 // If the selector we need to register a typed getter to the 1737 // If the selector we need to register a typed getter to the
1711 // [world]. The emitter needs to know if it needs to emit a 1738 // [world]. The emitter needs to know if it needs to emit a
1712 // bound closure for a method. 1739 // bound closure for a method.
1713 TypeMask receiverType = 1740 TypeMask receiverType =
1714 new TypeMask.nonNullExact(superClass, compiler.world); 1741 new TypeMask.nonNullExact(superClass, compiler.world);
1715 // TODO(floitsch): we know the target. We shouldn't register a 1742 // TODO(floitsch): we know the target. We shouldn't register a
1716 // dynamic getter. 1743 // dynamic getter.
1717 registry.registerDynamicGetter( 1744 registry.registerDynamicGetter(
1718 new UniverseSelector(selector, receiverType)); 1745 new UniverseSelector(selector, receiverType));
1719 registry.registerGetterForSuperMethod(node.element); 1746 registry.registerGetterForSuperMethod(node.element);
1720 methodName = backend.namer.invocationName(selector); 1747 methodName = backend.namer.invocationName(selector);
1721 } else { 1748 } else {
1722 assert(invariant(node, compiler.hasIncrementalSupport)); 1749 assert(invariant(node, compiler.hasIncrementalSupport));
1723 methodName = backend.namer.instanceMethodName(superMethod); 1750 methodName = backend.namer.instanceMethodName(superMethod);
1724 } 1751 }
1725 push(js.js('#.#.call(#)', 1752 push(js.js('#.#.call(#)',
1726 [backend.emitter.prototypeAccess(superClass, 1753 [backend.emitter.prototypeAccess(superClass,
1727 hasBeenInstantiated: true), 1754 hasBeenInstantiated: true),
1728 methodName, visitArguments(node.inputs, start: 0)]), 1755 methodName, visitArguments(node.inputs, start: 0)])
1729 node); 1756 .withSourceInformation(node.sourceInformation));
1730 } else { 1757 } else {
1731 use(node.receiver); 1758 use(node.receiver);
1732 push( 1759 push(
1733 js.js('#.#(#)', [ 1760 js.js('#.#(#)', [
1734 pop(), backend.namer.aliasedSuperMemberPropertyName(superMethod), 1761 pop(), backend.namer.aliasedSuperMemberPropertyName(superMethod),
1735 visitArguments(node.inputs, start: 1)]), // Skip receiver argument. 1762 visitArguments(node.inputs, start: 1)]) // Skip receiver argument.
1736 node); 1763 .withSourceInformation(node.sourceInformation));
1737 } 1764 }
1738 } 1765 }
1739 } 1766 }
1740 1767
1741 visitFieldGet(HFieldGet node) { 1768 visitFieldGet(HFieldGet node) {
1742 use(node.receiver); 1769 use(node.receiver);
1743 Element element = node.element; 1770 Element element = node.element;
1744 if (node.isNullCheck) { 1771 if (node.isNullCheck) {
1745 // We access a JavaScript member we know all objects besides 1772 // We access a JavaScript member we know all objects besides
1746 // null and undefined have: V8 does not like accessing a member 1773 // null and undefined have: V8 does not like accessing a member
1747 // that does not exist. 1774 // that does not exist.
1748 push(new js.PropertyAccess.field(pop(), 'toString'), node); 1775 push(new js.PropertyAccess.field(pop(), 'toString')
1776 .withSourceInformation(node.sourceInformation));
1749 } else if (element == backend.jsIndexableLength) { 1777 } else if (element == backend.jsIndexableLength) {
1750 // We're accessing a native JavaScript property called 'length' 1778 // We're accessing a native JavaScript property called 'length'
1751 // on a JS String or a JS array. Therefore, the name of that 1779 // on a JS String or a JS array. Therefore, the name of that
1752 // property should not be mangled. 1780 // property should not be mangled.
1753 push(new js.PropertyAccess.field(pop(), 'length'), node); 1781 push(new js.PropertyAccess.field(pop(), 'length')
1782 .withSourceInformation(node.sourceInformation));
1754 } else { 1783 } else {
1755 js.Name name = backend.namer.instanceFieldPropertyName(element); 1784 js.Name name = backend.namer.instanceFieldPropertyName(element);
1756 push(new js.PropertyAccess(pop(), name), node); 1785 push(new js.PropertyAccess(pop(), name)
1786 .withSourceInformation(node.sourceInformation));
1757 registry.registerFieldGetter(element); 1787 registry.registerFieldGetter(element);
1758 } 1788 }
1759 } 1789 }
1760 1790
1761 visitFieldSet(HFieldSet node) { 1791 visitFieldSet(HFieldSet node) {
1762 Element element = node.element; 1792 Element element = node.element;
1763 registry.registerFieldSetter(element); 1793 registry.registerFieldSetter(element);
1764 js.Name name = backend.namer.instanceFieldPropertyName(element); 1794 js.Name name = backend.namer.instanceFieldPropertyName(element);
1765 use(node.receiver); 1795 use(node.receiver);
1766 js.Expression receiver = pop(); 1796 js.Expression receiver = pop();
1767 use(node.value); 1797 use(node.value);
1768 push(new js.Assignment(new js.PropertyAccess(receiver, name), pop()), 1798 push(new js.Assignment(new js.PropertyAccess(receiver, name), pop())
1769 node); 1799 .withSourceInformation(node.sourceInformation));
1770 } 1800 }
1771 1801
1772 visitReadModifyWrite(HReadModifyWrite node) { 1802 visitReadModifyWrite(HReadModifyWrite node) {
1773 Element element = node.element; 1803 Element element = node.element;
1774 registry.registerFieldSetter(element); 1804 registry.registerFieldSetter(element);
1775 js.Name name = backend.namer.instanceFieldPropertyName(element); 1805 js.Name name = backend.namer.instanceFieldPropertyName(element);
1776 use(node.receiver); 1806 use(node.receiver);
1777 js.Expression fieldReference = new js.PropertyAccess(pop(), name); 1807 js.Expression fieldReference = new js.PropertyAccess(pop(), name);
1778 if (node.isPreOp) { 1808 if (node.isPreOp) {
1779 push(new js.Prefix(node.jsOp, fieldReference), node); 1809 push(new js.Prefix(node.jsOp, fieldReference)
1810 .withSourceInformation(node.sourceInformation));
1780 } else if (node.isPostOp) { 1811 } else if (node.isPostOp) {
1781 push(new js.Postfix(node.jsOp, fieldReference), node); 1812 push(new js.Postfix(node.jsOp, fieldReference)
1813 .withSourceInformation(node.sourceInformation));
1782 } else { 1814 } else {
1783 use(node.value); 1815 use(node.value);
1784 push(new js.Assignment.compound(fieldReference, node.jsOp, pop()), node); 1816 push(new js.Assignment.compound(fieldReference, node.jsOp, pop())
1817 .withSourceInformation(node.sourceInformation));
1785 } 1818 }
1786 } 1819 }
1787 1820
1788 visitLocalGet(HLocalGet node) { 1821 visitLocalGet(HLocalGet node) {
1789 use(node.receiver); 1822 use(node.receiver);
1790 } 1823 }
1791 1824
1792 visitLocalSet(HLocalSet node) { 1825 visitLocalSet(HLocalSet node) {
1793 use(node.value); 1826 use(node.value);
1794 assignVariable(variableNames.getName(node.receiver), pop()); 1827 assignVariable(variableNames.getName(node.receiver),
1828 pop(),
1829 node.sourceInformation);
1795 } 1830 }
1796 1831
1797 void registerForeignTypes(HForeign node) { 1832 void registerForeignTypes(HForeign node) {
1798 native.NativeBehavior nativeBehavior = node.nativeBehavior; 1833 native.NativeBehavior nativeBehavior = node.nativeBehavior;
1799 if (nativeBehavior == null) return; 1834 if (nativeBehavior == null) return;
1800 nativeBehavior.typesReturned.forEach((type) { 1835 nativeBehavior.typesReturned.forEach((type) {
1801 if (type is InterfaceType) { 1836 if (type is InterfaceType) {
1802 registry.registerInstantiatedType(type); 1837 registry.registerInstantiatedType(type);
1803 } 1838 }
1804 }); 1839 });
1805 } 1840 }
1806 1841
1807 visitForeignCode(HForeignCode node) { 1842 visitForeignCode(HForeignCode node) {
1808 List<HInstruction> inputs = node.inputs; 1843 List<HInstruction> inputs = node.inputs;
1809 if (node.isJsStatement()) { 1844 if (node.isJsStatement()) {
1810 List<js.Expression> interpolatedExpressions = <js.Expression>[]; 1845 List<js.Expression> interpolatedExpressions = <js.Expression>[];
1811 for (int i = 0; i < inputs.length; i++) { 1846 for (int i = 0; i < inputs.length; i++) {
1812 use(inputs[i]); 1847 use(inputs[i]);
1813 interpolatedExpressions.add(pop()); 1848 interpolatedExpressions.add(pop());
1814 } 1849 }
1815 pushStatement(node.codeTemplate.instantiate(interpolatedExpressions)); 1850 pushStatement(node.codeTemplate.instantiate(interpolatedExpressions)
1851 .withSourceInformation(node.sourceInformation));
1816 } else { 1852 } else {
1817 List<js.Expression> interpolatedExpressions = <js.Expression>[]; 1853 List<js.Expression> interpolatedExpressions = <js.Expression>[];
1818 for (int i = 0; i < inputs.length; i++) { 1854 for (int i = 0; i < inputs.length; i++) {
1819 use(inputs[i]); 1855 use(inputs[i]);
1820 interpolatedExpressions.add(pop()); 1856 interpolatedExpressions.add(pop());
1821 } 1857 }
1822 push(node.codeTemplate.instantiate(interpolatedExpressions)); 1858 push(node.codeTemplate.instantiate(interpolatedExpressions)
1859 .withSourceInformation(node.sourceInformation));
1823 } 1860 }
1824 1861
1825 // TODO(sra): Tell world.nativeEnqueuer about the types created here. 1862 // TODO(sra): Tell world.nativeEnqueuer about the types created here.
1826 registerForeignTypes(node); 1863 registerForeignTypes(node);
1827 } 1864 }
1828 1865
1829 visitForeignNew(HForeignNew node) { 1866 visitForeignNew(HForeignNew node) {
1830 js.Expression jsClassReference = 1867 js.Expression jsClassReference =
1831 backend.emitter.constructorAccess(node.element); 1868 backend.emitter.constructorAccess(node.element);
1832 List<js.Expression> arguments = visitArguments(node.inputs, start: 0); 1869 List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
1833 push(new js.New(jsClassReference, arguments), node); 1870 push(new js.New(jsClassReference, arguments)
1871 .withSourceInformation(node.sourceInformation));
1834 registerForeignTypes(node); 1872 registerForeignTypes(node);
1835 // We also use ForeignNew to instantiate closure classes that belong to 1873 // We also use ForeignNew to instantiate closure classes that belong to
1836 // function expressions. We have to register their use here, as otherwise 1874 // function expressions. We have to register their use here, as otherwise
1837 // code for them might not be emitted. 1875 // code for them might not be emitted.
1838 if (node.element.isClosure) { 1876 if (node.element.isClosure) {
1839 registry.registerInstantiatedClass(node.element); 1877 registry.registerInstantiatedClass(node.element);
1840 } 1878 }
1841 if (node.instantiatedTypes == null) { 1879 if (node.instantiatedTypes == null) {
1842 return; 1880 return;
1843 } 1881 }
1844 node.instantiatedTypes.forEach((type) { 1882 node.instantiatedTypes.forEach((type) {
1845 registry.registerInstantiatedType(type); 1883 registry.registerInstantiatedType(type);
1846 }); 1884 });
1847 } 1885 }
1848 1886
1849 js.Expression newLiteralBool(bool value) { 1887 js.Expression newLiteralBool(bool value,
1888 SourceInformation sourceInformation) {
1850 if (compiler.enableMinification) { 1889 if (compiler.enableMinification) {
1851 // Use !0 for true, !1 for false. 1890 // Use !0 for true, !1 for false.
1852 return new js.Prefix("!", new js.LiteralNumber(value ? "0" : "1")); 1891 return new js.Prefix("!", new js.LiteralNumber(value ? "0" : "1"))
1892 .withSourceInformation(sourceInformation);
1853 } else { 1893 } else {
1854 return new js.LiteralBool(value); 1894 return new js.LiteralBool(value)
1895 .withSourceInformation(sourceInformation);
1855 } 1896 }
1856 } 1897 }
1857 1898
1858 void generateConstant(ConstantValue constant) { 1899 void generateConstant(ConstantValue constant,
1900 SourceInformation sourceInformation) {
1859 if (constant.isFunction) { 1901 if (constant.isFunction) {
1860 FunctionConstantValue function = constant; 1902 FunctionConstantValue function = constant;
1861 registry.registerStaticUse(function.element); 1903 registry.registerStaticUse(function.element);
1862 } 1904 }
1863 if (constant.isType) { 1905 if (constant.isType) {
1864 // If the type is a web component, we need to ensure the constructors are 1906 // If the type is a web component, we need to ensure the constructors are
1865 // available to 'upgrade' the native object. 1907 // available to 'upgrade' the native object.
1866 TypeConstantValue type = constant; 1908 TypeConstantValue type = constant;
1867 Element element = type.representedType.element; 1909 Element element = type.representedType.element;
1868 if (element != null && element.isClass) { 1910 if (element != null && element.isClass) {
1869 registry.registerTypeConstant(element); 1911 registry.registerTypeConstant(element);
1870 } 1912 }
1871 } 1913 }
1872 push(backend.emitter.constantReference(constant)); 1914 push(backend.emitter.constantReference(constant)
1915 .withSourceInformation(sourceInformation));
1873 } 1916 }
1874 1917
1875 visitConstant(HConstant node) { 1918 visitConstant(HConstant node) {
1876 assert(isGenerateAtUseSite(node)); 1919 assert(isGenerateAtUseSite(node));
1877 generateConstant(node.constant); 1920 generateConstant(node.constant, node.sourceInformation);
1878 1921
1879 registry.registerCompileTimeConstant(node.constant); 1922 registry.registerCompileTimeConstant(node.constant);
1880 backend.constants.addCompileTimeConstantForEmission(node.constant); 1923 backend.constants.addCompileTimeConstantForEmission(node.constant);
1881 } 1924 }
1882 1925
1883 visitNot(HNot node) { 1926 visitNot(HNot node) {
1884 assert(node.inputs.length == 1); 1927 assert(node.inputs.length == 1);
1885 generateNot(node.inputs[0]); 1928 generateNot(node.inputs[0], node.sourceInformation);
1886 attachLocationToLast(node);
1887 } 1929 }
1888 1930
1889 static String mapRelationalOperator(String op, bool inverse) { 1931 static String mapRelationalOperator(String op, bool inverse) {
1890 Map<String, String> inverseOperator = const <String, String>{ 1932 Map<String, String> inverseOperator = const <String, String>{
1891 "==" : "!=", 1933 "==" : "!=",
1892 "!=" : "==", 1934 "!=" : "==",
1893 "===": "!==", 1935 "===": "!==",
1894 "!==": "===", 1936 "!==": "===",
1895 "<" : ">=", 1937 "<" : ">=",
1896 "<=" : ">", 1938 "<=" : ">",
1897 ">" : "<=", 1939 ">" : "<=",
1898 ">=" : "<" 1940 ">=" : "<"
1899 }; 1941 };
1900 return inverse ? inverseOperator[op] : op; 1942 return inverse ? inverseOperator[op] : op;
1901 } 1943 }
1902 1944
1903 void generateNot(HInstruction input) { 1945 void generateNot(HInstruction input, SourceInformation sourceInformation) {
1904 bool canGenerateOptimizedComparison(HInstruction instruction) { 1946 bool canGenerateOptimizedComparison(HInstruction instruction) {
1905 if (instruction is !HRelational) return false; 1947 if (instruction is !HRelational) return false;
1906 1948
1907 HRelational relational = instruction; 1949 HRelational relational = instruction;
1908 1950
1909 HInstruction left = relational.left; 1951 HInstruction left = relational.left;
1910 HInstruction right = relational.right; 1952 HInstruction right = relational.right;
1911 if (left.isStringOrNull(compiler) && right.isStringOrNull(compiler)) { 1953 if (left.isStringOrNull(compiler) && right.isStringOrNull(compiler)) {
1912 return true; 1954 return true;
1913 } 1955 }
1914 1956
1915 // This optimization doesn't work for NaN, so we only do it if the 1957 // This optimization doesn't work for NaN, so we only do it if the
1916 // type is known to be an integer. 1958 // type is known to be an integer.
1917 return left.isInteger(compiler) && right.isInteger(compiler); 1959 return left.isInteger(compiler) && right.isInteger(compiler);
1918 } 1960 }
1919 1961
1920 bool handledBySpecialCase = false; 1962 bool handledBySpecialCase = false;
1921 if (isGenerateAtUseSite(input)) { 1963 if (isGenerateAtUseSite(input)) {
1922 handledBySpecialCase = true; 1964 handledBySpecialCase = true;
1923 if (input is HIs) { 1965 if (input is HIs) {
1924 emitIs(input, '!=='); 1966 emitIs(input, '!==', sourceInformation);
1925 } else if (input is HIsViaInterceptor) { 1967 } else if (input is HIsViaInterceptor) {
1926 emitIsViaInterceptor(input, true); 1968 emitIsViaInterceptor(input, sourceInformation, negative: true);
1927 } else if (input is HNot) { 1969 } else if (input is HNot) {
1928 use(input.inputs[0]); 1970 use(input.inputs[0]);
1929 } else if (input is HIdentity) { 1971 } else if (input is HIdentity) {
1930 emitIdentityComparison(input, true); 1972 emitIdentityComparison(input, sourceInformation, inverse: true);
1931 } else if (input is HBoolify) { 1973 } else if (input is HBoolify) {
1932 use(input.inputs[0]); 1974 use(input.inputs[0]);
1933 push(new js.Binary("!==", pop(), newLiteralBool(true)), input); 1975 push(new js.Binary("!==", pop(),
1976 newLiteralBool(true, input.sourceInformation))
1977 .withSourceInformation(sourceInformation));
1934 } else if (canGenerateOptimizedComparison(input)) { 1978 } else if (canGenerateOptimizedComparison(input)) {
1935 HRelational relational = input; 1979 HRelational relational = input;
1936 BinaryOperation operation = 1980 BinaryOperation operation =
1937 relational.operation(backend.constantSystem); 1981 relational.operation(backend.constantSystem);
1938 String op = mapRelationalOperator(operation.name, true); 1982 String op = mapRelationalOperator(operation.name, true);
1939 visitRelational(input, op); 1983 handleInvokeBinary(input, op, sourceInformation);
1940 } else { 1984 } else {
1941 handledBySpecialCase = false; 1985 handledBySpecialCase = false;
1942 } 1986 }
1943 } 1987 }
1944 if (!handledBySpecialCase) { 1988 if (!handledBySpecialCase) {
1945 use(input); 1989 use(input);
1946 push(new js.Prefix("!", pop())); 1990 push(new js.Prefix("!", pop()).withSourceInformation(sourceInformation));
1947 } 1991 }
1948 } 1992 }
1949 1993
1950 visitParameterValue(HParameterValue node) { 1994 visitParameterValue(HParameterValue node) {
1951 assert(!isGenerateAtUseSite(node)); 1995 assert(!isGenerateAtUseSite(node));
1952 String name = variableNames.getName(node); 1996 String name = variableNames.getName(node);
1953 parameters.add(new js.Parameter(name)); 1997 parameters.add(new js.Parameter(name));
1954 declaredLocals.add(name); 1998 declaredLocals.add(name);
1955 } 1999 }
1956 2000
(...skipping 10 matching lines...) Expand all
1967 HBasicBlock ifBlock = node.block.dominator; 2011 HBasicBlock ifBlock = node.block.dominator;
1968 assert(controlFlowOperators.contains(ifBlock.last)); 2012 assert(controlFlowOperators.contains(ifBlock.last));
1969 HInstruction input = ifBlock.last.inputs[0]; 2013 HInstruction input = ifBlock.last.inputs[0];
1970 if (input.isConstantFalse()) { 2014 if (input.isConstantFalse()) {
1971 use(node.inputs[1]); 2015 use(node.inputs[1]);
1972 } else if (input.isConstantTrue()) { 2016 } else if (input.isConstantTrue()) {
1973 use(node.inputs[0]); 2017 use(node.inputs[0]);
1974 } else if (node.inputs[1].isConstantBoolean()) { 2018 } else if (node.inputs[1].isConstantBoolean()) {
1975 String operation = node.inputs[1].isConstantFalse() ? '&&' : '||'; 2019 String operation = node.inputs[1].isConstantFalse() ? '&&' : '||';
1976 if (operation == '||') { 2020 if (operation == '||') {
1977 generateNot(input); 2021 generateNot(input, input.sourceInformation);
1978 } else { 2022 } else {
1979 use(input); 2023 use(input);
1980 } 2024 }
1981 js.Expression left = pop(); 2025 js.Expression left = pop();
1982 use(node.inputs[0]); 2026 use(node.inputs[0]);
1983 push(new js.Binary(operation, left, pop())); 2027 push(new js.Binary(operation, left, pop()));
1984 } else { 2028 } else {
1985 use(input); 2029 use(input);
1986 js.Expression test = pop(); 2030 js.Expression test = pop();
1987 use(node.inputs[0]); 2031 use(node.inputs[0]);
1988 js.Expression then = pop(); 2032 js.Expression then = pop();
1989 use(node.inputs[1]); 2033 use(node.inputs[1]);
1990 push(new js.Conditional(test, then, pop())); 2034 push(new js.Conditional(test, then, pop()));
1991 } 2035 }
1992 } 2036 }
1993 2037
1994 visitReturn(HReturn node) { 2038 visitReturn(HReturn node) {
1995 assert(node.inputs.length == 1); 2039 assert(node.inputs.length == 1);
1996 HInstruction input = node.inputs[0]; 2040 HInstruction input = node.inputs[0];
1997 if (input.isConstantNull()) { 2041 if (input.isConstantNull()) {
1998 pushStatement(new js.Return(null), node); 2042 pushStatement(new js.Return()
2043 .withSourceInformation(node.sourceInformation));
1999 } else { 2044 } else {
2000 use(node.inputs[0]); 2045 use(node.inputs[0]);
2001 pushStatement(new js.Return(pop()), node); 2046 pushStatement(new js.Return(pop())
2047 .withSourceInformation(node.sourceInformation));
2002 } 2048 }
2003 } 2049 }
2004 2050
2005 visitThis(HThis node) { 2051 visitThis(HThis node) {
2006 push(new js.This()); 2052 push(new js.This());
2007 } 2053 }
2008 2054
2009 visitThrow(HThrow node) { 2055 visitThrow(HThrow node) {
2010 if (node.isRethrow) { 2056 if (node.isRethrow) {
2011 use(node.inputs[0]); 2057 use(node.inputs[0]);
2012 pushStatement(new js.Throw(pop()), node); 2058 pushStatement(new js.Throw(pop())
2059 .withSourceInformation(node.sourceInformation));
2013 } else { 2060 } else {
2014 generateThrowWithHelper('wrapException', node.inputs[0]); 2061 generateThrowWithHelper('wrapException', node.inputs[0],
2062 sourceInformation: node.sourceInformation);
2015 } 2063 }
2016 } 2064 }
2017 2065
2018 visitAwait(HAwait node) { 2066 visitAwait(HAwait node) {
2019 use(node.inputs[0]); 2067 use(node.inputs[0]);
2020 push(new js.Await(pop()), node); 2068 push(new js.Await(pop())
2069 .withSourceInformation(node.sourceInformation));
2021 } 2070 }
2022 2071
2023 visitYield(HYield node) { 2072 visitYield(HYield node) {
2024 use(node.inputs[0]); 2073 use(node.inputs[0]);
2025 pushStatement(new js.DartYield(pop(), node.hasStar), node); 2074 pushStatement(new js.DartYield(pop(), node.hasStar)
2075 .withSourceInformation(node.sourceInformation));
2026 } 2076 }
2027 2077
2028 visitRangeConversion(HRangeConversion node) { 2078 visitRangeConversion(HRangeConversion node) {
2029 // Range conversion instructions are removed by the value range 2079 // Range conversion instructions are removed by the value range
2030 // analyzer. 2080 // analyzer.
2031 assert(false); 2081 assert(false);
2032 } 2082 }
2033 2083
2034 visitBoundsCheck(HBoundsCheck node) { 2084 visitBoundsCheck(HBoundsCheck node) {
2035 // TODO(ngeoffray): Separate the two checks of the bounds check, so, 2085 // TODO(ngeoffray): Separate the two checks of the bounds check, so,
(...skipping 29 matching lines...) Expand all
2065 ? over 2115 ? over
2066 : over == null 2116 : over == null
2067 ? under 2117 ? under
2068 : new js.Binary("||", under, over); 2118 : new js.Binary("||", under, over);
2069 js.Statement thenBody = new js.Block.empty(); 2119 js.Statement thenBody = new js.Block.empty();
2070 js.Block oldContainer = currentContainer; 2120 js.Block oldContainer = currentContainer;
2071 currentContainer = thenBody; 2121 currentContainer = thenBody;
2072 generateThrowWithHelper('ioore', [node.array, node.index]); 2122 generateThrowWithHelper('ioore', [node.array, node.index]);
2073 currentContainer = oldContainer; 2123 currentContainer = oldContainer;
2074 thenBody = unwrapStatement(thenBody); 2124 thenBody = unwrapStatement(thenBody);
2075 pushStatement(new js.If.noElse(underOver, thenBody), node); 2125 pushStatement(new js.If.noElse(underOver, thenBody)
2126 .withSourceInformation(node.sourceInformation));
2076 } else { 2127 } else {
2077 generateThrowWithHelper('ioore', [node.array, node.index]); 2128 generateThrowWithHelper('ioore', [node.array, node.index]);
2078 } 2129 }
2079 } 2130 }
2080 2131
2081 void generateThrowWithHelper(String helperName, argument) { 2132 void generateThrowWithHelper(String helperName, argument,
2133 {SourceInformation sourceInformation}) {
2082 Element helper = backend.findHelper(helperName); 2134 Element helper = backend.findHelper(helperName);
2083 registry.registerStaticUse(helper); 2135 registry.registerStaticUse(helper);
2084 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper); 2136 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper);
2085 List arguments = []; 2137 List arguments = [];
2086 var location; 2138 var location;
2087 if (argument is List) { 2139 if (argument is List) {
2088 location = argument[0]; 2140 location = argument[0];
2089 argument.forEach((instruction) { 2141 argument.forEach((instruction) {
2090 use(instruction); 2142 use(instruction);
2091 arguments.add(pop()); 2143 arguments.add(pop());
2092 }); 2144 });
2093 } else { 2145 } else {
2094 location = argument; 2146 location = argument;
2095 use(argument); 2147 use(argument);
2096 arguments.add(pop()); 2148 arguments.add(pop());
2097 } 2149 }
2098 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false)); 2150 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false),
2099 value = attachLocation(value, location); 2151 sourceInformation: sourceInformation);
2100 // BUG(4906): Using throw/return here adds to the size of the generated code 2152 // BUG(4906): Using throw/return here adds to the size of the generated code
2101 // but it has the advantage of explicitly telling the JS engine that 2153 // but it has the advantage of explicitly telling the JS engine that
2102 // this code path will terminate abruptly. Needs more work. 2154 // this code path will terminate abruptly. Needs more work.
2103 if (helperName == 'wrapException') { 2155 if (helperName == 'wrapException') {
2104 pushStatement(new js.Throw(value)); 2156 pushStatement(new js.Throw(value)
2157 .withSourceInformation(sourceInformation));
2105 } else { 2158 } else {
2106 Element element = work.element; 2159 Element element = work.element;
2107 if (element is FunctionElement && element.asyncMarker.isYielding) { 2160 if (element is FunctionElement && element.asyncMarker.isYielding) {
2108 // `return <expr>;` is illegal in a sync* or async* function. 2161 // `return <expr>;` is illegal in a sync* or async* function.
2109 // To have the the async-translator working, we avoid introducing 2162 // To have the the async-translator working, we avoid introducing
2110 // `return` nodes. 2163 // `return` nodes.
2111 pushStatement(new js.ExpressionStatement(value)); 2164 pushStatement(new js.ExpressionStatement(value)
2165 .withSourceInformation(sourceInformation));
2112 } else { 2166 } else {
2113 pushStatement(new js.Return(value)); 2167 pushStatement(new js.Return(value)
2168 .withSourceInformation(sourceInformation));
2114 } 2169 }
2115 } 2170 }
2116 } 2171 }
2117 2172
2118 visitThrowExpression(HThrowExpression node) { 2173 visitThrowExpression(HThrowExpression node) {
2119 HInstruction argument = node.inputs[0]; 2174 HInstruction argument = node.inputs[0];
2120 use(argument); 2175 use(argument);
2121 2176
2122 Element helper = backend.findHelper("throwExpression"); 2177 Element helper = backend.findHelper("throwExpression");
2123 registry.registerStaticUse(helper); 2178 registry.registerStaticUse(helper);
2124 2179
2125 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper); 2180 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper);
2126 js.Call value = new js.Call(jsHelper, [pop()]); 2181 js.Call value = new js.Call(jsHelper, [pop()])
2127 value = attachLocation(value, argument); 2182 .withSourceInformation(node.sourceInformation);
2128 push(value, node); 2183 push(value);
2129 } 2184 }
2130 2185
2131 void visitSwitch(HSwitch node) { 2186 void visitSwitch(HSwitch node) {
2132 // Switches are handled using [visitSwitchInfo]. 2187 // Switches are handled using [visitSwitchInfo].
2133 } 2188 }
2134 2189
2135 void visitStatic(HStatic node) { 2190 void visitStatic(HStatic node) {
2136 Element element = node.element; 2191 Element element = node.element;
2137 assert(element.isFunction || element.isField); 2192 assert(element.isFunction || element.isField);
2138 if (element.isFunction) { 2193 if (element.isFunction) {
2139 push(backend.emitter.isolateStaticClosureAccess(element)); 2194 push(backend.emitter.isolateStaticClosureAccess(element)
2195 .withSourceInformation(node.sourceInformation));
2140 registry.registerGetOfStaticFunction(element); 2196 registry.registerGetOfStaticFunction(element);
2141 } else { 2197 } else {
2142 push(backend.emitter.staticFieldAccess(element)); 2198 push(backend.emitter.staticFieldAccess(element)
2199 .withSourceInformation(node.sourceInformation));
2143 } 2200 }
2144 registry.registerStaticUse(element); 2201 registry.registerStaticUse(element);
2145 } 2202 }
2146 2203
2147 void visitLazyStatic(HLazyStatic node) { 2204 void visitLazyStatic(HLazyStatic node) {
2148 Element element = node.element; 2205 Element element = node.element;
2149 registry.registerStaticUse(element); 2206 registry.registerStaticUse(element);
2150 js.Expression lazyGetter = 2207 js.Expression lazyGetter =
2151 backend.emitter.isolateLazyInitializerAccess(element); 2208 backend.emitter.isolateLazyInitializerAccess(element);
2152 js.Call call = new js.Call(lazyGetter, <js.Expression>[]); 2209 js.Call call = new js.Call(lazyGetter, <js.Expression>[],
2153 push(call, node); 2210 sourceInformation: node.sourceInformation);
2211 push(call);
2154 } 2212 }
2155 2213
2156 void visitStaticStore(HStaticStore node) { 2214 void visitStaticStore(HStaticStore node) {
2157 registry.registerStaticUse(node.element); 2215 registry.registerStaticUse(node.element);
2158 js.Node variable = backend.emitter.staticFieldAccess(node.element); 2216 js.Node variable = backend.emitter.staticFieldAccess(node.element);
2159 use(node.inputs[0]); 2217 use(node.inputs[0]);
2160 push(new js.Assignment(variable, pop()), node); 2218 push(new js.Assignment(variable, pop())
2219 .withSourceInformation(node.sourceInformation));
2161 } 2220 }
2162 2221
2163 void visitStringConcat(HStringConcat node) { 2222 void visitStringConcat(HStringConcat node) {
2164 use(node.left); 2223 use(node.left);
2165 js.Expression jsLeft = pop(); 2224 js.Expression jsLeft = pop();
2166 use(node.right); 2225 use(node.right);
2167 push(new js.Binary('+', jsLeft, pop()), node); 2226 push(new js.Binary('+', jsLeft, pop())
2227 .withSourceInformation(node.sourceInformation));
2168 } 2228 }
2169 2229
2170 void visitStringify(HStringify node) { 2230 void visitStringify(HStringify node) {
2171 HInstruction input = node.inputs.first; 2231 HInstruction input = node.inputs.first;
2172 if (input.isString(compiler)) { 2232 if (input.isString(compiler)) {
2173 use(input); 2233 use(input);
2174 } else if (input.isInteger(compiler) || input.isBoolean(compiler)) { 2234 } else if (input.isInteger(compiler) || input.isBoolean(compiler)) {
2175 // JavaScript's + operator with a string for the left operand will convert 2235 // JavaScript's + operator with a string for the left operand will convert
2176 // the right operand to a string, and the conversion result is correct. 2236 // the right operand to a string, and the conversion result is correct.
2177 use(input); 2237 use(input);
2178 if (node.usedBy.length == 1 2238 if (node.usedBy.length == 1
2179 && node.usedBy[0] is HStringConcat 2239 && node.usedBy[0] is HStringConcat
2180 && node.usedBy[0].inputs[1] == node) { 2240 && node.usedBy[0].inputs[1] == node) {
2181 // The context is already <string> + value. 2241 // The context is already <string> + value.
2182 } else { 2242 } else {
2183 // Force an empty string for the first operand. 2243 // Force an empty string for the first operand.
2184 push(new js.Binary('+', js.string(""), pop()), node); 2244 push(new js.Binary('+', js.string(""), pop())
2245 .withSourceInformation(node.sourceInformation));
2185 } 2246 }
2186 } else { 2247 } else {
2187 Element convertToString = backend.getStringInterpolationHelper(); 2248 Element convertToString = backend.getStringInterpolationHelper();
2188 registry.registerStaticUse(convertToString); 2249 registry.registerStaticUse(convertToString);
2189 js.Expression jsHelper = 2250 js.Expression jsHelper =
2190 backend.emitter.staticFunctionAccess(convertToString); 2251 backend.emitter.staticFunctionAccess(convertToString);
2191 use(input); 2252 use(input);
2192 push(new js.Call(jsHelper, <js.Expression>[pop()]), node); 2253 push(new js.Call(jsHelper, <js.Expression>[pop()],
2254 sourceInformation: node.sourceInformation));
2193 } 2255 }
2194 } 2256 }
2195 2257
2196 void visitLiteralList(HLiteralList node) { 2258 void visitLiteralList(HLiteralList node) {
2197 registry.registerInstantiatedClass(compiler.listClass); 2259 registry.registerInstantiatedClass(compiler.listClass);
2198 generateArrayLiteral(node); 2260 generateArrayLiteral(node);
2199 } 2261 }
2200 2262
2201 void generateArrayLiteral(HLiteralList node) { 2263 void generateArrayLiteral(HLiteralList node) {
2202 List<js.Expression> elements = node.inputs.map((HInstruction input) { 2264 List<js.Expression> elements = node.inputs.map((HInstruction input) {
2203 use(input); 2265 use(input);
2204 return pop(); 2266 return pop();
2205 }).toList(); 2267 }).toList();
2206 push(new js.ArrayInitializer(elements), node); 2268 push(new js.ArrayInitializer(elements)
2269 .withSourceInformation(node.sourceInformation));
2207 } 2270 }
2208 2271
2209 void visitIndex(HIndex node) { 2272 void visitIndex(HIndex node) {
2210 use(node.receiver); 2273 use(node.receiver);
2211 js.Expression receiver = pop(); 2274 js.Expression receiver = pop();
2212 use(node.index); 2275 use(node.index);
2213 push(new js.PropertyAccess(receiver, pop()), node); 2276 push(new js.PropertyAccess(receiver, pop())
2277 .withSourceInformation(node.sourceInformation));
2214 } 2278 }
2215 2279
2216 void visitIndexAssign(HIndexAssign node) { 2280 void visitIndexAssign(HIndexAssign node) {
2217 use(node.receiver); 2281 use(node.receiver);
2218 js.Expression receiver = pop(); 2282 js.Expression receiver = pop();
2219 use(node.index); 2283 use(node.index);
2220 js.Expression index = pop(); 2284 js.Expression index = pop();
2221 use(node.value); 2285 use(node.value);
2222 push(new js.Assignment(new js.PropertyAccess(receiver, index), pop()), 2286 push(new js.Assignment(new js.PropertyAccess(receiver, index), pop())
2223 node); 2287 .withSourceInformation(node.sourceInformation));
2224 } 2288 }
2225 2289
2226 void checkInt(HInstruction input, String cmp) { 2290 void checkInt(HInstruction input, String cmp) {
2227 use(input); 2291 use(input);
2228 js.Expression left = pop(); 2292 js.Expression left = pop();
2229 use(input); 2293 use(input);
2230 js.Expression or0 = new js.Binary("|", pop(), new js.LiteralNumber("0")); 2294 js.Expression or0 = new js.Binary("|", pop(), new js.LiteralNumber("0"));
2231 push(new js.Binary(cmp, left, or0)); 2295 push(new js.Binary(cmp, left, or0));
2232 } 2296 }
2233 2297
2234 void checkBigInt(HInstruction input, String cmp) { 2298 void checkBigInt(HInstruction input, String cmp,
2299 SourceInformation sourceInformation) {
2235 use(input); 2300 use(input);
2236 js.Expression left = pop(); 2301 js.Expression left = pop();
2237 use(input); 2302 use(input);
2238 js.Expression right = pop(); 2303 js.Expression right = pop();
2239 // TODO(4984): Deal with infinity and -0.0. 2304 // TODO(4984): Deal with infinity and -0.0.
2240 push(js.js('Math.floor(#) $cmp #', <js.Expression>[left, right])); 2305 push(js.js('Math.floor(#) $cmp #', <js.Expression>[left, right])
2306 .withSourceInformation(sourceInformation));
2241 } 2307 }
2242 2308
2243 void checkTypeOf(HInstruction input, String cmp, String typeName) { 2309 void checkTypeOf(HInstruction input, String cmp, String typeName,
2310 SourceInformation sourceInformation) {
2244 use(input); 2311 use(input);
2245 js.Expression typeOf = new js.Prefix("typeof", pop()); 2312 js.Expression typeOf = new js.Prefix("typeof", pop());
2246 push(new js.Binary(cmp, typeOf, js.string(typeName))); 2313 push(new js.Binary(cmp, typeOf, js.string(typeName)));
2247 } 2314 }
2248 2315
2249 void checkNum(HInstruction input, String cmp) 2316 void checkNum(HInstruction input, String cmp,
2250 => checkTypeOf(input, cmp, 'number'); 2317 SourceInformation sourceInformation) {
2318 return checkTypeOf(input, cmp, 'number', sourceInformation);
2319 }
2251 2320
2252 void checkDouble(HInstruction input, String cmp) => checkNum(input, cmp); 2321 void checkDouble(HInstruction input, String cmp,
2322 SourceInformation sourceInformation) {
2323 return checkNum(input, cmp, sourceInformation);
2324 }
2253 2325
2254 void checkString(HInstruction input, String cmp) 2326 void checkString(HInstruction input, String cmp,
2255 => checkTypeOf(input, cmp, 'string'); 2327 SourceInformation sourceInformation) {
2328 return checkTypeOf(input, cmp, 'string', sourceInformation);
2329 }
2256 2330
2257 void checkBool(HInstruction input, String cmp) 2331 void checkBool(HInstruction input, String cmp,
2258 => checkTypeOf(input, cmp, 'boolean'); 2332 SourceInformation sourceInformation) {
2333 return checkTypeOf(input, cmp, 'boolean', sourceInformation);
2334 }
2259 2335
2260 void checkObject(HInstruction input, String cmp) { 2336 void checkObject(HInstruction input, String cmp,
2337 SourceInformation sourceInformation) {
2261 assert(NullConstantValue.JsNull == 'null'); 2338 assert(NullConstantValue.JsNull == 'null');
2262 if (cmp == "===") { 2339 if (cmp == "===") {
2263 checkTypeOf(input, '===', 'object'); 2340 checkTypeOf(input, '===', 'object', sourceInformation);
2264 js.Expression left = pop(); 2341 js.Expression left = pop();
2265 use(input); 2342 use(input);
2266 js.Expression notNull = new js.Binary("!==", pop(), new js.LiteralNull()); 2343 js.Expression notNull = new js.Binary("!==", pop(), new js.LiteralNull());
2267 push(new js.Binary("&&", left, notNull)); 2344 push(new js.Binary("&&", left, notNull)
2345 .withSourceInformation(sourceInformation));
2268 } else { 2346 } else {
2269 assert(cmp == "!=="); 2347 assert(cmp == "!==");
2270 checkTypeOf(input, '!==', 'object'); 2348 checkTypeOf(input, '!==', 'object', sourceInformation);
2271 js.Expression left = pop(); 2349 js.Expression left = pop();
2272 use(input); 2350 use(input);
2273 js.Expression eqNull = new js.Binary("===", pop(), new js.LiteralNull()); 2351 js.Expression eqNull = new js.Binary("===", pop(), new js.LiteralNull());
2274 push(new js.Binary("||", left, eqNull)); 2352 push(new js.Binary("||", left, eqNull)
2353 .withSourceInformation(sourceInformation));
2275 } 2354 }
2276 } 2355 }
2277 2356
2278 void checkArray(HInstruction input, String cmp) { 2357 void checkArray(HInstruction input, String cmp) {
2279 use(input); 2358 use(input);
2280 js.PropertyAccess constructor = 2359 js.PropertyAccess constructor =
2281 new js.PropertyAccess.field(pop(), 'constructor'); 2360 new js.PropertyAccess.field(pop(), 'constructor');
2282 push(new js.Binary(cmp, constructor, new js.VariableUse('Array'))); 2361 push(new js.Binary(cmp, constructor, new js.VariableUse('Array')));
2283 } 2362 }
2284 2363
(...skipping 30 matching lines...) Expand all
2315 use(input); 2394 use(input);
2316 push(new js.Binary('==', pop(), new js.LiteralNull())); 2395 push(new js.Binary('==', pop(), new js.LiteralNull()));
2317 } 2396 }
2318 2397
2319 void checkNonNull(HInstruction input) { 2398 void checkNonNull(HInstruction input) {
2320 use(input); 2399 use(input);
2321 push(new js.Binary('!=', pop(), new js.LiteralNull())); 2400 push(new js.Binary('!=', pop(), new js.LiteralNull()));
2322 } 2401 }
2323 2402
2324 void checkType(HInstruction input, HInstruction interceptor, 2403 void checkType(HInstruction input, HInstruction interceptor,
2325 DartType type, {bool negative: false}) { 2404 DartType type,
2405 SourceInformation sourceInformation,
2406 {bool negative: false}) {
2326 Element element = type.element; 2407 Element element = type.element;
2327 if (element == backend.jsArrayClass) { 2408 if (element == backend.jsArrayClass) {
2328 checkArray(input, negative ? '!==': '==='); 2409 checkArray(input, negative ? '!==': '===');
2329 return; 2410 return;
2330 } else if (element == backend.jsMutableArrayClass) { 2411 } else if (element == backend.jsMutableArrayClass) {
2331 if (negative) { 2412 if (negative) {
2332 checkImmutableArray(input); 2413 checkImmutableArray(input);
2333 } else { 2414 } else {
2334 checkMutableArray(input); 2415 checkMutableArray(input);
2335 } 2416 }
(...skipping 14 matching lines...) Expand all
2350 return; 2431 return;
2351 } else if (element == backend.jsUnmodifiableArrayClass) { 2432 } else if (element == backend.jsUnmodifiableArrayClass) {
2352 if (negative) { 2433 if (negative) {
2353 checkMutableArray(input); 2434 checkMutableArray(input);
2354 } else { 2435 } else {
2355 checkImmutableArray(input); 2436 checkImmutableArray(input);
2356 } 2437 }
2357 return; 2438 return;
2358 } 2439 }
2359 if (interceptor != null) { 2440 if (interceptor != null) {
2360 checkTypeViaProperty(interceptor, type, negative); 2441 checkTypeViaProperty(interceptor, type, sourceInformation,
2442 negative: negative);
2361 } else { 2443 } else {
2362 checkTypeViaProperty(input, type, negative); 2444 checkTypeViaProperty(input, type, sourceInformation, negative: negative);
2363 } 2445 }
2364 } 2446 }
2365 2447
2366 void checkTypeViaProperty(HInstruction input, DartType type, bool negative) { 2448 void checkTypeViaProperty(HInstruction input, DartType type,
2449 SourceInformation sourceInformation,
2450 {bool negative: false}) {
2367 registry.registerIsCheck(type); 2451 registry.registerIsCheck(type);
2368 2452
2369 use(input); 2453 use(input);
2370 2454
2371 js.PropertyAccess field = 2455 js.PropertyAccess field =
2372 new js.PropertyAccess(pop(), backend.namer.operatorIsType(type)); 2456 new js.PropertyAccess(pop(), backend.namer.operatorIsType(type))
2457 .withSourceInformation(sourceInformation);
2373 // We always negate at least once so that the result is boolified. 2458 // We always negate at least once so that the result is boolified.
2374 push(new js.Prefix('!', field)); 2459 push(new js.Prefix('!', field)
2460 .withSourceInformation(sourceInformation));
2375 // If the result is not negated, put another '!' in front. 2461 // If the result is not negated, put another '!' in front.
2376 if (!negative) push(new js.Prefix('!', pop())); 2462 if (!negative) {
2463 push(new js.Prefix('!', pop())
2464 .withSourceInformation(sourceInformation));
2465 }
2377 } 2466 }
2378 2467
2379 void checkTypeViaInstanceof( 2468 void checkTypeViaInstanceof(
2380 HInstruction input, DartType type, bool negative) { 2469 HInstruction input, DartType type,
2470 SourceInformation sourceInformation,
2471 {bool negative: false}) {
2381 registry.registerIsCheck(type); 2472 registry.registerIsCheck(type);
2382 2473
2383 use(input); 2474 use(input);
2384 2475
2385 js.Expression jsClassReference = 2476 js.Expression jsClassReference =
2386 backend.emitter.constructorAccess(type.element); 2477 backend.emitter.constructorAccess(type.element);
2387 push(js.js('# instanceof #', [pop(), jsClassReference])); 2478 push(js.js('# instanceof #', [pop(), jsClassReference])
2388 if (negative) push(new js.Prefix('!', pop())); 2479 .withSourceInformation(sourceInformation));
2480 if (negative) {
2481 push(new js.Prefix('!', pop())
2482 .withSourceInformation(sourceInformation));
2483 }
2389 registry.registerInstantiatedType(type); 2484 registry.registerInstantiatedType(type);
2390 } 2485 }
2391 2486
2392 void handleNumberOrStringSupertypeCheck(HInstruction input, 2487 void handleNumberOrStringSupertypeCheck(HInstruction input,
2393 HInstruction interceptor, 2488 HInstruction interceptor,
2394 DartType type, 2489 DartType type,
2395 { bool negative: false }) { 2490 SourceInformation sourceInformation,
2396 assert(!identical(type.element, compiler.listClass) 2491 {bool negative: false}) {
2397 && !Elements.isListSupertype(type.element, compiler) 2492 assert(!identical(type.element, compiler.listClass) &&
2398 && !Elements.isStringOnlySupertype(type.element, compiler)); 2493 !Elements.isListSupertype(type.element, compiler) &&
2494 !Elements.isStringOnlySupertype(type.element, compiler));
2399 String relation = negative ? '!==' : '==='; 2495 String relation = negative ? '!==' : '===';
2400 checkNum(input, relation); 2496 checkNum(input, relation, sourceInformation);
2401 js.Expression numberTest = pop(); 2497 js.Expression numberTest = pop();
2402 checkString(input, relation); 2498 checkString(input, relation, sourceInformation);
2403 js.Expression stringTest = pop(); 2499 js.Expression stringTest = pop();
2404 checkObject(input, relation); 2500 checkObject(input, relation, sourceInformation);
2405 js.Expression objectTest = pop(); 2501 js.Expression objectTest = pop();
2406 checkType(input, interceptor, type, negative: negative); 2502 checkType(input, interceptor, type, sourceInformation, negative: negative);
2407 String combiner = negative ? '&&' : '||'; 2503 String combiner = negative ? '&&' : '||';
2408 String combiner2 = negative ? '||' : '&&'; 2504 String combiner2 = negative ? '||' : '&&';
2409 push(new js.Binary(combiner, 2505 push(new js.Binary(combiner,
2410 new js.Binary(combiner, numberTest, stringTest), 2506 new js.Binary(combiner, numberTest, stringTest)
2411 new js.Binary(combiner2, objectTest, pop()))); 2507 .withSourceInformation(sourceInformation),
2508 new js.Binary(combiner2, objectTest, pop())
2509 .withSourceInformation(sourceInformation))
2510 .withSourceInformation(sourceInformation));
2412 } 2511 }
2413 2512
2414 void handleStringSupertypeCheck(HInstruction input, 2513 void handleStringSupertypeCheck(HInstruction input,
2415 HInstruction interceptor, 2514 HInstruction interceptor,
2416 DartType type, 2515 DartType type,
2417 { bool negative: false }) { 2516 SourceInformation sourceInformation,
2517 {bool negative: false}) {
2418 assert(!identical(type.element, compiler.listClass) 2518 assert(!identical(type.element, compiler.listClass)
2419 && !Elements.isListSupertype(type.element, compiler) 2519 && !Elements.isListSupertype(type.element, compiler)
2420 && !Elements.isNumberOrStringSupertype(type.element, compiler)); 2520 && !Elements.isNumberOrStringSupertype(type.element, compiler));
2421 String relation = negative ? '!==' : '==='; 2521 String relation = negative ? '!==' : '===';
2422 checkString(input, relation); 2522 checkString(input, relation, sourceInformation);
2423 js.Expression stringTest = pop(); 2523 js.Expression stringTest = pop();
2424 checkObject(input, relation); 2524 checkObject(input, relation, sourceInformation);
2425 js.Expression objectTest = pop(); 2525 js.Expression objectTest = pop();
2426 checkType(input, interceptor, type, negative: negative); 2526 checkType(input, interceptor, type, sourceInformation, negative: negative);
2427 String combiner = negative ? '||' : '&&'; 2527 String combiner = negative ? '||' : '&&';
2428 push(new js.Binary(negative ? '&&' : '||', 2528 push(new js.Binary(negative ? '&&' : '||',
2429 stringTest, 2529 stringTest,
2430 new js.Binary(combiner, objectTest, pop()))); 2530 new js.Binary(combiner, objectTest, pop())));
2431 } 2531 }
2432 2532
2433 void handleListOrSupertypeCheck(HInstruction input, 2533 void handleListOrSupertypeCheck(HInstruction input,
2434 HInstruction interceptor, 2534 HInstruction interceptor,
2435 DartType type, 2535 DartType type,
2536 SourceInformation sourceInformation,
2436 { bool negative: false }) { 2537 { bool negative: false }) {
2437 assert(!identical(type.element, compiler.stringClass) 2538 assert(!identical(type.element, compiler.stringClass)
2438 && !Elements.isStringOnlySupertype(type.element, compiler) 2539 && !Elements.isStringOnlySupertype(type.element, compiler)
2439 && !Elements.isNumberOrStringSupertype(type.element, compiler)); 2540 && !Elements.isNumberOrStringSupertype(type.element, compiler));
2440 String relation = negative ? '!==' : '==='; 2541 String relation = negative ? '!==' : '===';
2441 checkObject(input, relation); 2542 checkObject(input, relation, sourceInformation);
2442 js.Expression objectTest = pop(); 2543 js.Expression objectTest = pop();
2443 checkArray(input, relation); 2544 checkArray(input, relation);
2444 js.Expression arrayTest = pop(); 2545 js.Expression arrayTest = pop();
2445 checkType(input, interceptor, type, negative: negative); 2546 checkType(input, interceptor, type, sourceInformation, negative: negative);
2446 String combiner = negative ? '&&' : '||'; 2547 String combiner = negative ? '&&' : '||';
2447 push(new js.Binary(negative ? '||' : '&&', 2548 push(new js.Binary(negative ? '||' : '&&',
2448 objectTest, 2549 objectTest,
2449 new js.Binary(combiner, arrayTest, pop()))); 2550 new js.Binary(combiner, arrayTest, pop()))
2551 .withSourceInformation(sourceInformation));
2450 } 2552 }
2451 2553
2452 void visitIs(HIs node) { 2554 void visitIs(HIs node) {
2453 emitIs(node, "==="); 2555 emitIs(node, "===", node.sourceInformation);
2454 } 2556 }
2455 2557
2456 void visitIsViaInterceptor(HIsViaInterceptor node) { 2558 void visitIsViaInterceptor(HIsViaInterceptor node) {
2457 emitIsViaInterceptor(node, false); 2559 emitIsViaInterceptor(node, node.sourceInformation, negative: false);
2458 } 2560 }
2459 2561
2460 void emitIs(HIs node, String relation) { 2562 void emitIs(HIs node, String relation, SourceInformation sourceInformation) {
2461 DartType type = node.typeExpression; 2563 DartType type = node.typeExpression;
2462 registry.registerIsCheck(type); 2564 registry.registerIsCheck(type);
2463 HInstruction input = node.expression; 2565 HInstruction input = node.expression;
2464 2566
2465 // If this is changed to single == there are several places below that must 2567 // If this is changed to single == there are several places below that must
2466 // be changed to match. 2568 // be changed to match.
2467 assert(relation == '===' || relation == '!=='); 2569 assert(relation == '===' || relation == '!==');
2468 bool negative = relation == '!=='; 2570 bool negative = relation == '!==';
2469 2571
2470 if (node.isVariableCheck || node.isCompoundCheck) { 2572 if (node.isVariableCheck || node.isCompoundCheck) {
2471 use(node.checkCall); 2573 use(node.checkCall);
2472 if (negative) push(new js.Prefix('!', pop())); 2574 if (negative) push(new js.Prefix('!', pop()));
2473 } else { 2575 } else {
2474 assert(node.isRawCheck); 2576 assert(node.isRawCheck);
2475 HInstruction interceptor = node.interceptor; 2577 HInstruction interceptor = node.interceptor;
2476 ClassElement objectClass = compiler.objectClass; 2578 ClassElement objectClass = compiler.objectClass;
2477 Element element = type.element; 2579 Element element = type.element;
2478 if (element == compiler.nullClass) { 2580 if (element == compiler.nullClass) {
2479 if (negative) { 2581 if (negative) {
2480 checkNonNull(input); 2582 checkNonNull(input);
2481 } else { 2583 } else {
2482 checkNull(input); 2584 checkNull(input);
2483 } 2585 }
2484 } else if (identical(element, objectClass) || type.treatAsDynamic) { 2586 } else if (identical(element, objectClass) || type.treatAsDynamic) {
2485 // The constant folder also does this optimization, but we make 2587 // The constant folder also does this optimization, but we make
2486 // it safe by assuming it may have not run. 2588 // it safe by assuming it may have not run.
2487 push(newLiteralBool(!negative), node); 2589 push(newLiteralBool(!negative, sourceInformation));
2488 } else if (element == compiler.stringClass) { 2590 } else if (element == compiler.stringClass) {
2489 checkString(input, relation); 2591 checkString(input, relation, sourceInformation);
2490 attachLocationToLast(node);
2491 } else if (element == compiler.doubleClass) { 2592 } else if (element == compiler.doubleClass) {
2492 checkDouble(input, relation); 2593 checkDouble(input, relation, sourceInformation);
2493 attachLocationToLast(node);
2494 } else if (element == compiler.numClass) { 2594 } else if (element == compiler.numClass) {
2495 checkNum(input, relation); 2595 checkNum(input, relation, sourceInformation);
2496 attachLocationToLast(node);
2497 } else if (element == compiler.boolClass) { 2596 } else if (element == compiler.boolClass) {
2498 checkBool(input, relation); 2597 checkBool(input, relation, sourceInformation);
2499 attachLocationToLast(node);
2500 } else if (element == compiler.intClass) { 2598 } else if (element == compiler.intClass) {
2501 // The is check in the code tells us that it might not be an 2599 // The is check in the code tells us that it might not be an
2502 // int. So we do a typeof first to avoid possible 2600 // int. So we do a typeof first to avoid possible
2503 // deoptimizations on the JS engine due to the Math.floor check. 2601 // deoptimizations on the JS engine due to the Math.floor check.
2504 checkNum(input, relation); 2602 checkNum(input, relation, sourceInformation);
2505 js.Expression numTest = pop(); 2603 js.Expression numTest = pop();
2506 checkBigInt(input, relation); 2604 checkBigInt(input, relation, sourceInformation);
2507 push(new js.Binary(negative ? '||' : '&&', numTest, pop()), node); 2605 push(new js.Binary(negative ? '||' : '&&', numTest, pop())
2606 .withSourceInformation(sourceInformation));
2508 } else if (node.useInstanceOf) { 2607 } else if (node.useInstanceOf) {
2509 assert(interceptor == null); 2608 assert(interceptor == null);
2510 checkTypeViaInstanceof(input, type, negative); 2609 checkTypeViaInstanceof(input, type,
2511 attachLocationToLast(node); 2610 sourceInformation,
2611 negative: negative);
2512 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { 2612 } else if (Elements.isNumberOrStringSupertype(element, compiler)) {
2513 handleNumberOrStringSupertypeCheck( 2613 handleNumberOrStringSupertypeCheck(
2514 input, interceptor, type, negative: negative); 2614 input, interceptor, type,
2515 attachLocationToLast(node); 2615 sourceInformation,
2616 negative: negative);
2516 } else if (Elements.isStringOnlySupertype(element, compiler)) { 2617 } else if (Elements.isStringOnlySupertype(element, compiler)) {
2517 handleStringSupertypeCheck( 2618 handleStringSupertypeCheck(
2518 input, interceptor, type, negative: negative); 2619 input, interceptor, type,
2519 attachLocationToLast(node); 2620 sourceInformation,
2520 } else if (identical(element, compiler.listClass) 2621 negative: negative);
2521 || Elements.isListSupertype(element, compiler)) { 2622 } else if (identical(element, compiler.listClass) ||
2623 Elements.isListSupertype(element, compiler)) {
2522 handleListOrSupertypeCheck( 2624 handleListOrSupertypeCheck(
2523 input, interceptor, type, negative: negative); 2625 input, interceptor, type,
2524 attachLocationToLast(node); 2626 sourceInformation,
2627 negative: negative);
2525 } else if (type.isFunctionType) { 2628 } else if (type.isFunctionType) {
2526 checkType(input, interceptor, type, negative: negative); 2629 checkType(input, interceptor, type,
2527 attachLocationToLast(node); 2630 sourceInformation,
2631 negative: negative);
2528 } else if ((input.canBePrimitive(compiler) 2632 } else if ((input.canBePrimitive(compiler)
2529 && !input.canBePrimitiveArray(compiler)) 2633 && !input.canBePrimitiveArray(compiler))
2530 || input.canBeNull()) { 2634 || input.canBeNull()) {
2531 checkObject(input, relation); 2635 checkObject(input, relation, node.sourceInformation);
2532 js.Expression objectTest = pop(); 2636 js.Expression objectTest = pop();
2533 checkType(input, interceptor, type, negative: negative); 2637 checkType(input, interceptor, type,
2534 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()), node); 2638 sourceInformation,
2639 negative: negative);
2640 push(new js.Binary(negative ? '||' : '&&', objectTest, pop())
2641 .withSourceInformation(sourceInformation));
2535 } else { 2642 } else {
2536 checkType(input, interceptor, type, negative: negative); 2643 checkType(input, interceptor, type,
2537 attachLocationToLast(node); 2644 sourceInformation,
2645 negative: negative);
2538 } 2646 }
2539 } 2647 }
2540 } 2648 }
2541 2649
2542 void emitIsViaInterceptor(HIsViaInterceptor node, bool negative) { 2650 void emitIsViaInterceptor(HIsViaInterceptor node,
2543 checkTypeViaProperty(node.interceptor, node.typeExpression, negative); 2651 SourceInformation sourceInformation,
2544 attachLocationToLast(node); 2652 {bool negative: false}) {
2653 checkTypeViaProperty(node.interceptor, node.typeExpression,
2654 sourceInformation,
2655 negative: negative);
2545 } 2656 }
2546 2657
2547 js.Expression generateReceiverOrArgumentTypeTest( 2658 js.Expression generateReceiverOrArgumentTypeTest(
2548 HInstruction input, TypeMask checkedType) { 2659 HInstruction input, TypeMask checkedType) {
2549 ClassWorld classWorld = compiler.world; 2660 ClassWorld classWorld = compiler.world;
2550 TypeMask inputType = input.instructionType; 2661 TypeMask inputType = input.instructionType;
2551 // Figure out if it is beneficial to turn this into a null check. 2662 // Figure out if it is beneficial to turn this into a null check.
2552 // V8 generally prefers 'typeof' checks, but for integers and 2663 // V8 generally prefers 'typeof' checks, but for integers and
2553 // indexable primitives we cannot compile this test into a single 2664 // indexable primitives we cannot compile this test into a single
2554 // typeof check so the null check is cheaper. 2665 // typeof check so the null check is cheaper.
2555 bool isIntCheck = checkedType.containsOnlyInt(classWorld); 2666 bool isIntCheck = checkedType.containsOnlyInt(classWorld);
2556 bool turnIntoNumCheck = isIntCheck && input.isIntegerOrNull(compiler); 2667 bool turnIntoNumCheck = isIntCheck && input.isIntegerOrNull(compiler);
2557 bool turnIntoNullCheck = !turnIntoNumCheck 2668 bool turnIntoNullCheck = !turnIntoNumCheck
2558 && (checkedType.nullable() == inputType) 2669 && (checkedType.nullable() == inputType)
2559 && (isIntCheck 2670 && (isIntCheck
2560 || checkedType.satisfies(backend.jsIndexableClass, classWorld)); 2671 || checkedType.satisfies(backend.jsIndexableClass, classWorld));
2561 2672
2562 if (turnIntoNullCheck) { 2673 if (turnIntoNullCheck) {
2563 use(input); 2674 use(input);
2564 return new js.Binary("==", pop(), new js.LiteralNull()); 2675 return new js.Binary("==", pop(), new js.LiteralNull())
2676 .withSourceInformation(input.sourceInformation);
2565 } else if (isIntCheck && !turnIntoNumCheck) { 2677 } else if (isIntCheck && !turnIntoNumCheck) {
2566 // input is !int 2678 // input is !int
2567 checkBigInt(input, '!=='); 2679 checkBigInt(input, '!==', input.sourceInformation);
2568 return pop(); 2680 return pop();
2569 } else if (turnIntoNumCheck || checkedType.containsOnlyNum(classWorld)) { 2681 } else if (turnIntoNumCheck || checkedType.containsOnlyNum(classWorld)) {
2570 // input is !num 2682 // input is !num
2571 checkNum(input, '!=='); 2683 checkNum(input, '!==', input.sourceInformation);
2572 return pop(); 2684 return pop();
2573 } else if (checkedType.containsOnlyBool(classWorld)) { 2685 } else if (checkedType.containsOnlyBool(classWorld)) {
2574 // input is !bool 2686 // input is !bool
2575 checkBool(input, '!=='); 2687 checkBool(input, '!==', input.sourceInformation);
2576 return pop(); 2688 return pop();
2577 } else if (checkedType.containsOnlyString(classWorld)) { 2689 } else if (checkedType.containsOnlyString(classWorld)) {
2578 // input is !string 2690 // input is !string
2579 checkString(input, '!=='); 2691 checkString(input, '!==', input.sourceInformation);
2580 return pop(); 2692 return pop();
2581 } 2693 }
2582 compiler.internalError(input, 'Unexpected check.'); 2694 compiler.internalError(input, 'Unexpected check.');
2583 return null; 2695 return null;
2584 } 2696 }
2585 2697
2586 void visitTypeConversion(HTypeConversion node) { 2698 void visitTypeConversion(HTypeConversion node) {
2587 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) { 2699 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
2588 ClassWorld classWorld = compiler.world; 2700 ClassWorld classWorld = compiler.world;
2589 // An int check if the input is not int or null, is not 2701 // An int check if the input is not int or null, is not
(...skipping 10 matching lines...) Expand all
2600 generateThrowWithHelper('iae', node.checkedInput); 2712 generateThrowWithHelper('iae', node.checkedInput);
2601 } else if (node.isReceiverTypeCheck) { 2713 } else if (node.isReceiverTypeCheck) {
2602 use(node.checkedInput); 2714 use(node.checkedInput);
2603 js.Name methodName = 2715 js.Name methodName =
2604 backend.namer.invocationName(node.receiverTypeCheckSelector); 2716 backend.namer.invocationName(node.receiverTypeCheckSelector);
2605 js.Expression call = js.propertyCall(pop(), methodName, []); 2717 js.Expression call = js.propertyCall(pop(), methodName, []);
2606 pushStatement(new js.Return(call)); 2718 pushStatement(new js.Return(call));
2607 } 2719 }
2608 currentContainer = oldContainer; 2720 currentContainer = oldContainer;
2609 body = unwrapStatement(body); 2721 body = unwrapStatement(body);
2610 pushStatement(new js.If.noElse(test, body), node); 2722 pushStatement(new js.If.noElse(test, body)
2723 .withSourceInformation(node.sourceInformation));
2611 return; 2724 return;
2612 } 2725 }
2613 2726
2614 assert(node.isCheckedModeCheck || node.isCastTypeCheck); 2727 assert(node.isCheckedModeCheck || node.isCastTypeCheck);
2615 DartType type = node.typeExpression; 2728 DartType type = node.typeExpression;
2616 assert(type.kind != TypeKind.TYPEDEF); 2729 assert(type.kind != TypeKind.TYPEDEF);
2617 if (type.isFunctionType) { 2730 if (type.isFunctionType) {
2618 // TODO(5022): We currently generate $isFunction checks for 2731 // TODO(5022): We currently generate $isFunction checks for
2619 // function types. 2732 // function types.
2620 registry.registerIsCheck(compiler.functionClass.rawType); 2733 registry.registerIsCheck(compiler.functionClass.rawType);
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
2740 js.PropertyAccess accessHelper(String name) { 2853 js.PropertyAccess accessHelper(String name) {
2741 Element helper = backend.findHelper(name); 2854 Element helper = backend.findHelper(name);
2742 if (helper == null) { 2855 if (helper == null) {
2743 // For mocked-up tests. 2856 // For mocked-up tests.
2744 return js.js('(void 0).$name'); 2857 return js.js('(void 0).$name');
2745 } 2858 }
2746 registry.registerStaticUse(helper); 2859 registry.registerStaticUse(helper);
2747 return backend.emitter.staticFunctionAccess(helper); 2860 return backend.emitter.staticFunctionAccess(helper);
2748 } 2861 }
2749 } 2862 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder.dart ('k') | pkg/compiler/lib/src/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698