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

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: Update comments. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of ssa; 5 part of ssa;
6 6
7 class 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 String name = 1513 String 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 14 matching lines...) Expand all
1527 // optimization. The optimization ensures any type checks or 1545 // optimization. The optimization ensures any type checks or
1528 // conversions have been satisified. 1546 // conversions have been satisified.
1529 methodName = target.fixedBackendName; 1547 methodName = target.fixedBackendName;
1530 } 1548 }
1531 } 1549 }
1532 1550
1533 if (methodName == null) { 1551 if (methodName == null) {
1534 methodName = backend.namer.invocationName(node.selector); 1552 methodName = backend.namer.invocationName(node.selector);
1535 registerMethodInvoke(node); 1553 registerMethodInvoke(node);
1536 } 1554 }
1537 push(js.propertyCall(object, methodName, arguments), node); 1555 push(js.propertyCall(object, methodName, arguments)
1556 .withSourceInformation(node.sourceInformation));
1538 } 1557 }
1539 1558
1540 void visitInvokeConstructorBody(HInvokeConstructorBody node) { 1559 void visitInvokeConstructorBody(HInvokeConstructorBody node) {
1541 use(node.inputs[0]); 1560 use(node.inputs[0]);
1542 js.Expression object = pop(); 1561 js.Expression object = pop();
1543 String methodName = backend.namer.instanceMethodName(node.element); 1562 String methodName = backend.namer.instanceMethodName(node.element);
1544 List<js.Expression> arguments = visitArguments(node.inputs); 1563 List<js.Expression> arguments = visitArguments(node.inputs);
1545 push(js.propertyCall(object, methodName, arguments), node); 1564 push(js.propertyCall(object, methodName, arguments)
1565 .withSourceInformation(node.sourceInformation));
1546 registry.registerStaticUse(node.element); 1566 registry.registerStaticUse(node.element);
1547 } 1567 }
1548 1568
1549 void visitOneShotInterceptor(HOneShotInterceptor node) { 1569 void visitOneShotInterceptor(HOneShotInterceptor node) {
1550 List<js.Expression> arguments = visitArguments(node.inputs); 1570 List<js.Expression> arguments = visitArguments(node.inputs);
1551 var isolate = new js.VariableUse( 1571 var isolate = new js.VariableUse(
1552 backend.namer.globalObjectFor(backend.interceptorsLibrary)); 1572 backend.namer.globalObjectFor(backend.interceptorsLibrary));
1553 Selector selector = getOptimizedSelectorFor(node, node.selector); 1573 Selector selector = getOptimizedSelectorFor(node, node.selector);
1554 String methodName = backend.registerOneShotInterceptor(selector); 1574 String methodName = backend.registerOneShotInterceptor(selector);
1555 push(js.propertyCall(isolate, methodName, arguments), node); 1575 push(js.propertyCall(isolate, methodName, arguments)
1576 .withSourceInformation(node.sourceInformation));
1556 if (selector.isGetter) { 1577 if (selector.isGetter) {
1557 registerGetter(node); 1578 registerGetter(node);
1558 } else if (selector.isSetter) { 1579 } else if (selector.isSetter) {
1559 registerSetter(node); 1580 registerSetter(node);
1560 } else { 1581 } else {
1561 registerMethodInvoke(node); 1582 registerMethodInvoke(node);
1562 } 1583 }
1563 registry.registerUseInterceptor(); 1584 registry.registerUseInterceptor();
1564 } 1585 }
1565 1586
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 } 1623 }
1603 1624
1604 void registerGetter(HInvokeDynamic node) { 1625 void registerGetter(HInvokeDynamic node) {
1605 Selector selector = getOptimizedSelectorFor(node, node.selector); 1626 Selector selector = getOptimizedSelectorFor(node, node.selector);
1606 registry.registerDynamicGetter(selector); 1627 registry.registerDynamicGetter(selector);
1607 } 1628 }
1608 1629
1609 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { 1630 visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
1610 use(node.receiver); 1631 use(node.receiver);
1611 String name = backend.namer.invocationName(node.selector); 1632 String name = backend.namer.invocationName(node.selector);
1612 push(js.propertyCall(pop(), name, visitArguments(node.inputs)), node); 1633 push(js.propertyCall(pop(), name, visitArguments(node.inputs))
1634 .withSourceInformation(node.sourceInformation));
1613 registerSetter(node); 1635 registerSetter(node);
1614 } 1636 }
1615 1637
1616 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { 1638 visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
1617 use(node.receiver); 1639 use(node.receiver);
1618 String name = backend.namer.invocationName(node.selector); 1640 String name = backend.namer.invocationName(node.selector);
1619 push(js.propertyCall(pop(), name, visitArguments(node.inputs)), node); 1641 push(js.propertyCall(pop(), name, visitArguments(node.inputs))
1642 .withSourceInformation(node.sourceInformation));
1620 registerGetter(node); 1643 registerGetter(node);
1621 } 1644 }
1622 1645
1623 visitInvokeClosure(HInvokeClosure node) { 1646 visitInvokeClosure(HInvokeClosure node) {
1624 Selector call = new Selector.callClosureFrom(node.selector); 1647 Selector call = new Selector.callClosureFrom(node.selector);
1625 use(node.receiver); 1648 use(node.receiver);
1626 push(js.propertyCall(pop(), 1649 push(js.propertyCall(pop(),
1627 backend.namer.invocationName(call), 1650 backend.namer.invocationName(call),
1628 visitArguments(node.inputs)), 1651 visitArguments(node.inputs))
1629 node); 1652 .withSourceInformation(node.sourceInformation));
1630 registry.registerDynamicInvocation(call); 1653 registry.registerDynamicInvocation(call);
1631 } 1654 }
1632 1655
1633 visitInvokeStatic(HInvokeStatic node) { 1656 visitInvokeStatic(HInvokeStatic node) {
1634 Element element = node.element; 1657 Element element = node.element;
1635 List<DartType> instantiatedTypes = node.instantiatedTypes; 1658 List<DartType> instantiatedTypes = node.instantiatedTypes;
1636 1659
1637 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) { 1660 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) {
1638 instantiatedTypes.forEach((type) { 1661 instantiatedTypes.forEach((type) {
1639 registry.registerInstantiatedType(type); 1662 registry.registerInstantiatedType(type);
(...skipping 20 matching lines...) Expand all
1660 // more optimizations available to the loop. This form is 50% faster on 1683 // more optimizations available to the loop. This form is 50% faster on
1661 // some small loop, almost as fast as loops with no concurrent 1684 // some small loop, almost as fast as loops with no concurrent
1662 // modification check. 1685 // modification check.
1663 push(js.js('# || (0, #)(#)',[ 1686 push(js.js('# || (0, #)(#)',[
1664 arguments[0], 1687 arguments[0],
1665 backend.emitter.staticFunctionAccess(throwFunction), 1688 backend.emitter.staticFunctionAccess(throwFunction),
1666 arguments[1]])); 1689 arguments[1]]));
1667 } else { 1690 } else {
1668 registry.registerStaticInvocation(element); 1691 registry.registerStaticInvocation(element);
1669 push(backend.emitter.staticFunctionAccess(element)); 1692 push(backend.emitter.staticFunctionAccess(element));
1670 push(new js.Call(pop(), arguments), node); 1693 push(new js.Call(pop(), arguments,
1694 sourceInformation: node.sourceInformation));
1671 } 1695 }
1672 1696
1673 } 1697 }
1674 1698
1675 visitInvokeSuper(HInvokeSuper node) { 1699 visitInvokeSuper(HInvokeSuper node) {
1676 Element superMethod = node.element; 1700 Element superMethod = node.element;
1677 registry.registerSuperInvocation(superMethod); 1701 registry.registerSuperInvocation(superMethod);
1678 ClassElement superClass = superMethod.enclosingClass; 1702 ClassElement superClass = superMethod.enclosingClass;
1679 if (superMethod.kind == ElementKind.FIELD) { 1703 if (superMethod.kind == ElementKind.FIELD) {
1680 String fieldName = backend.namer.instanceFieldPropertyName(superMethod); 1704 String fieldName = backend.namer.instanceFieldPropertyName(superMethod);
1681 use(node.inputs[0]); 1705 use(node.inputs[0]);
1682 js.PropertyAccess access = 1706 js.PropertyAccess access =
1683 new js.PropertyAccess.field(pop(), fieldName); 1707 new js.PropertyAccess.field(pop(), fieldName)
1708 .withSourceInformation(node.sourceInformation);
1684 if (node.isSetter) { 1709 if (node.isSetter) {
1685 use(node.value); 1710 use(node.value);
1686 push(new js.Assignment(access, pop()), node); 1711 push(new js.Assignment(access, pop())
1712 .withSourceInformation(node.sourceInformation));
1687 } else { 1713 } else {
1688 push(access, node); 1714 push(access);
1689 } 1715 }
1690 } else { 1716 } else {
1691 Selector selector = node.selector; 1717 Selector selector = node.selector;
1692 1718
1693 if (!backend.maybeRegisterAliasedSuperMember(superMethod, selector)) { 1719 if (!backend.maybeRegisterAliasedSuperMember(superMethod, selector)) {
1694 String methodName; 1720 String methodName;
1695 if (selector.isGetter) { 1721 if (selector.isGetter) {
1696 // If the selector we need to register a typed getter to the 1722 // If the selector we need to register a typed getter to the
1697 // [world]. The emitter needs to know if it needs to emit a 1723 // [world]. The emitter needs to know if it needs to emit a
1698 // bound closure for a method. 1724 // bound closure for a method.
1699 TypeMask receiverType = 1725 TypeMask receiverType =
1700 new TypeMask.nonNullExact(superClass, compiler.world); 1726 new TypeMask.nonNullExact(superClass, compiler.world);
1701 selector = new TypedSelector(receiverType, selector, compiler.world); 1727 selector = new TypedSelector(receiverType, selector, compiler.world);
1702 // TODO(floitsch): we know the target. We shouldn't register a 1728 // TODO(floitsch): we know the target. We shouldn't register a
1703 // dynamic getter. 1729 // dynamic getter.
1704 registry.registerDynamicGetter(selector); 1730 registry.registerDynamicGetter(selector);
1705 registry.registerGetterForSuperMethod(node.element); 1731 registry.registerGetterForSuperMethod(node.element);
1706 methodName = backend.namer.invocationName(selector); 1732 methodName = backend.namer.invocationName(selector);
1707 } else { 1733 } else {
1708 assert(invariant(node, compiler.hasIncrementalSupport)); 1734 assert(invariant(node, compiler.hasIncrementalSupport));
1709 methodName = backend.namer.instanceMethodName(superMethod); 1735 methodName = backend.namer.instanceMethodName(superMethod);
1710 } 1736 }
1711 push(js.js('#.#.call(#)', 1737 push(js.js('#.#.call(#)',
1712 [backend.emitter.prototypeAccess(superClass, 1738 [backend.emitter.prototypeAccess(superClass,
1713 hasBeenInstantiated: true), 1739 hasBeenInstantiated: true),
1714 methodName, visitArguments(node.inputs, start: 0)]), 1740 methodName, visitArguments(node.inputs, start: 0)])
1715 node); 1741 .withSourceInformation(node.sourceInformation));
1716 } else { 1742 } else {
1717 use(node.receiver); 1743 use(node.receiver);
1718 push( 1744 push(
1719 js.js('#.#(#)', [ 1745 js.js('#.#(#)', [
1720 pop(), backend.namer.aliasedSuperMemberPropertyName(superMethod), 1746 pop(), backend.namer.aliasedSuperMemberPropertyName(superMethod),
1721 visitArguments(node.inputs, start: 1)]), // Skip receiver argument. 1747 visitArguments(node.inputs, start: 1)]) // Skip receiver argument.
1722 node); 1748 .withSourceInformation(node.sourceInformation));
1723 } 1749 }
1724 } 1750 }
1725 } 1751 }
1726 1752
1727 visitFieldGet(HFieldGet node) { 1753 visitFieldGet(HFieldGet node) {
1728 use(node.receiver); 1754 use(node.receiver);
1729 Element element = node.element; 1755 Element element = node.element;
1730 if (node.isNullCheck) { 1756 if (node.isNullCheck) {
1731 // We access a JavaScript member we know all objects besides 1757 // We access a JavaScript member we know all objects besides
1732 // null and undefined have: V8 does not like accessing a member 1758 // null and undefined have: V8 does not like accessing a member
1733 // that does not exist. 1759 // that does not exist.
1734 push(new js.PropertyAccess.field(pop(), 'toString'), node); 1760 push(new js.PropertyAccess.field(pop(), 'toString')
1761 .withSourceInformation(node.sourceInformation));
1735 } else if (element == backend.jsIndexableLength) { 1762 } else if (element == backend.jsIndexableLength) {
1736 // We're accessing a native JavaScript property called 'length' 1763 // We're accessing a native JavaScript property called 'length'
1737 // on a JS String or a JS array. Therefore, the name of that 1764 // on a JS String or a JS array. Therefore, the name of that
1738 // property should not be mangled. 1765 // property should not be mangled.
1739 push(new js.PropertyAccess.field(pop(), 'length'), node); 1766 push(new js.PropertyAccess.field(pop(), 'length')
1767 .withSourceInformation(node.sourceInformation));
1740 } else { 1768 } else {
1741 String name = backend.namer.instanceFieldPropertyName(element); 1769 String name = backend.namer.instanceFieldPropertyName(element);
1742 push(new js.PropertyAccess.field(pop(), name), node); 1770 push(new js.PropertyAccess.field(pop(), name)
1771 .withSourceInformation(node.sourceInformation));
1743 registry.registerFieldGetter(element); 1772 registry.registerFieldGetter(element);
1744 } 1773 }
1745 } 1774 }
1746 1775
1747 visitFieldSet(HFieldSet node) { 1776 visitFieldSet(HFieldSet node) {
1748 Element element = node.element; 1777 Element element = node.element;
1749 registry.registerFieldSetter(element); 1778 registry.registerFieldSetter(element);
1750 String name = backend.namer.instanceFieldPropertyName(element); 1779 String name = backend.namer.instanceFieldPropertyName(element);
1751 use(node.receiver); 1780 use(node.receiver);
1752 js.Expression receiver = pop(); 1781 js.Expression receiver = pop();
1753 use(node.value); 1782 use(node.value);
1754 push(new js.Assignment(new js.PropertyAccess.field(receiver, name), pop()), 1783 push(new js.Assignment(new js.PropertyAccess.field(receiver, name), pop())
1755 node); 1784 .withSourceInformation(node.sourceInformation));
1756 } 1785 }
1757 1786
1758 visitReadModifyWrite(HReadModifyWrite node) { 1787 visitReadModifyWrite(HReadModifyWrite node) {
1759 Element element = node.element; 1788 Element element = node.element;
1760 registry.registerFieldSetter(element); 1789 registry.registerFieldSetter(element);
1761 String name = backend.namer.instanceFieldPropertyName(element); 1790 String name = backend.namer.instanceFieldPropertyName(element);
1762 use(node.receiver); 1791 use(node.receiver);
1763 js.Expression fieldReference = new js.PropertyAccess.field(pop(), name); 1792 js.Expression fieldReference = new js.PropertyAccess.field(pop(), name);
1764 if (node.isPreOp) { 1793 if (node.isPreOp) {
1765 push(new js.Prefix(node.jsOp, fieldReference), node); 1794 push(new js.Prefix(node.jsOp, fieldReference)
1795 .withSourceInformation(node.sourceInformation));
1766 } else if (node.isPostOp) { 1796 } else if (node.isPostOp) {
1767 push(new js.Postfix(node.jsOp, fieldReference), node); 1797 push(new js.Postfix(node.jsOp, fieldReference)
1798 .withSourceInformation(node.sourceInformation));
1768 } else { 1799 } else {
1769 use(node.value); 1800 use(node.value);
1770 push(new js.Assignment.compound(fieldReference, node.jsOp, pop()), node); 1801 push(new js.Assignment.compound(fieldReference, node.jsOp, pop())
1802 .withSourceInformation(node.sourceInformation));
1771 } 1803 }
1772 } 1804 }
1773 1805
1774 visitLocalGet(HLocalGet node) { 1806 visitLocalGet(HLocalGet node) {
1775 use(node.receiver); 1807 use(node.receiver);
1776 } 1808 }
1777 1809
1778 visitLocalSet(HLocalSet node) { 1810 visitLocalSet(HLocalSet node) {
1779 use(node.value); 1811 use(node.value);
1780 assignVariable(variableNames.getName(node.receiver), pop()); 1812 assignVariable(variableNames.getName(node.receiver),
1813 pop(),
1814 node.sourceInformation);
1781 } 1815 }
1782 1816
1783 void registerForeignTypes(HForeign node) { 1817 void registerForeignTypes(HForeign node) {
1784 native.NativeBehavior nativeBehavior = node.nativeBehavior; 1818 native.NativeBehavior nativeBehavior = node.nativeBehavior;
1785 if (nativeBehavior == null) return; 1819 if (nativeBehavior == null) return;
1786 nativeBehavior.typesReturned.forEach((type) { 1820 nativeBehavior.typesReturned.forEach((type) {
1787 if (type is InterfaceType) { 1821 if (type is InterfaceType) {
1788 registry.registerInstantiatedType(type); 1822 registry.registerInstantiatedType(type);
1789 } 1823 }
1790 }); 1824 });
1791 } 1825 }
1792 1826
1793 visitForeignCode(HForeignCode node) { 1827 visitForeignCode(HForeignCode node) {
1794 List<HInstruction> inputs = node.inputs; 1828 List<HInstruction> inputs = node.inputs;
1795 if (node.isJsStatement()) { 1829 if (node.isJsStatement()) {
1796 List<js.Expression> interpolatedExpressions = <js.Expression>[]; 1830 List<js.Expression> interpolatedExpressions = <js.Expression>[];
1797 for (int i = 0; i < inputs.length; i++) { 1831 for (int i = 0; i < inputs.length; i++) {
1798 use(inputs[i]); 1832 use(inputs[i]);
1799 interpolatedExpressions.add(pop()); 1833 interpolatedExpressions.add(pop());
1800 } 1834 }
1801 pushStatement(node.codeTemplate.instantiate(interpolatedExpressions)); 1835 pushStatement(node.codeTemplate.instantiate(interpolatedExpressions)
1836 .withSourceInformation(node.sourceInformation));
1802 } else { 1837 } else {
1803 List<js.Expression> interpolatedExpressions = <js.Expression>[]; 1838 List<js.Expression> interpolatedExpressions = <js.Expression>[];
1804 for (int i = 0; i < inputs.length; i++) { 1839 for (int i = 0; i < inputs.length; i++) {
1805 use(inputs[i]); 1840 use(inputs[i]);
1806 interpolatedExpressions.add(pop()); 1841 interpolatedExpressions.add(pop());
1807 } 1842 }
1808 push(node.codeTemplate.instantiate(interpolatedExpressions)); 1843 push(node.codeTemplate.instantiate(interpolatedExpressions)
1844 .withSourceInformation(node.sourceInformation));
1809 } 1845 }
1810 1846
1811 // TODO(sra): Tell world.nativeEnqueuer about the types created here. 1847 // TODO(sra): Tell world.nativeEnqueuer about the types created here.
1812 registerForeignTypes(node); 1848 registerForeignTypes(node);
1813 } 1849 }
1814 1850
1815 visitForeignNew(HForeignNew node) { 1851 visitForeignNew(HForeignNew node) {
1816 js.Expression jsClassReference = 1852 js.Expression jsClassReference =
1817 backend.emitter.constructorAccess(node.element); 1853 backend.emitter.constructorAccess(node.element);
1818 List<js.Expression> arguments = visitArguments(node.inputs, start: 0); 1854 List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
1819 push(new js.New(jsClassReference, arguments), node); 1855 push(new js.New(jsClassReference, arguments)
1856 .withSourceInformation(node.sourceInformation));
1820 registerForeignTypes(node); 1857 registerForeignTypes(node);
1821 // We also use ForeignNew to instantiate closure classes that belong to 1858 // We also use ForeignNew to instantiate closure classes that belong to
1822 // function expressions. We have to register their use here, as otherwise 1859 // function expressions. We have to register their use here, as otherwise
1823 // code for them might not be emitted. 1860 // code for them might not be emitted.
1824 if (node.element.isClosure) { 1861 if (node.element.isClosure) {
1825 registry.registerInstantiatedClass(node.element); 1862 registry.registerInstantiatedClass(node.element);
1826 } 1863 }
1827 if (node.instantiatedTypes == null) { 1864 if (node.instantiatedTypes == null) {
1828 return; 1865 return;
1829 } 1866 }
1830 node.instantiatedTypes.forEach((type) { 1867 node.instantiatedTypes.forEach((type) {
1831 registry.registerInstantiatedType(type); 1868 registry.registerInstantiatedType(type);
1832 }); 1869 });
1833 } 1870 }
1834 1871
1835 js.Expression newLiteralBool(bool value) { 1872 js.Expression newLiteralBool(bool value,
1873 SourceInformation sourceInformation) {
1836 if (compiler.enableMinification) { 1874 if (compiler.enableMinification) {
1837 // Use !0 for true, !1 for false. 1875 // Use !0 for true, !1 for false.
1838 return new js.Prefix("!", new js.LiteralNumber(value ? "0" : "1")); 1876 return new js.Prefix("!", new js.LiteralNumber(value ? "0" : "1"))
1877 .withSourceInformation(sourceInformation);
1839 } else { 1878 } else {
1840 return new js.LiteralBool(value); 1879 return new js.LiteralBool(value)
1880 .withSourceInformation(sourceInformation);
1841 } 1881 }
1842 } 1882 }
1843 1883
1844 void generateConstant(ConstantValue constant) { 1884 void generateConstant(ConstantValue constant,
1885 SourceInformation sourceInformation) {
1845 if (constant.isFunction) { 1886 if (constant.isFunction) {
1846 FunctionConstantValue function = constant; 1887 FunctionConstantValue function = constant;
1847 registry.registerStaticUse(function.element); 1888 registry.registerStaticUse(function.element);
1848 } 1889 }
1849 if (constant.isType) { 1890 if (constant.isType) {
1850 // If the type is a web component, we need to ensure the constructors are 1891 // If the type is a web component, we need to ensure the constructors are
1851 // available to 'upgrade' the native object. 1892 // available to 'upgrade' the native object.
1852 TypeConstantValue type = constant; 1893 TypeConstantValue type = constant;
1853 Element element = type.representedType.element; 1894 Element element = type.representedType.element;
1854 if (element != null && element.isClass) { 1895 if (element != null && element.isClass) {
1855 registry.registerTypeConstant(element); 1896 registry.registerTypeConstant(element);
1856 } 1897 }
1857 } 1898 }
1858 push(backend.emitter.constantReference(constant)); 1899 push(backend.emitter.constantReference(constant)
1900 .withSourceInformation(sourceInformation));
1859 } 1901 }
1860 1902
1861 visitConstant(HConstant node) { 1903 visitConstant(HConstant node) {
1862 assert(isGenerateAtUseSite(node)); 1904 assert(isGenerateAtUseSite(node));
1863 generateConstant(node.constant); 1905 generateConstant(node.constant, node.sourceInformation);
1864 1906
1865 registry.registerCompileTimeConstant(node.constant); 1907 registry.registerCompileTimeConstant(node.constant);
1866 backend.constants.addCompileTimeConstantForEmission(node.constant); 1908 backend.constants.addCompileTimeConstantForEmission(node.constant);
1867 } 1909 }
1868 1910
1869 visitNot(HNot node) { 1911 visitNot(HNot node) {
1870 assert(node.inputs.length == 1); 1912 assert(node.inputs.length == 1);
1871 generateNot(node.inputs[0]); 1913 generateNot(node.inputs[0], node.sourceInformation);
1872 attachLocationToLast(node);
1873 } 1914 }
1874 1915
1875 static String mapRelationalOperator(String op, bool inverse) { 1916 static String mapRelationalOperator(String op, bool inverse) {
1876 Map<String, String> inverseOperator = const <String, String>{ 1917 Map<String, String> inverseOperator = const <String, String>{
1877 "==" : "!=", 1918 "==" : "!=",
1878 "!=" : "==", 1919 "!=" : "==",
1879 "===": "!==", 1920 "===": "!==",
1880 "!==": "===", 1921 "!==": "===",
1881 "<" : ">=", 1922 "<" : ">=",
1882 "<=" : ">", 1923 "<=" : ">",
1883 ">" : "<=", 1924 ">" : "<=",
1884 ">=" : "<" 1925 ">=" : "<"
1885 }; 1926 };
1886 return inverse ? inverseOperator[op] : op; 1927 return inverse ? inverseOperator[op] : op;
1887 } 1928 }
1888 1929
1889 void generateNot(HInstruction input) { 1930 void generateNot(HInstruction input, SourceInformation sourceInformation) {
1890 bool canGenerateOptimizedComparison(HInstruction instruction) { 1931 bool canGenerateOptimizedComparison(HInstruction instruction) {
1891 if (instruction is !HRelational) return false; 1932 if (instruction is !HRelational) return false;
1892 1933
1893 HRelational relational = instruction; 1934 HRelational relational = instruction;
1894 1935
1895 HInstruction left = relational.left; 1936 HInstruction left = relational.left;
1896 HInstruction right = relational.right; 1937 HInstruction right = relational.right;
1897 if (left.isStringOrNull(compiler) && right.isStringOrNull(compiler)) { 1938 if (left.isStringOrNull(compiler) && right.isStringOrNull(compiler)) {
1898 return true; 1939 return true;
1899 } 1940 }
1900 1941
1901 // This optimization doesn't work for NaN, so we only do it if the 1942 // This optimization doesn't work for NaN, so we only do it if the
1902 // type is known to be an integer. 1943 // type is known to be an integer.
1903 return left.isInteger(compiler) && right.isInteger(compiler); 1944 return left.isInteger(compiler) && right.isInteger(compiler);
1904 } 1945 }
1905 1946
1906 bool handledBySpecialCase = false; 1947 bool handledBySpecialCase = false;
1907 if (isGenerateAtUseSite(input)) { 1948 if (isGenerateAtUseSite(input)) {
1908 handledBySpecialCase = true; 1949 handledBySpecialCase = true;
1909 if (input is HIs) { 1950 if (input is HIs) {
1910 emitIs(input, '!=='); 1951 emitIs(input, '!==', sourceInformation);
1911 } else if (input is HIsViaInterceptor) { 1952 } else if (input is HIsViaInterceptor) {
1912 emitIsViaInterceptor(input, true); 1953 emitIsViaInterceptor(input, sourceInformation, negative: true);
1913 } else if (input is HNot) { 1954 } else if (input is HNot) {
1914 use(input.inputs[0]); 1955 use(input.inputs[0]);
1915 } else if (input is HIdentity) { 1956 } else if (input is HIdentity) {
1916 emitIdentityComparison(input, true); 1957 emitIdentityComparison(input, sourceInformation, inverse: true);
1917 } else if (input is HBoolify) { 1958 } else if (input is HBoolify) {
1918 use(input.inputs[0]); 1959 use(input.inputs[0]);
1919 push(new js.Binary("!==", pop(), newLiteralBool(true)), input); 1960 push(new js.Binary("!==", pop(),
1961 newLiteralBool(true, input.sourceInformation))
1962 .withSourceInformation(sourceInformation));
1920 } else if (canGenerateOptimizedComparison(input)) { 1963 } else if (canGenerateOptimizedComparison(input)) {
1921 HRelational relational = input; 1964 HRelational relational = input;
1922 BinaryOperation operation = 1965 BinaryOperation operation =
1923 relational.operation(backend.constantSystem); 1966 relational.operation(backend.constantSystem);
1924 String op = mapRelationalOperator(operation.name, true); 1967 String op = mapRelationalOperator(operation.name, true);
1925 visitRelational(input, op); 1968 handleInvokeBinary(input, op, sourceInformation);
1926 } else { 1969 } else {
1927 handledBySpecialCase = false; 1970 handledBySpecialCase = false;
1928 } 1971 }
1929 } 1972 }
1930 if (!handledBySpecialCase) { 1973 if (!handledBySpecialCase) {
1931 use(input); 1974 use(input);
1932 push(new js.Prefix("!", pop())); 1975 push(new js.Prefix("!", pop()).withSourceInformation(sourceInformation));
1933 } 1976 }
1934 } 1977 }
1935 1978
1936 visitParameterValue(HParameterValue node) { 1979 visitParameterValue(HParameterValue node) {
1937 assert(!isGenerateAtUseSite(node)); 1980 assert(!isGenerateAtUseSite(node));
1938 String name = variableNames.getName(node); 1981 String name = variableNames.getName(node);
1939 parameters.add(new js.Parameter(name)); 1982 parameters.add(new js.Parameter(name));
1940 declaredLocals.add(name); 1983 declaredLocals.add(name);
1941 } 1984 }
1942 1985
(...skipping 10 matching lines...) Expand all
1953 HBasicBlock ifBlock = node.block.dominator; 1996 HBasicBlock ifBlock = node.block.dominator;
1954 assert(controlFlowOperators.contains(ifBlock.last)); 1997 assert(controlFlowOperators.contains(ifBlock.last));
1955 HInstruction input = ifBlock.last.inputs[0]; 1998 HInstruction input = ifBlock.last.inputs[0];
1956 if (input.isConstantFalse()) { 1999 if (input.isConstantFalse()) {
1957 use(node.inputs[1]); 2000 use(node.inputs[1]);
1958 } else if (input.isConstantTrue()) { 2001 } else if (input.isConstantTrue()) {
1959 use(node.inputs[0]); 2002 use(node.inputs[0]);
1960 } else if (node.inputs[1].isConstantBoolean()) { 2003 } else if (node.inputs[1].isConstantBoolean()) {
1961 String operation = node.inputs[1].isConstantFalse() ? '&&' : '||'; 2004 String operation = node.inputs[1].isConstantFalse() ? '&&' : '||';
1962 if (operation == '||') { 2005 if (operation == '||') {
1963 generateNot(input); 2006 generateNot(input, input.sourceInformation);
1964 } else { 2007 } else {
1965 use(input); 2008 use(input);
1966 } 2009 }
1967 js.Expression left = pop(); 2010 js.Expression left = pop();
1968 use(node.inputs[0]); 2011 use(node.inputs[0]);
1969 push(new js.Binary(operation, left, pop())); 2012 push(new js.Binary(operation, left, pop()));
1970 } else { 2013 } else {
1971 use(input); 2014 use(input);
1972 js.Expression test = pop(); 2015 js.Expression test = pop();
1973 use(node.inputs[0]); 2016 use(node.inputs[0]);
1974 js.Expression then = pop(); 2017 js.Expression then = pop();
1975 use(node.inputs[1]); 2018 use(node.inputs[1]);
1976 push(new js.Conditional(test, then, pop())); 2019 push(new js.Conditional(test, then, pop()));
1977 } 2020 }
1978 } 2021 }
1979 2022
1980 visitReturn(HReturn node) { 2023 visitReturn(HReturn node) {
1981 assert(node.inputs.length == 1); 2024 assert(node.inputs.length == 1);
1982 HInstruction input = node.inputs[0]; 2025 HInstruction input = node.inputs[0];
1983 if (input.isConstantNull()) { 2026 if (input.isConstantNull()) {
1984 pushStatement(new js.Return(null), node); 2027 pushStatement(new js.Return()
2028 .withSourceInformation(node.sourceInformation));
1985 } else { 2029 } else {
1986 use(node.inputs[0]); 2030 use(node.inputs[0]);
1987 pushStatement(new js.Return(pop()), node); 2031 pushStatement(new js.Return(pop())
2032 .withSourceInformation(node.sourceInformation));
1988 } 2033 }
1989 } 2034 }
1990 2035
1991 visitThis(HThis node) { 2036 visitThis(HThis node) {
1992 push(new js.This()); 2037 push(new js.This());
1993 } 2038 }
1994 2039
1995 visitThrow(HThrow node) { 2040 visitThrow(HThrow node) {
1996 if (node.isRethrow) { 2041 if (node.isRethrow) {
1997 use(node.inputs[0]); 2042 use(node.inputs[0]);
1998 pushStatement(new js.Throw(pop()), node); 2043 pushStatement(new js.Throw(pop())
2044 .withSourceInformation(node.sourceInformation));
1999 } else { 2045 } else {
2000 generateThrowWithHelper('wrapException', node.inputs[0]); 2046 generateThrowWithHelper('wrapException', node.inputs[0],
2047 sourceInformation: node.sourceInformation);
2001 } 2048 }
2002 } 2049 }
2003 2050
2004 visitAwait(HAwait node) { 2051 visitAwait(HAwait node) {
2005 use(node.inputs[0]); 2052 use(node.inputs[0]);
2006 push(new js.Await(pop()), node); 2053 push(new js.Await(pop())
2054 .withSourceInformation(node.sourceInformation));
2007 } 2055 }
2008 2056
2009 visitYield(HYield node) { 2057 visitYield(HYield node) {
2010 use(node.inputs[0]); 2058 use(node.inputs[0]);
2011 pushStatement(new js.DartYield(pop(), node.hasStar), node); 2059 pushStatement(new js.DartYield(pop(), node.hasStar)
2060 .withSourceInformation(node.sourceInformation));
2012 } 2061 }
2013 2062
2014 visitRangeConversion(HRangeConversion node) { 2063 visitRangeConversion(HRangeConversion node) {
2015 // Range conversion instructions are removed by the value range 2064 // Range conversion instructions are removed by the value range
2016 // analyzer. 2065 // analyzer.
2017 assert(false); 2066 assert(false);
2018 } 2067 }
2019 2068
2020 visitBoundsCheck(HBoundsCheck node) { 2069 visitBoundsCheck(HBoundsCheck node) {
2021 // TODO(ngeoffray): Separate the two checks of the bounds check, so, 2070 // TODO(ngeoffray): Separate the two checks of the bounds check, so,
(...skipping 29 matching lines...) Expand all
2051 ? over 2100 ? over
2052 : over == null 2101 : over == null
2053 ? under 2102 ? under
2054 : new js.Binary("||", under, over); 2103 : new js.Binary("||", under, over);
2055 js.Statement thenBody = new js.Block.empty(); 2104 js.Statement thenBody = new js.Block.empty();
2056 js.Block oldContainer = currentContainer; 2105 js.Block oldContainer = currentContainer;
2057 currentContainer = thenBody; 2106 currentContainer = thenBody;
2058 generateThrowWithHelper('ioore', [node.array, node.index]); 2107 generateThrowWithHelper('ioore', [node.array, node.index]);
2059 currentContainer = oldContainer; 2108 currentContainer = oldContainer;
2060 thenBody = unwrapStatement(thenBody); 2109 thenBody = unwrapStatement(thenBody);
2061 pushStatement(new js.If.noElse(underOver, thenBody), node); 2110 pushStatement(new js.If.noElse(underOver, thenBody)
2111 .withSourceInformation(node.sourceInformation));
2062 } else { 2112 } else {
2063 generateThrowWithHelper('ioore', [node.array, node.index]); 2113 generateThrowWithHelper('ioore', [node.array, node.index]);
2064 } 2114 }
2065 } 2115 }
2066 2116
2067 void generateThrowWithHelper(String helperName, argument) { 2117 void generateThrowWithHelper(String helperName, argument,
2118 {SourceInformation sourceInformation}) {
2068 Element helper = backend.findHelper(helperName); 2119 Element helper = backend.findHelper(helperName);
2069 registry.registerStaticUse(helper); 2120 registry.registerStaticUse(helper);
2070 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper); 2121 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper);
2071 List arguments = []; 2122 List arguments = [];
2072 var location; 2123 var location;
2073 if (argument is List) { 2124 if (argument is List) {
2074 location = argument[0]; 2125 location = argument[0];
2075 argument.forEach((instruction) { 2126 argument.forEach((instruction) {
2076 use(instruction); 2127 use(instruction);
2077 arguments.add(pop()); 2128 arguments.add(pop());
2078 }); 2129 });
2079 } else { 2130 } else {
2080 location = argument; 2131 location = argument;
2081 use(argument); 2132 use(argument);
2082 arguments.add(pop()); 2133 arguments.add(pop());
2083 } 2134 }
2084 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false)); 2135 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false),
2085 value = attachLocation(value, location); 2136 sourceInformation: sourceInformation);
2086 // BUG(4906): Using throw/return here adds to the size of the generated code 2137 // BUG(4906): Using throw/return here adds to the size of the generated code
2087 // but it has the advantage of explicitly telling the JS engine that 2138 // but it has the advantage of explicitly telling the JS engine that
2088 // this code path will terminate abruptly. Needs more work. 2139 // this code path will terminate abruptly. Needs more work.
2089 if (helperName == 'wrapException') { 2140 if (helperName == 'wrapException') {
2090 pushStatement(new js.Throw(value)); 2141 pushStatement(new js.Throw(value)
2142 .withSourceInformation(sourceInformation));
2091 } else { 2143 } else {
2092 Element element = work.element; 2144 Element element = work.element;
2093 if (element is FunctionElement && element.asyncMarker.isYielding) { 2145 if (element is FunctionElement && element.asyncMarker.isYielding) {
2094 // `return <expr>;` is illegal in a sync* or async* function. 2146 // `return <expr>;` is illegal in a sync* or async* function.
2095 // To have the the async-translator working, we avoid introducing 2147 // To have the the async-translator working, we avoid introducing
2096 // `return` nodes. 2148 // `return` nodes.
2097 pushStatement(new js.ExpressionStatement(value)); 2149 pushStatement(new js.ExpressionStatement(value)
2150 .withSourceInformation(sourceInformation));
2098 } else { 2151 } else {
2099 pushStatement(new js.Return(value)); 2152 pushStatement(new js.Return(value)
2153 .withSourceInformation(sourceInformation));
2100 } 2154 }
2101 } 2155 }
2102 } 2156 }
2103 2157
2104 visitThrowExpression(HThrowExpression node) { 2158 visitThrowExpression(HThrowExpression node) {
2105 HInstruction argument = node.inputs[0]; 2159 HInstruction argument = node.inputs[0];
2106 use(argument); 2160 use(argument);
2107 2161
2108 Element helper = backend.findHelper("throwExpression"); 2162 Element helper = backend.findHelper("throwExpression");
2109 registry.registerStaticUse(helper); 2163 registry.registerStaticUse(helper);
2110 2164
2111 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper); 2165 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper);
2112 js.Call value = new js.Call(jsHelper, [pop()]); 2166 js.Call value = new js.Call(jsHelper, [pop()])
2113 value = attachLocation(value, argument); 2167 .withSourceInformation(node.sourceInformation);
2114 push(value, node); 2168 push(value);
2115 } 2169 }
2116 2170
2117 void visitSwitch(HSwitch node) { 2171 void visitSwitch(HSwitch node) {
2118 // Switches are handled using [visitSwitchInfo]. 2172 // Switches are handled using [visitSwitchInfo].
2119 } 2173 }
2120 2174
2121 void visitStatic(HStatic node) { 2175 void visitStatic(HStatic node) {
2122 Element element = node.element; 2176 Element element = node.element;
2123 assert(element.isFunction || element.isField); 2177 assert(element.isFunction || element.isField);
2124 if (element.isFunction) { 2178 if (element.isFunction) {
2125 push(backend.emitter.isolateStaticClosureAccess(node.element)); 2179 push(backend.emitter.isolateStaticClosureAccess(node.element)
2180 .withSourceInformation(node.sourceInformation));
2126 } else { 2181 } else {
2127 push(backend.emitter.staticFieldAccess(node.element)); 2182 push(backend.emitter.staticFieldAccess(node.element)
2183 .withSourceInformation(node.sourceInformation));
2128 } 2184 }
2129 registry.registerStaticUse(element); 2185 registry.registerStaticUse(element);
2130 } 2186 }
2131 2187
2132 void visitLazyStatic(HLazyStatic node) { 2188 void visitLazyStatic(HLazyStatic node) {
2133 Element element = node.element; 2189 Element element = node.element;
2134 registry.registerStaticUse(element); 2190 registry.registerStaticUse(element);
2135 js.Expression lazyGetter = 2191 js.Expression lazyGetter =
2136 backend.emitter.isolateLazyInitializerAccess(element); 2192 backend.emitter.isolateLazyInitializerAccess(element);
2137 js.Call call = new js.Call(lazyGetter, <js.Expression>[]); 2193 js.Call call = new js.Call(lazyGetter, <js.Expression>[],
2138 push(call, node); 2194 sourceInformation: node.sourceInformation);
2195 push(call);
2139 } 2196 }
2140 2197
2141 void visitStaticStore(HStaticStore node) { 2198 void visitStaticStore(HStaticStore node) {
2142 registry.registerStaticUse(node.element); 2199 registry.registerStaticUse(node.element);
2143 js.Node variable = backend.emitter.staticFieldAccess(node.element); 2200 js.Node variable = backend.emitter.staticFieldAccess(node.element);
2144 use(node.inputs[0]); 2201 use(node.inputs[0]);
2145 push(new js.Assignment(variable, pop()), node); 2202 push(new js.Assignment(variable, pop())
2203 .withSourceInformation(node.sourceInformation));
2146 } 2204 }
2147 2205
2148 void visitStringConcat(HStringConcat node) { 2206 void visitStringConcat(HStringConcat node) {
2149 use(node.left); 2207 use(node.left);
2150 js.Expression jsLeft = pop(); 2208 js.Expression jsLeft = pop();
2151 use(node.right); 2209 use(node.right);
2152 push(new js.Binary('+', jsLeft, pop()), node); 2210 push(new js.Binary('+', jsLeft, pop())
2211 .withSourceInformation(node.sourceInformation));
2153 } 2212 }
2154 2213
2155 void visitStringify(HStringify node) { 2214 void visitStringify(HStringify node) {
2156 HInstruction input = node.inputs.first; 2215 HInstruction input = node.inputs.first;
2157 if (input.isString(compiler)) { 2216 if (input.isString(compiler)) {
2158 use(input); 2217 use(input);
2159 } else if (input.isInteger(compiler) || input.isBoolean(compiler)) { 2218 } else if (input.isInteger(compiler) || input.isBoolean(compiler)) {
2160 // JavaScript's + operator with a string for the left operand will convert 2219 // JavaScript's + operator with a string for the left operand will convert
2161 // the right operand to a string, and the conversion result is correct. 2220 // the right operand to a string, and the conversion result is correct.
2162 use(input); 2221 use(input);
2163 if (node.usedBy.length == 1 2222 if (node.usedBy.length == 1
2164 && node.usedBy[0] is HStringConcat 2223 && node.usedBy[0] is HStringConcat
2165 && node.usedBy[0].inputs[1] == node) { 2224 && node.usedBy[0].inputs[1] == node) {
2166 // The context is already <string> + value. 2225 // The context is already <string> + value.
2167 } else { 2226 } else {
2168 // Force an empty string for the first operand. 2227 // Force an empty string for the first operand.
2169 push(new js.Binary('+', js.string(""), pop()), node); 2228 push(new js.Binary('+', js.string(""), pop())
2229 .withSourceInformation(node.sourceInformation));
2170 } 2230 }
2171 } else { 2231 } else {
2172 Element convertToString = backend.getStringInterpolationHelper(); 2232 Element convertToString = backend.getStringInterpolationHelper();
2173 registry.registerStaticUse(convertToString); 2233 registry.registerStaticUse(convertToString);
2174 js.Expression jsHelper = 2234 js.Expression jsHelper =
2175 backend.emitter.staticFunctionAccess(convertToString); 2235 backend.emitter.staticFunctionAccess(convertToString);
2176 use(input); 2236 use(input);
2177 push(new js.Call(jsHelper, <js.Expression>[pop()]), node); 2237 push(new js.Call(jsHelper, <js.Expression>[pop()],
2238 sourceInformation: node.sourceInformation));
2178 } 2239 }
2179 } 2240 }
2180 2241
2181 void visitLiteralList(HLiteralList node) { 2242 void visitLiteralList(HLiteralList node) {
2182 registry.registerInstantiatedClass(compiler.listClass); 2243 registry.registerInstantiatedClass(compiler.listClass);
2183 generateArrayLiteral(node); 2244 generateArrayLiteral(node);
2184 } 2245 }
2185 2246
2186 void generateArrayLiteral(HLiteralList node) { 2247 void generateArrayLiteral(HLiteralList node) {
2187 List<js.Expression> elements = node.inputs.map((HInstruction input) { 2248 List<js.Expression> elements = node.inputs.map((HInstruction input) {
2188 use(input); 2249 use(input);
2189 return pop(); 2250 return pop();
2190 }).toList(); 2251 }).toList();
2191 push(new js.ArrayInitializer(elements), node); 2252 push(new js.ArrayInitializer(elements)
2253 .withSourceInformation(node.sourceInformation));
2192 } 2254 }
2193 2255
2194 void visitIndex(HIndex node) { 2256 void visitIndex(HIndex node) {
2195 use(node.receiver); 2257 use(node.receiver);
2196 js.Expression receiver = pop(); 2258 js.Expression receiver = pop();
2197 use(node.index); 2259 use(node.index);
2198 push(new js.PropertyAccess(receiver, pop()), node); 2260 push(new js.PropertyAccess(receiver, pop())
2261 .withSourceInformation(node.sourceInformation));
2199 } 2262 }
2200 2263
2201 void visitIndexAssign(HIndexAssign node) { 2264 void visitIndexAssign(HIndexAssign node) {
2202 use(node.receiver); 2265 use(node.receiver);
2203 js.Expression receiver = pop(); 2266 js.Expression receiver = pop();
2204 use(node.index); 2267 use(node.index);
2205 js.Expression index = pop(); 2268 js.Expression index = pop();
2206 use(node.value); 2269 use(node.value);
2207 push(new js.Assignment(new js.PropertyAccess(receiver, index), pop()), 2270 push(new js.Assignment(new js.PropertyAccess(receiver, index), pop())
2208 node); 2271 .withSourceInformation(node.sourceInformation));
2209 } 2272 }
2210 2273
2211 void checkInt(HInstruction input, String cmp) { 2274 void checkInt(HInstruction input, String cmp) {
2212 use(input); 2275 use(input);
2213 js.Expression left = pop(); 2276 js.Expression left = pop();
2214 use(input); 2277 use(input);
2215 js.Expression or0 = new js.Binary("|", pop(), new js.LiteralNumber("0")); 2278 js.Expression or0 = new js.Binary("|", pop(), new js.LiteralNumber("0"));
2216 push(new js.Binary(cmp, left, or0)); 2279 push(new js.Binary(cmp, left, or0));
2217 } 2280 }
2218 2281
2219 void checkBigInt(HInstruction input, String cmp) { 2282 void checkBigInt(HInstruction input, String cmp,
2283 SourceInformation sourceInformation) {
2220 use(input); 2284 use(input);
2221 js.Expression left = pop(); 2285 js.Expression left = pop();
2222 use(input); 2286 use(input);
2223 js.Expression right = pop(); 2287 js.Expression right = pop();
2224 // TODO(4984): Deal with infinity and -0.0. 2288 // TODO(4984): Deal with infinity and -0.0.
2225 push(js.js('Math.floor(#) $cmp #', <js.Expression>[left, right])); 2289 push(js.js('Math.floor(#) $cmp #', <js.Expression>[left, right])
2290 .withSourceInformation(sourceInformation));
2226 } 2291 }
2227 2292
2228 void checkTypeOf(HInstruction input, String cmp, String typeName) { 2293 void checkTypeOf(HInstruction input, String cmp, String typeName,
2294 SourceInformation sourceInformation) {
2229 use(input); 2295 use(input);
2230 js.Expression typeOf = new js.Prefix("typeof", pop()); 2296 js.Expression typeOf = new js.Prefix("typeof", pop());
2231 push(new js.Binary(cmp, typeOf, js.string(typeName))); 2297 push(new js.Binary(cmp, typeOf, js.string(typeName)));
2232 } 2298 }
2233 2299
2234 void checkNum(HInstruction input, String cmp) 2300 void checkNum(HInstruction input, String cmp,
2235 => checkTypeOf(input, cmp, 'number'); 2301 SourceInformation sourceInformation) {
2302 return checkTypeOf(input, cmp, 'number', sourceInformation);
2303 }
2236 2304
2237 void checkDouble(HInstruction input, String cmp) => checkNum(input, cmp); 2305 void checkDouble(HInstruction input, String cmp,
2306 SourceInformation sourceInformation) {
2307 return checkNum(input, cmp, sourceInformation);
2308 }
2238 2309
2239 void checkString(HInstruction input, String cmp) 2310 void checkString(HInstruction input, String cmp,
2240 => checkTypeOf(input, cmp, 'string'); 2311 SourceInformation sourceInformation) {
2312 return checkTypeOf(input, cmp, 'string', sourceInformation);
2313 }
2241 2314
2242 void checkBool(HInstruction input, String cmp) 2315 void checkBool(HInstruction input, String cmp,
2243 => checkTypeOf(input, cmp, 'boolean'); 2316 SourceInformation sourceInformation) {
2317 return checkTypeOf(input, cmp, 'boolean', sourceInformation);
2318 }
2244 2319
2245 void checkObject(HInstruction input, String cmp) { 2320 void checkObject(HInstruction input, String cmp,
2321 SourceInformation sourceInformation) {
2246 assert(NullConstantValue.JsNull == 'null'); 2322 assert(NullConstantValue.JsNull == 'null');
2247 if (cmp == "===") { 2323 if (cmp == "===") {
2248 checkTypeOf(input, '===', 'object'); 2324 checkTypeOf(input, '===', 'object', sourceInformation);
2249 js.Expression left = pop(); 2325 js.Expression left = pop();
2250 use(input); 2326 use(input);
2251 js.Expression notNull = new js.Binary("!==", pop(), new js.LiteralNull()); 2327 js.Expression notNull = new js.Binary("!==", pop(), new js.LiteralNull());
2252 push(new js.Binary("&&", left, notNull)); 2328 push(new js.Binary("&&", left, notNull)
2329 .withSourceInformation(sourceInformation));
2253 } else { 2330 } else {
2254 assert(cmp == "!=="); 2331 assert(cmp == "!==");
2255 checkTypeOf(input, '!==', 'object'); 2332 checkTypeOf(input, '!==', 'object', sourceInformation);
2256 js.Expression left = pop(); 2333 js.Expression left = pop();
2257 use(input); 2334 use(input);
2258 js.Expression eqNull = new js.Binary("===", pop(), new js.LiteralNull()); 2335 js.Expression eqNull = new js.Binary("===", pop(), new js.LiteralNull());
2259 push(new js.Binary("||", left, eqNull)); 2336 push(new js.Binary("||", left, eqNull)
2337 .withSourceInformation(sourceInformation));
2260 } 2338 }
2261 } 2339 }
2262 2340
2263 void checkArray(HInstruction input, String cmp) { 2341 void checkArray(HInstruction input, String cmp) {
2264 use(input); 2342 use(input);
2265 js.PropertyAccess constructor = 2343 js.PropertyAccess constructor =
2266 new js.PropertyAccess.field(pop(), 'constructor'); 2344 new js.PropertyAccess.field(pop(), 'constructor');
2267 push(new js.Binary(cmp, constructor, new js.VariableUse('Array'))); 2345 push(new js.Binary(cmp, constructor, new js.VariableUse('Array')));
2268 } 2346 }
2269 2347
(...skipping 30 matching lines...) Expand all
2300 use(input); 2378 use(input);
2301 push(new js.Binary('==', pop(), new js.LiteralNull())); 2379 push(new js.Binary('==', pop(), new js.LiteralNull()));
2302 } 2380 }
2303 2381
2304 void checkNonNull(HInstruction input) { 2382 void checkNonNull(HInstruction input) {
2305 use(input); 2383 use(input);
2306 push(new js.Binary('!=', pop(), new js.LiteralNull())); 2384 push(new js.Binary('!=', pop(), new js.LiteralNull()));
2307 } 2385 }
2308 2386
2309 void checkType(HInstruction input, HInstruction interceptor, 2387 void checkType(HInstruction input, HInstruction interceptor,
2310 DartType type, {bool negative: false}) { 2388 DartType type,
2389 SourceInformation sourceInformation,
2390 {bool negative: false}) {
2311 Element element = type.element; 2391 Element element = type.element;
2312 if (element == backend.jsArrayClass) { 2392 if (element == backend.jsArrayClass) {
2313 checkArray(input, negative ? '!==': '==='); 2393 checkArray(input, negative ? '!==': '===');
2314 return; 2394 return;
2315 } else if (element == backend.jsMutableArrayClass) { 2395 } else if (element == backend.jsMutableArrayClass) {
2316 if (negative) { 2396 if (negative) {
2317 checkImmutableArray(input); 2397 checkImmutableArray(input);
2318 } else { 2398 } else {
2319 checkMutableArray(input); 2399 checkMutableArray(input);
2320 } 2400 }
(...skipping 14 matching lines...) Expand all
2335 return; 2415 return;
2336 } else if (element == backend.jsUnmodifiableArrayClass) { 2416 } else if (element == backend.jsUnmodifiableArrayClass) {
2337 if (negative) { 2417 if (negative) {
2338 checkMutableArray(input); 2418 checkMutableArray(input);
2339 } else { 2419 } else {
2340 checkImmutableArray(input); 2420 checkImmutableArray(input);
2341 } 2421 }
2342 return; 2422 return;
2343 } 2423 }
2344 if (interceptor != null) { 2424 if (interceptor != null) {
2345 checkTypeViaProperty(interceptor, type, negative); 2425 checkTypeViaProperty(interceptor, type, sourceInformation,
2426 negative: negative);
2346 } else { 2427 } else {
2347 checkTypeViaProperty(input, type, negative); 2428 checkTypeViaProperty(input, type, sourceInformation, negative: negative);
2348 } 2429 }
2349 } 2430 }
2350 2431
2351 void checkTypeViaProperty(HInstruction input, DartType type, bool negative) { 2432 void checkTypeViaProperty(HInstruction input, DartType type,
2433 SourceInformation sourceInformation,
2434 {bool negative: false}) {
2352 registry.registerIsCheck(type); 2435 registry.registerIsCheck(type);
2353 2436
2354 use(input); 2437 use(input);
2355 2438
2356 js.PropertyAccess field = 2439 js.PropertyAccess field =
2357 new js.PropertyAccess.field(pop(), backend.namer.operatorIsType(type)); 2440 new js.PropertyAccess.field(pop(), backend.namer.operatorIsType(type))
2441 .withSourceInformation(sourceInformation);
2358 // We always negate at least once so that the result is boolified. 2442 // We always negate at least once so that the result is boolified.
2359 push(new js.Prefix('!', field)); 2443 push(new js.Prefix('!', field)
2444 .withSourceInformation(sourceInformation));
2360 // If the result is not negated, put another '!' in front. 2445 // If the result is not negated, put another '!' in front.
2361 if (!negative) push(new js.Prefix('!', pop())); 2446 if (!negative) {
2447 push(new js.Prefix('!', pop())
2448 .withSourceInformation(sourceInformation));
2449 }
2362 } 2450 }
2363 2451
2364 void checkTypeViaInstanceof( 2452 void checkTypeViaInstanceof(
2365 HInstruction input, DartType type, bool negative) { 2453 HInstruction input, DartType type,
2454 SourceInformation sourceInformation,
2455 {bool negative: false}) {
2366 registry.registerIsCheck(type); 2456 registry.registerIsCheck(type);
2367 2457
2368 use(input); 2458 use(input);
2369 2459
2370 js.Expression jsClassReference = 2460 js.Expression jsClassReference =
2371 backend.emitter.constructorAccess(type.element); 2461 backend.emitter.constructorAccess(type.element);
2372 push(js.js('# instanceof #', [pop(), jsClassReference])); 2462 push(js.js('# instanceof #', [pop(), jsClassReference])
2373 if (negative) push(new js.Prefix('!', pop())); 2463 .withSourceInformation(sourceInformation));
2464 if (negative) {
2465 push(new js.Prefix('!', pop())
2466 .withSourceInformation(sourceInformation));
2467 }
2374 registry.registerInstantiatedType(type); 2468 registry.registerInstantiatedType(type);
2375 } 2469 }
2376 2470
2377 void handleNumberOrStringSupertypeCheck(HInstruction input, 2471 void handleNumberOrStringSupertypeCheck(HInstruction input,
2378 HInstruction interceptor, 2472 HInstruction interceptor,
2379 DartType type, 2473 DartType type,
2380 { bool negative: false }) { 2474 SourceInformation sourceInformation,
2381 assert(!identical(type.element, compiler.listClass) 2475 {bool negative: false}) {
2382 && !Elements.isListSupertype(type.element, compiler) 2476 assert(!identical(type.element, compiler.listClass) &&
2383 && !Elements.isStringOnlySupertype(type.element, compiler)); 2477 !Elements.isListSupertype(type.element, compiler) &&
2478 !Elements.isStringOnlySupertype(type.element, compiler));
2384 String relation = negative ? '!==' : '==='; 2479 String relation = negative ? '!==' : '===';
2385 checkNum(input, relation); 2480 checkNum(input, relation, sourceInformation);
2386 js.Expression numberTest = pop(); 2481 js.Expression numberTest = pop();
2387 checkString(input, relation); 2482 checkString(input, relation, sourceInformation);
2388 js.Expression stringTest = pop(); 2483 js.Expression stringTest = pop();
2389 checkObject(input, relation); 2484 checkObject(input, relation, sourceInformation);
2390 js.Expression objectTest = pop(); 2485 js.Expression objectTest = pop();
2391 checkType(input, interceptor, type, negative: negative); 2486 checkType(input, interceptor, type, sourceInformation, negative: negative);
2392 String combiner = negative ? '&&' : '||'; 2487 String combiner = negative ? '&&' : '||';
2393 String combiner2 = negative ? '||' : '&&'; 2488 String combiner2 = negative ? '||' : '&&';
2394 push(new js.Binary(combiner, 2489 push(new js.Binary(combiner,
2395 new js.Binary(combiner, numberTest, stringTest), 2490 new js.Binary(combiner, numberTest, stringTest)
2396 new js.Binary(combiner2, objectTest, pop()))); 2491 .withSourceInformation(sourceInformation),
2492 new js.Binary(combiner2, objectTest, pop())
2493 .withSourceInformation(sourceInformation))
2494 .withSourceInformation(sourceInformation));
2397 } 2495 }
2398 2496
2399 void handleStringSupertypeCheck(HInstruction input, 2497 void handleStringSupertypeCheck(HInstruction input,
2400 HInstruction interceptor, 2498 HInstruction interceptor,
2401 DartType type, 2499 DartType type,
2402 { bool negative: false }) { 2500 SourceInformation sourceInformation,
2501 {bool negative: false}) {
2403 assert(!identical(type.element, compiler.listClass) 2502 assert(!identical(type.element, compiler.listClass)
2404 && !Elements.isListSupertype(type.element, compiler) 2503 && !Elements.isListSupertype(type.element, compiler)
2405 && !Elements.isNumberOrStringSupertype(type.element, compiler)); 2504 && !Elements.isNumberOrStringSupertype(type.element, compiler));
2406 String relation = negative ? '!==' : '==='; 2505 String relation = negative ? '!==' : '===';
2407 checkString(input, relation); 2506 checkString(input, relation, sourceInformation);
2408 js.Expression stringTest = pop(); 2507 js.Expression stringTest = pop();
2409 checkObject(input, relation); 2508 checkObject(input, relation, sourceInformation);
2410 js.Expression objectTest = pop(); 2509 js.Expression objectTest = pop();
2411 checkType(input, interceptor, type, negative: negative); 2510 checkType(input, interceptor, type, sourceInformation, negative: negative);
2412 String combiner = negative ? '||' : '&&'; 2511 String combiner = negative ? '||' : '&&';
2413 push(new js.Binary(negative ? '&&' : '||', 2512 push(new js.Binary(negative ? '&&' : '||',
2414 stringTest, 2513 stringTest,
2415 new js.Binary(combiner, objectTest, pop()))); 2514 new js.Binary(combiner, objectTest, pop())));
2416 } 2515 }
2417 2516
2418 void handleListOrSupertypeCheck(HInstruction input, 2517 void handleListOrSupertypeCheck(HInstruction input,
2419 HInstruction interceptor, 2518 HInstruction interceptor,
2420 DartType type, 2519 DartType type,
2520 SourceInformation sourceInformation,
2421 { bool negative: false }) { 2521 { bool negative: false }) {
2422 assert(!identical(type.element, compiler.stringClass) 2522 assert(!identical(type.element, compiler.stringClass)
2423 && !Elements.isStringOnlySupertype(type.element, compiler) 2523 && !Elements.isStringOnlySupertype(type.element, compiler)
2424 && !Elements.isNumberOrStringSupertype(type.element, compiler)); 2524 && !Elements.isNumberOrStringSupertype(type.element, compiler));
2425 String relation = negative ? '!==' : '==='; 2525 String relation = negative ? '!==' : '===';
2426 checkObject(input, relation); 2526 checkObject(input, relation, sourceInformation);
2427 js.Expression objectTest = pop(); 2527 js.Expression objectTest = pop();
2428 checkArray(input, relation); 2528 checkArray(input, relation);
2429 js.Expression arrayTest = pop(); 2529 js.Expression arrayTest = pop();
2430 checkType(input, interceptor, type, negative: negative); 2530 checkType(input, interceptor, type, sourceInformation, negative: negative);
2431 String combiner = negative ? '&&' : '||'; 2531 String combiner = negative ? '&&' : '||';
2432 push(new js.Binary(negative ? '||' : '&&', 2532 push(new js.Binary(negative ? '||' : '&&',
2433 objectTest, 2533 objectTest,
2434 new js.Binary(combiner, arrayTest, pop()))); 2534 new js.Binary(combiner, arrayTest, pop()))
2535 .withSourceInformation(sourceInformation));
2435 } 2536 }
2436 2537
2437 void visitIs(HIs node) { 2538 void visitIs(HIs node) {
2438 emitIs(node, "==="); 2539 emitIs(node, "===", node.sourceInformation);
2439 } 2540 }
2440 2541
2441 void visitIsViaInterceptor(HIsViaInterceptor node) { 2542 void visitIsViaInterceptor(HIsViaInterceptor node) {
2442 emitIsViaInterceptor(node, false); 2543 emitIsViaInterceptor(node, node.sourceInformation, negative: false);
2443 } 2544 }
2444 2545
2445 void emitIs(HIs node, String relation) { 2546 void emitIs(HIs node, String relation, SourceInformation sourceInformation) {
2446 DartType type = node.typeExpression; 2547 DartType type = node.typeExpression;
2447 registry.registerIsCheck(type); 2548 registry.registerIsCheck(type);
2448 HInstruction input = node.expression; 2549 HInstruction input = node.expression;
2449 2550
2450 // If this is changed to single == there are several places below that must 2551 // If this is changed to single == there are several places below that must
2451 // be changed to match. 2552 // be changed to match.
2452 assert(relation == '===' || relation == '!=='); 2553 assert(relation == '===' || relation == '!==');
2453 bool negative = relation == '!=='; 2554 bool negative = relation == '!==';
2454 2555
2455 if (node.isVariableCheck || node.isCompoundCheck) { 2556 if (node.isVariableCheck || node.isCompoundCheck) {
2456 use(node.checkCall); 2557 use(node.checkCall);
2457 if (negative) push(new js.Prefix('!', pop())); 2558 if (negative) push(new js.Prefix('!', pop()));
2458 } else { 2559 } else {
2459 assert(node.isRawCheck); 2560 assert(node.isRawCheck);
2460 HInstruction interceptor = node.interceptor; 2561 HInstruction interceptor = node.interceptor;
2461 ClassElement objectClass = compiler.objectClass; 2562 ClassElement objectClass = compiler.objectClass;
2462 Element element = type.element; 2563 Element element = type.element;
2463 if (element == compiler.nullClass) { 2564 if (element == compiler.nullClass) {
2464 if (negative) { 2565 if (negative) {
2465 checkNonNull(input); 2566 checkNonNull(input);
2466 } else { 2567 } else {
2467 checkNull(input); 2568 checkNull(input);
2468 } 2569 }
2469 } else if (identical(element, objectClass) || type.treatAsDynamic) { 2570 } else if (identical(element, objectClass) || type.treatAsDynamic) {
2470 // The constant folder also does this optimization, but we make 2571 // The constant folder also does this optimization, but we make
2471 // it safe by assuming it may have not run. 2572 // it safe by assuming it may have not run.
2472 push(newLiteralBool(!negative), node); 2573 push(newLiteralBool(!negative, sourceInformation));
2473 } else if (element == compiler.stringClass) { 2574 } else if (element == compiler.stringClass) {
2474 checkString(input, relation); 2575 checkString(input, relation, sourceInformation);
2475 attachLocationToLast(node);
2476 } else if (element == compiler.doubleClass) { 2576 } else if (element == compiler.doubleClass) {
2477 checkDouble(input, relation); 2577 checkDouble(input, relation, sourceInformation);
2478 attachLocationToLast(node);
2479 } else if (element == compiler.numClass) { 2578 } else if (element == compiler.numClass) {
2480 checkNum(input, relation); 2579 checkNum(input, relation, sourceInformation);
2481 attachLocationToLast(node);
2482 } else if (element == compiler.boolClass) { 2580 } else if (element == compiler.boolClass) {
2483 checkBool(input, relation); 2581 checkBool(input, relation, sourceInformation);
2484 attachLocationToLast(node);
2485 } else if (element == compiler.intClass) { 2582 } else if (element == compiler.intClass) {
2486 // The is check in the code tells us that it might not be an 2583 // The is check in the code tells us that it might not be an
2487 // int. So we do a typeof first to avoid possible 2584 // int. So we do a typeof first to avoid possible
2488 // deoptimizations on the JS engine due to the Math.floor check. 2585 // deoptimizations on the JS engine due to the Math.floor check.
2489 checkNum(input, relation); 2586 checkNum(input, relation, sourceInformation);
2490 js.Expression numTest = pop(); 2587 js.Expression numTest = pop();
2491 checkBigInt(input, relation); 2588 checkBigInt(input, relation, sourceInformation);
2492 push(new js.Binary(negative ? '||' : '&&', numTest, pop()), node); 2589 push(new js.Binary(negative ? '||' : '&&', numTest, pop())
2590 .withSourceInformation(sourceInformation));
2493 } else if (node.useInstanceOf) { 2591 } else if (node.useInstanceOf) {
2494 assert(interceptor == null); 2592 assert(interceptor == null);
2495 checkTypeViaInstanceof(input, type, negative); 2593 checkTypeViaInstanceof(input, type,
2496 attachLocationToLast(node); 2594 sourceInformation,
2595 negative: negative);
2497 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { 2596 } else if (Elements.isNumberOrStringSupertype(element, compiler)) {
2498 handleNumberOrStringSupertypeCheck( 2597 handleNumberOrStringSupertypeCheck(
2499 input, interceptor, type, negative: negative); 2598 input, interceptor, type,
2500 attachLocationToLast(node); 2599 sourceInformation,
2600 negative: negative);
2501 } else if (Elements.isStringOnlySupertype(element, compiler)) { 2601 } else if (Elements.isStringOnlySupertype(element, compiler)) {
2502 handleStringSupertypeCheck( 2602 handleStringSupertypeCheck(
2503 input, interceptor, type, negative: negative); 2603 input, interceptor, type,
2504 attachLocationToLast(node); 2604 sourceInformation,
2505 } else if (identical(element, compiler.listClass) 2605 negative: negative);
2506 || Elements.isListSupertype(element, compiler)) { 2606 } else if (identical(element, compiler.listClass) ||
2607 Elements.isListSupertype(element, compiler)) {
2507 handleListOrSupertypeCheck( 2608 handleListOrSupertypeCheck(
2508 input, interceptor, type, negative: negative); 2609 input, interceptor, type,
2509 attachLocationToLast(node); 2610 sourceInformation,
2611 negative: negative);
2510 } else if (type.isFunctionType) { 2612 } else if (type.isFunctionType) {
2511 checkType(input, interceptor, type, negative: negative); 2613 checkType(input, interceptor, type,
2512 attachLocationToLast(node); 2614 sourceInformation,
2615 negative: negative);
2513 } else if ((input.canBePrimitive(compiler) 2616 } else if ((input.canBePrimitive(compiler)
2514 && !input.canBePrimitiveArray(compiler)) 2617 && !input.canBePrimitiveArray(compiler))
2515 || input.canBeNull()) { 2618 || input.canBeNull()) {
2516 checkObject(input, relation); 2619 checkObject(input, relation, node.sourceInformation);
2517 js.Expression objectTest = pop(); 2620 js.Expression objectTest = pop();
2518 checkType(input, interceptor, type, negative: negative); 2621 checkType(input, interceptor, type,
2519 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()), node); 2622 sourceInformation,
2623 negative: negative);
2624 push(new js.Binary(negative ? '||' : '&&', objectTest, pop())
2625 .withSourceInformation(sourceInformation));
2520 } else { 2626 } else {
2521 checkType(input, interceptor, type, negative: negative); 2627 checkType(input, interceptor, type,
2522 attachLocationToLast(node); 2628 sourceInformation,
2629 negative: negative);
2523 } 2630 }
2524 } 2631 }
2525 } 2632 }
2526 2633
2527 void emitIsViaInterceptor(HIsViaInterceptor node, bool negative) { 2634 void emitIsViaInterceptor(HIsViaInterceptor node,
2528 checkTypeViaProperty(node.interceptor, node.typeExpression, negative); 2635 SourceInformation sourceInformation,
2529 attachLocationToLast(node); 2636 {bool negative: false}) {
2637 checkTypeViaProperty(node.interceptor, node.typeExpression,
2638 sourceInformation,
2639 negative: negative);
2530 } 2640 }
2531 2641
2532 js.Expression generateReceiverOrArgumentTypeTest( 2642 js.Expression generateReceiverOrArgumentTypeTest(
2533 HInstruction input, TypeMask checkedType) { 2643 HInstruction input, TypeMask checkedType) {
2534 ClassWorld classWorld = compiler.world; 2644 ClassWorld classWorld = compiler.world;
2535 TypeMask inputType = input.instructionType; 2645 TypeMask inputType = input.instructionType;
2536 // Figure out if it is beneficial to turn this into a null check. 2646 // Figure out if it is beneficial to turn this into a null check.
2537 // V8 generally prefers 'typeof' checks, but for integers and 2647 // V8 generally prefers 'typeof' checks, but for integers and
2538 // indexable primitives we cannot compile this test into a single 2648 // indexable primitives we cannot compile this test into a single
2539 // typeof check so the null check is cheaper. 2649 // typeof check so the null check is cheaper.
2540 bool isIntCheck = checkedType.containsOnlyInt(classWorld); 2650 bool isIntCheck = checkedType.containsOnlyInt(classWorld);
2541 bool turnIntoNumCheck = isIntCheck && input.isIntegerOrNull(compiler); 2651 bool turnIntoNumCheck = isIntCheck && input.isIntegerOrNull(compiler);
2542 bool turnIntoNullCheck = !turnIntoNumCheck 2652 bool turnIntoNullCheck = !turnIntoNumCheck
2543 && (checkedType.nullable() == inputType) 2653 && (checkedType.nullable() == inputType)
2544 && (isIntCheck 2654 && (isIntCheck
2545 || checkedType.satisfies(backend.jsIndexableClass, classWorld)); 2655 || checkedType.satisfies(backend.jsIndexableClass, classWorld));
2546 2656
2547 if (turnIntoNullCheck) { 2657 if (turnIntoNullCheck) {
2548 use(input); 2658 use(input);
2549 return new js.Binary("==", pop(), new js.LiteralNull()); 2659 return new js.Binary("==", pop(), new js.LiteralNull())
2660 .withSourceInformation(input.sourceInformation);
2550 } else if (isIntCheck && !turnIntoNumCheck) { 2661 } else if (isIntCheck && !turnIntoNumCheck) {
2551 // input is !int 2662 // input is !int
2552 checkBigInt(input, '!=='); 2663 checkBigInt(input, '!==', input.sourceInformation);
2553 return pop(); 2664 return pop();
2554 } else if (turnIntoNumCheck || checkedType.containsOnlyNum(classWorld)) { 2665 } else if (turnIntoNumCheck || checkedType.containsOnlyNum(classWorld)) {
2555 // input is !num 2666 // input is !num
2556 checkNum(input, '!=='); 2667 checkNum(input, '!==', input.sourceInformation);
2557 return pop(); 2668 return pop();
2558 } else if (checkedType.containsOnlyBool(classWorld)) { 2669 } else if (checkedType.containsOnlyBool(classWorld)) {
2559 // input is !bool 2670 // input is !bool
2560 checkBool(input, '!=='); 2671 checkBool(input, '!==', input.sourceInformation);
2561 return pop(); 2672 return pop();
2562 } else if (checkedType.containsOnlyString(classWorld)) { 2673 } else if (checkedType.containsOnlyString(classWorld)) {
2563 // input is !string 2674 // input is !string
2564 checkString(input, '!=='); 2675 checkString(input, '!==', input.sourceInformation);
2565 return pop(); 2676 return pop();
2566 } 2677 }
2567 compiler.internalError(input, 'Unexpected check.'); 2678 compiler.internalError(input, 'Unexpected check.');
2568 return null; 2679 return null;
2569 } 2680 }
2570 2681
2571 void visitTypeConversion(HTypeConversion node) { 2682 void visitTypeConversion(HTypeConversion node) {
2572 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) { 2683 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
2573 ClassWorld classWorld = compiler.world; 2684 ClassWorld classWorld = compiler.world;
2574 // An int check if the input is not int or null, is not 2685 // An int check if the input is not int or null, is not
(...skipping 10 matching lines...) Expand all
2585 generateThrowWithHelper('iae', node.checkedInput); 2696 generateThrowWithHelper('iae', node.checkedInput);
2586 } else if (node.isReceiverTypeCheck) { 2697 } else if (node.isReceiverTypeCheck) {
2587 use(node.checkedInput); 2698 use(node.checkedInput);
2588 String methodName = 2699 String methodName =
2589 backend.namer.invocationName(node.receiverTypeCheckSelector); 2700 backend.namer.invocationName(node.receiverTypeCheckSelector);
2590 js.Expression call = js.propertyCall(pop(), methodName, []); 2701 js.Expression call = js.propertyCall(pop(), methodName, []);
2591 pushStatement(new js.Return(call)); 2702 pushStatement(new js.Return(call));
2592 } 2703 }
2593 currentContainer = oldContainer; 2704 currentContainer = oldContainer;
2594 body = unwrapStatement(body); 2705 body = unwrapStatement(body);
2595 pushStatement(new js.If.noElse(test, body), node); 2706 pushStatement(new js.If.noElse(test, body)
2707 .withSourceInformation(node.sourceInformation));
2596 return; 2708 return;
2597 } 2709 }
2598 2710
2599 assert(node.isCheckedModeCheck || node.isCastTypeCheck); 2711 assert(node.isCheckedModeCheck || node.isCastTypeCheck);
2600 DartType type = node.typeExpression; 2712 DartType type = node.typeExpression;
2601 assert(type.kind != TypeKind.TYPEDEF); 2713 assert(type.kind != TypeKind.TYPEDEF);
2602 if (type.isFunctionType) { 2714 if (type.isFunctionType) {
2603 // TODO(5022): We currently generate $isFunction checks for 2715 // TODO(5022): We currently generate $isFunction checks for
2604 // function types. 2716 // function types.
2605 registry.registerIsCheck(compiler.functionClass.rawType); 2717 registry.registerIsCheck(compiler.functionClass.rawType);
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
2725 js.PropertyAccess accessHelper(String name) { 2837 js.PropertyAccess accessHelper(String name) {
2726 Element helper = backend.findHelper(name); 2838 Element helper = backend.findHelper(name);
2727 if (helper == null) { 2839 if (helper == null) {
2728 // For mocked-up tests. 2840 // For mocked-up tests.
2729 return js.js('(void 0).$name'); 2841 return js.js('(void 0).$name');
2730 } 2842 }
2731 registry.registerStaticUse(helper); 2843 registry.registerStaticUse(helper);
2732 return backend.emitter.staticFunctionAccess(helper); 2844 return backend.emitter.staticFunctionAccess(helper);
2733 } 2845 }
2734 } 2846 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698