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

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

Issue 2305623004: Refactor how we read global-type-inference data from ssa (Closed)
Patch Set: fix copy/paste typo. Created 4 years, 3 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 import 'dart:collection'; 5 import 'dart:collection';
6 6
7 import 'package:js_runtime/shared/embedded_names.dart'; 7 import 'package:js_runtime/shared/embedded_names.dart';
8 8
9 import '../closure.dart'; 9 import '../closure.dart';
10 import '../common.dart'; 10 import '../common.dart';
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 /// Registry used to enqueue work during codegen, may be null to avoid 370 /// Registry used to enqueue work during codegen, may be null to avoid
371 /// enqueing any work. 371 /// enqueing any work.
372 // TODO(sigmund,johnniwinther): get rid of registry entirely. We should be 372 // TODO(sigmund,johnniwinther): get rid of registry entirely. We should be
373 // able to return the impact as a result after building and avoid enqueing 373 // able to return the impact as a result after building and avoid enqueing
374 // things here. Later the codegen task can decide whether to enqueue 374 // things here. Later the codegen task can decide whether to enqueue
375 // something. In the past this didn't matter as much because the SSA graph was 375 // something. In the past this didn't matter as much because the SSA graph was
376 // used only for codegen, but currently we want to experiment using it for 376 // used only for codegen, but currently we want to experiment using it for
377 // code-analysis too. 377 // code-analysis too.
378 final CodegenRegistry registry; 378 final CodegenRegistry registry;
379 final Compiler compiler; 379 final Compiler compiler;
380 final GlobalTypeInferenceResults inferenceResults;
380 final JavaScriptBackend backend; 381 final JavaScriptBackend backend;
381 final ConstantSystem constantSystem; 382 final ConstantSystem constantSystem;
382 final RuntimeTypes rti; 383 final RuntimeTypes rti;
383 384
384 SourceInformationBuilder sourceInformationBuilder; 385 SourceInformationBuilder sourceInformationBuilder;
385 386
386 bool inLazyInitializerExpression = false; 387 bool inLazyInitializerExpression = false;
387 388
388 // TODO(sigmund): make all comments /// instead of /* */ 389 // TODO(sigmund): make all comments /// instead of /* */
389 /* This field is used by the native handler. */ 390 /* This field is used by the native handler. */
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 this.target, 425 this.target,
425 this.resolvedAst, 426 this.resolvedAst,
426 this.registry, 427 this.registry,
427 JavaScriptBackend backend, 428 JavaScriptBackend backend,
428 this.nativeEmitter, 429 this.nativeEmitter,
429 SourceInformationStrategy sourceInformationFactory) 430 SourceInformationStrategy sourceInformationFactory)
430 : this.compiler = backend.compiler, 431 : this.compiler = backend.compiler,
431 this.infoReporter = backend.compiler.dumpInfoTask, 432 this.infoReporter = backend.compiler.dumpInfoTask,
432 this.backend = backend, 433 this.backend = backend,
433 this.constantSystem = backend.constantSystem, 434 this.constantSystem = backend.constantSystem,
434 this.rti = backend.rti { 435 this.rti = backend.rti,
436 this.inferenceResults = backend.compiler.globalInference.results {
435 assert(target.isImplementation); 437 assert(target.isImplementation);
436 graph.element = target; 438 graph.element = target;
437 sourceElementStack.add(target); 439 sourceElementStack.add(target);
438 sourceInformationBuilder = 440 sourceInformationBuilder =
439 sourceInformationFactory.createBuilderForContext(resolvedAst); 441 sourceInformationFactory.createBuilderForContext(resolvedAst);
440 graph.sourceInformation = 442 graph.sourceInformation =
441 sourceInformationBuilder.buildVariableDeclaration(); 443 sourceInformationBuilder.buildVariableDeclaration();
442 localsHandler = new LocalsHandler(this, target, null, compiler); 444 localsHandler = new LocalsHandler(this, target, null, compiler);
443 } 445 }
444 446
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 // Generative constructors of native classes should not be called directly 669 // Generative constructors of native classes should not be called directly
668 // and have an extra argument that causes problems with inlining. 670 // and have an extra argument that causes problems with inlining.
669 if (element.isGenerativeConstructor && 671 if (element.isGenerativeConstructor &&
670 backend.isNativeOrExtendsNative(element.enclosingClass)) { 672 backend.isNativeOrExtendsNative(element.enclosingClass)) {
671 return false; 673 return false;
672 } 674 }
673 675
674 // A generative constructor body is not seen by global analysis, 676 // A generative constructor body is not seen by global analysis,
675 // so we should not query for its type. 677 // so we should not query for its type.
676 if (!element.isGenerativeConstructorBody) { 678 if (!element.isGenerativeConstructorBody) {
677 if (compiler.globalInference.throwsAlways(element)) { 679 if (inferenceResults.throwsAlways(element)) {
678 isReachable = false; 680 isReachable = false;
679 return false; 681 return false;
680 } 682 }
681 } 683 }
682 684
683 return true; 685 return true;
684 } 686 }
685 687
686 bool doesNotContainCode() { 688 bool doesNotContainCode() {
687 // A function with size 1 does not contain any code. 689 // A function with size 1 does not contain any code.
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 806
805 bool get allInlinedFunctionsCalledOnce { 807 bool get allInlinedFunctionsCalledOnce {
806 return inliningStack.isEmpty || inliningStack.last.allFunctionsCalledOnce; 808 return inliningStack.isEmpty || inliningStack.last.allFunctionsCalledOnce;
807 } 809 }
808 810
809 bool isFunctionCalledOnce(Element element) { 811 bool isFunctionCalledOnce(Element element) {
810 if (element is ConstructorBodyElement) { 812 if (element is ConstructorBodyElement) {
811 // ConstructorBodyElements are not in the type inference graph. 813 // ConstructorBodyElements are not in the type inference graph.
812 return false; 814 return false;
813 } 815 }
814 return compiler.globalInference.isCalledOnce(element); 816 return inferenceResults.isCalledOnce(element);
815 } 817 }
816 818
817 bool isCalledOnce(Element element) { 819 bool isCalledOnce(Element element) {
818 return allInlinedFunctionsCalledOnce && isFunctionCalledOnce(element); 820 return allInlinedFunctionsCalledOnce && isFunctionCalledOnce(element);
819 } 821 }
820 822
821 inlinedFrom(ResolvedAst resolvedAst, f()) { 823 inlinedFrom(ResolvedAst resolvedAst, f()) {
822 Element element = resolvedAst.element; 824 Element element = resolvedAst.element;
823 assert(element is FunctionElement || element is VariableElement); 825 assert(element is FunctionElement || element is VariableElement);
824 return reporter.withCurrentElement(element.implementation, () { 826 return reporter.withCurrentElement(element.implementation, () {
(...skipping 1728 matching lines...) Expand 10 before | Expand all | Expand 10 after
2553 if (operand is HConstant) { 2555 if (operand is HConstant) {
2554 UnaryOperation operation = constantSystem.lookupUnary(operator); 2556 UnaryOperation operation = constantSystem.lookupUnary(operator);
2555 HConstant constant = operand; 2557 HConstant constant = operand;
2556 ConstantValue folded = operation.fold(constant.constant); 2558 ConstantValue folded = operation.fold(constant.constant);
2557 if (folded != null) { 2559 if (folded != null) {
2558 stack.add(graph.addConstant(folded, compiler)); 2560 stack.add(graph.addConstant(folded, compiler));
2559 return; 2561 return;
2560 } 2562 }
2561 } 2563 }
2562 2564
2563 pushInvokeDynamic( 2565 pushInvokeDynamic(node, elements.getSelector(node),
2564 node, elements.getSelector(node), elements.getTypeMask(node), [operand], 2566 inferenceResults.typeOfSend(node, elements), [operand],
2565 sourceInformation: sourceInformationBuilder.buildGeneric(node)); 2567 sourceInformation: sourceInformationBuilder.buildGeneric(node));
2566 } 2568 }
2567 2569
2568 @override 2570 @override
2569 void visitBinary(ast.Send node, ast.Node left, BinaryOperator operator, 2571 void visitBinary(ast.Send node, ast.Node left, BinaryOperator operator,
2570 ast.Node right, _) { 2572 ast.Node right, _) {
2571 handleBinary(node, left, right); 2573 handleBinary(node, left, right);
2572 } 2574 }
2573 2575
2574 @override 2576 @override
2575 void visitIndex(ast.Send node, ast.Node receiver, ast.Node index, _) { 2577 void visitIndex(ast.Send node, ast.Node receiver, ast.Node index, _) {
2576 generateDynamicSend(node); 2578 generateDynamicSend(node);
2577 } 2579 }
2578 2580
2579 @override 2581 @override
2580 void visitEquals(ast.Send node, ast.Node left, ast.Node right, _) { 2582 void visitEquals(ast.Send node, ast.Node left, ast.Node right, _) {
2581 handleBinary(node, left, right); 2583 handleBinary(node, left, right);
2582 } 2584 }
2583 2585
2584 @override 2586 @override
2585 void visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) { 2587 void visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) {
2586 handleBinary(node, left, right); 2588 handleBinary(node, left, right);
2587 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); 2589 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector);
2588 } 2590 }
2589 2591
2590 void handleBinary(ast.Send node, ast.Node left, ast.Node right) { 2592 void handleBinary(ast.Send node, ast.Node left, ast.Node right) {
2591 visitBinarySend(visitAndPop(left), visitAndPop(right), 2593 visitBinarySend(
2592 elements.getSelector(node), elements.getTypeMask(node), node, 2594 visitAndPop(left),
2595 visitAndPop(right),
2596 elements.getSelector(node),
2597 inferenceResults.typeOfSend(node, elements),
2598 node,
2593 sourceInformation: 2599 sourceInformation:
2594 sourceInformationBuilder.buildGeneric(node.selector)); 2600 sourceInformationBuilder.buildGeneric(node.selector));
2595 } 2601 }
2596 2602
2597 /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and 2603 /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and
2598 /// remove use of [location] for source information. 2604 /// remove use of [location] for source information.
2599 void visitBinarySend(HInstruction left, HInstruction right, Selector selector, 2605 void visitBinarySend(HInstruction left, HInstruction right, Selector selector,
2600 TypeMask mask, ast.Send send, 2606 TypeMask mask, ast.Send send,
2601 {SourceInformation sourceInformation}) { 2607 {SourceInformation sourceInformation}) {
2602 pushInvokeDynamic(send, selector, mask, [left, right], 2608 pushInvokeDynamic(send, selector, mask, [left, right],
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
2742 generateDeferredLoaderGet(node, getter, sourceInformation); 2748 generateDeferredLoaderGet(node, getter, sourceInformation);
2743 } else { 2749 } else {
2744 pushInvokeStatic(node, getter, <HInstruction>[], 2750 pushInvokeStatic(node, getter, <HInstruction>[],
2745 sourceInformation: sourceInformation); 2751 sourceInformation: sourceInformation);
2746 } 2752 }
2747 } 2753 }
2748 2754
2749 /// Generate a dynamic getter invocation. 2755 /// Generate a dynamic getter invocation.
2750 void generateDynamicGet(ast.Send node) { 2756 void generateDynamicGet(ast.Send node) {
2751 HInstruction receiver = generateInstanceSendReceiver(node); 2757 HInstruction receiver = generateInstanceSendReceiver(node);
2752 generateInstanceGetterWithCompiledReceiver( 2758 generateInstanceGetterWithCompiledReceiver(node, elements.getSelector(node),
2753 node, elements.getSelector(node), elements.getTypeMask(node), receiver); 2759 inferenceResults.typeOfSend(node, elements), receiver);
2754 } 2760 }
2755 2761
2756 /// Generate a closurization of the static or top level [function]. 2762 /// Generate a closurization of the static or top level [function].
2757 void generateStaticFunctionGet(ast.Send node, MethodElement function) { 2763 void generateStaticFunctionGet(ast.Send node, MethodElement function) {
2758 // TODO(5346): Try to avoid the need for calling [declaration] before 2764 // TODO(5346): Try to avoid the need for calling [declaration] before
2759 // creating an [HStatic]. 2765 // creating an [HStatic].
2760 SourceInformation sourceInformation = 2766 SourceInformation sourceInformation =
2761 sourceInformationBuilder.buildGet(node); 2767 sourceInformationBuilder.buildGet(node);
2762 push(new HStatic(function.declaration, backend.nonNullType) 2768 push(new HStatic(function.declaration, backend.nonNullType)
2763 ..sourceInformation = sourceInformation); 2769 ..sourceInformation = sourceInformation);
(...skipping 28 matching lines...) Expand all
2792 brancher.handleConditional( 2798 brancher.handleConditional(
2793 () { 2799 () {
2794 expression = visitAndPop(receiver); 2800 expression = visitAndPop(receiver);
2795 pushCheckNull(expression); 2801 pushCheckNull(expression);
2796 }, 2802 },
2797 () => stack.add(expression), 2803 () => stack.add(expression),
2798 () { 2804 () {
2799 generateInstanceGetterWithCompiledReceiver( 2805 generateInstanceGetterWithCompiledReceiver(
2800 node, 2806 node,
2801 elements.getSelector(node), 2807 elements.getSelector(node),
2802 elements.getTypeMask(node), 2808 inferenceResults.typeOfSend(node, elements),
2803 expression); 2809 expression);
2804 }); 2810 });
2805 } 2811 }
2806 2812
2807 @override 2813 @override
2808 pushCheckNull(HInstruction expression) { 2814 pushCheckNull(HInstruction expression) {
2809 push(new HIdentity( 2815 push(new HIdentity(
2810 expression, graph.addConstantNull(compiler), null, backend.boolType)); 2816 expression, graph.addConstantNull(compiler), null, backend.boolType));
2811 } 2817 }
2812 2818
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2863 void generateInstanceSetterWithCompiledReceiver( 2869 void generateInstanceSetterWithCompiledReceiver(
2864 ast.Send send, HInstruction receiver, HInstruction value, 2870 ast.Send send, HInstruction receiver, HInstruction value,
2865 {Selector selector, TypeMask mask, ast.Node location}) { 2871 {Selector selector, TypeMask mask, ast.Node location}) {
2866 assert(invariant(send == null ? location : send, 2872 assert(invariant(send == null ? location : send,
2867 send == null || Elements.isInstanceSend(send, elements), 2873 send == null || Elements.isInstanceSend(send, elements),
2868 message: "Unexpected instance setter" 2874 message: "Unexpected instance setter"
2869 "${send != null ? " element: ${elements[send]}" : ""}")); 2875 "${send != null ? " element: ${elements[send]}" : ""}"));
2870 if (selector == null) { 2876 if (selector == null) {
2871 assert(send != null); 2877 assert(send != null);
2872 selector = elements.getSelector(send); 2878 selector = elements.getSelector(send);
2873 if (mask == null) { 2879 mask ??= inferenceResults.typeOfSend(send, elements);
2874 mask = elements.getTypeMask(send);
2875 }
2876 } 2880 }
2877 if (location == null) { 2881 if (location == null) {
2878 assert(send != null); 2882 assert(send != null);
2879 location = send; 2883 location = send;
2880 } 2884 }
2881 assert(selector.isSetter); 2885 assert(selector.isSetter);
2882 pushInvokeDynamic(location, selector, mask, [receiver, value], 2886 pushInvokeDynamic(location, selector, mask, [receiver, value],
2883 sourceInformation: sourceInformationBuilder.buildAssignment(location)); 2887 sourceInformation: sourceInformationBuilder.buildAssignment(location));
2884 pop(); 2888 pop();
2885 stack.add(value); 2889 stack.add(value);
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
3137 } 3141 }
3138 3142
3139 /// Generate a dynamic method, getter or setter invocation. 3143 /// Generate a dynamic method, getter or setter invocation.
3140 void generateDynamicSend(ast.Send node) { 3144 void generateDynamicSend(ast.Send node) {
3141 HInstruction receiver = generateInstanceSendReceiver(node); 3145 HInstruction receiver = generateInstanceSendReceiver(node);
3142 _generateDynamicSend(node, receiver); 3146 _generateDynamicSend(node, receiver);
3143 } 3147 }
3144 3148
3145 void _generateDynamicSend(ast.Send node, HInstruction receiver) { 3149 void _generateDynamicSend(ast.Send node, HInstruction receiver) {
3146 Selector selector = elements.getSelector(node); 3150 Selector selector = elements.getSelector(node);
3147 TypeMask mask = elements.getTypeMask(node); 3151 TypeMask mask = inferenceResults.typeOfSend(node, elements);
3148 SourceInformation sourceInformation = 3152 SourceInformation sourceInformation =
3149 sourceInformationBuilder.buildCall(node, node.selector); 3153 sourceInformationBuilder.buildCall(node, node.selector);
3150 3154
3151 List<HInstruction> inputs = <HInstruction>[]; 3155 List<HInstruction> inputs = <HInstruction>[];
3152 inputs.add(receiver); 3156 inputs.add(receiver);
3153 addDynamicSendArgumentsToList(node, inputs); 3157 addDynamicSendArgumentsToList(node, inputs);
3154 3158
3155 pushInvokeDynamic(node, selector, mask, inputs, 3159 pushInvokeDynamic(node, selector, mask, inputs,
3156 sourceInformation: sourceInformation); 3160 sourceInformation: sourceInformation);
3157 if (selector.isSetter || selector.isIndexSet) { 3161 if (selector.isSetter || selector.isIndexSet) {
(...skipping 866 matching lines...) Expand 10 before | Expand all | Expand 10 after
4024 Elements.isFixedListConstructorCall(elements[send], send, compiler); 4028 Elements.isFixedListConstructorCall(elements[send], send, compiler);
4025 bool isGrowableListConstructorCall = 4029 bool isGrowableListConstructorCall =
4026 Elements.isGrowableListConstructorCall(elements[send], send, compiler); 4030 Elements.isGrowableListConstructorCall(elements[send], send, compiler);
4027 4031
4028 TypeMask computeType(element) { 4032 TypeMask computeType(element) {
4029 Element originalElement = elements[send]; 4033 Element originalElement = elements[send];
4030 if (isFixedListConstructorCall || 4034 if (isFixedListConstructorCall ||
4031 Elements.isFilledListConstructorCall( 4035 Elements.isFilledListConstructorCall(
4032 originalElement, send, compiler)) { 4036 originalElement, send, compiler)) {
4033 isFixedList = true; 4037 isFixedList = true;
4034 TypeMask inferred = 4038 TypeMask inferred = _inferredTypeOfNewList(send);
4035 TypeMaskFactory.inferredForNode(sourceElement, send, compiler);
4036 return inferred.containsAll(compiler.world) 4039 return inferred.containsAll(compiler.world)
4037 ? backend.fixedArrayType 4040 ? backend.fixedArrayType
4038 : inferred; 4041 : inferred;
4039 } else if (isGrowableListConstructorCall) { 4042 } else if (isGrowableListConstructorCall) {
4040 TypeMask inferred = 4043 TypeMask inferred = _inferredTypeOfNewList(send);
4041 TypeMaskFactory.inferredForNode(sourceElement, send, compiler);
4042 return inferred.containsAll(compiler.world) 4044 return inferred.containsAll(compiler.world)
4043 ? backend.extendableArrayType 4045 ? backend.extendableArrayType
4044 : inferred; 4046 : inferred;
4045 } else if (Elements.isConstructorOfTypedArraySubclass( 4047 } else if (Elements.isConstructorOfTypedArraySubclass(
4046 originalElement, compiler)) { 4048 originalElement, compiler)) {
4047 isFixedList = true; 4049 isFixedList = true;
4048 TypeMask inferred = 4050 TypeMask inferred = _inferredTypeOfNewList(send);
4049 TypeMaskFactory.inferredForNode(sourceElement, send, compiler);
4050 ClassElement cls = element.enclosingClass; 4051 ClassElement cls = element.enclosingClass;
4051 assert(backend.isNative(cls.thisType.element)); 4052 assert(backend.isNative(cls.thisType.element));
4052 return inferred.containsAll(compiler.world) 4053 return inferred.containsAll(compiler.world)
4053 ? new TypeMask.nonNullExact(cls.thisType.element, compiler.world) 4054 ? new TypeMask.nonNullExact(cls.thisType.element, compiler.world)
4054 : inferred; 4055 : inferred;
4055 } else if (element.isGenerativeConstructor) { 4056 } else if (element.isGenerativeConstructor) {
4056 ClassElement cls = element.enclosingClass; 4057 ClassElement cls = element.enclosingClass;
4057 if (cls.isAbstract) { 4058 if (cls.isAbstract) {
4058 // An error will be thrown. 4059 // An error will be thrown.
4059 return new TypeMask.nonNullEmpty(); 4060 return new TypeMask.nonNullEmpty();
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
4171 var constant = inputs[0]; 4172 var constant = inputs[0];
4172 int value = constant.constant.primitiveValue; 4173 int value = constant.constant.primitiveValue;
4173 if (0 <= value && value < 0x100000000) canThrow = false; 4174 if (0 <= value && value < 0x100000000) canThrow = false;
4174 } 4175 }
4175 HForeignCode foreign = new HForeignCode(code, elementType, inputs, 4176 HForeignCode foreign = new HForeignCode(code, elementType, inputs,
4176 nativeBehavior: behavior, 4177 nativeBehavior: behavior,
4177 throwBehavior: canThrow 4178 throwBehavior: canThrow
4178 ? native.NativeThrowBehavior.MAY 4179 ? native.NativeThrowBehavior.MAY
4179 : native.NativeThrowBehavior.NEVER); 4180 : native.NativeThrowBehavior.NEVER);
4180 push(foreign); 4181 push(foreign);
4181 if (compiler.globalInference.isFixedArrayCheckedForGrowable(send)) { 4182 if (inferenceResults.isFixedArrayCheckedForGrowable(send)) {
4182 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); 4183 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array');
4183 // We set the instruction as [canThrow] to avoid it being dead code. 4184 // We set the instruction as [canThrow] to avoid it being dead code.
4184 // We need a finer grained side effect. 4185 // We need a finer grained side effect.
4185 add(new HForeignCode(code, backend.nullType, [stack.last], 4186 add(new HForeignCode(code, backend.nullType, [stack.last],
4186 throwBehavior: native.NativeThrowBehavior.MAY)); 4187 throwBehavior: native.NativeThrowBehavior.MAY));
4187 } 4188 }
4188 } else if (isGrowableListConstructorCall) { 4189 } else if (isGrowableListConstructorCall) {
4189 push(buildLiteralList(<HInstruction>[])); 4190 push(buildLiteralList(<HInstruction>[]));
4190 stack.last.instructionType = elementType; 4191 stack.last.instructionType = elementType;
4191 } else { 4192 } else {
(...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after
4916 rhs = graph.addConstantInt(1, compiler); 4917 rhs = graph.addConstantInt(1, compiler);
4917 } else { 4918 } else {
4918 visit(arguments.head); 4919 visit(arguments.head);
4919 assert(arguments.tail.isEmpty); 4920 assert(arguments.tail.isEmpty);
4920 rhs = pop(); 4921 rhs = pop();
4921 } 4922 }
4922 visitBinarySend( 4923 visitBinarySend(
4923 receiver, 4924 receiver,
4924 rhs, 4925 rhs,
4925 elements.getOperatorSelectorInComplexSendSet(node), 4926 elements.getOperatorSelectorInComplexSendSet(node),
4926 elements.getOperatorTypeMaskInComplexSendSet(node), 4927 inferenceResults.typeOfOperator(node, elements),
4927 node, 4928 node,
4928 sourceInformation: 4929 sourceInformation:
4929 sourceInformationBuilder.buildGeneric(node.assignmentOperator)); 4930 sourceInformationBuilder.buildGeneric(node.assignmentOperator));
4930 } 4931 }
4931 4932
4932 void handleSuperSendSet(ast.SendSet node) { 4933 void handleSuperSendSet(ast.SendSet node) {
4933 Element element = elements[node]; 4934 Element element = elements[node];
4934 List<HInstruction> setterInputs = <HInstruction>[]; 4935 List<HInstruction> setterInputs = <HInstruction>[];
4935 void generateSuperSendSet() { 4936 void generateSuperSendSet() {
4936 Selector setterSelector = elements.getSelector(node); 4937 Selector setterSelector = elements.getSelector(node);
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
5280 HInstruction receiver = pop(); 5281 HInstruction receiver = pop();
5281 Link<ast.Node> arguments = node.arguments; 5282 Link<ast.Node> arguments = node.arguments;
5282 HInstruction index; 5283 HInstruction index;
5283 if (node.isIndex) { 5284 if (node.isIndex) {
5284 visit(arguments.head); 5285 visit(arguments.head);
5285 arguments = arguments.tail; 5286 arguments = arguments.tail;
5286 index = pop(); 5287 index = pop();
5287 } 5288 }
5288 5289
5289 pushInvokeDynamic(node, elements.getGetterSelectorInComplexSendSet(node), 5290 pushInvokeDynamic(node, elements.getGetterSelectorInComplexSendSet(node),
5290 elements.getGetterTypeMaskInComplexSendSet(node), [receiver, index]); 5291 inferenceResults.typeOfGetter(node, elements), [receiver, index]);
5291 HInstruction getterInstruction = pop(); 5292 HInstruction getterInstruction = pop();
5292 if (node.isIfNullAssignment) { 5293 if (node.isIfNullAssignment) {
5293 // Compile x[i] ??= e as: 5294 // Compile x[i] ??= e as:
5294 // t1 = x[i] 5295 // t1 = x[i]
5295 // if (t1 == null) 5296 // if (t1 == null)
5296 // t1 = x[i] = e; 5297 // t1 = x[i] = e;
5297 // result = t1 5298 // result = t1
5298 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); 5299 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
5299 brancher.handleIfNull(() => stack.add(getterInstruction), () { 5300 brancher.handleIfNull(() => stack.add(getterInstruction), () {
5300 visit(arguments.head); 5301 visit(arguments.head);
5301 HInstruction value = pop(); 5302 HInstruction value = pop();
5302 pushInvokeDynamic(node, elements.getSelector(node), 5303 pushInvokeDynamic(
5303 elements.getTypeMask(node), [receiver, index, value]); 5304 node,
5305 elements.getSelector(node),
5306 inferenceResults.typeOfSend(node, elements),
5307 [receiver, index, value]);
5304 pop(); 5308 pop();
5305 stack.add(value); 5309 stack.add(value);
5306 }); 5310 });
5307 } else { 5311 } else {
5308 handleComplexOperatorSend(node, getterInstruction, arguments); 5312 handleComplexOperatorSend(node, getterInstruction, arguments);
5309 HInstruction value = pop(); 5313 HInstruction value = pop();
5310 pushInvokeDynamic(node, elements.getSelector(node), 5314 pushInvokeDynamic(
5311 elements.getTypeMask(node), [receiver, index, value]); 5315 node,
5316 elements.getSelector(node),
5317 inferenceResults.typeOfSend(node, elements),
5318 [receiver, index, value]);
5312 pop(); 5319 pop();
5313 if (node.isPostfix) { 5320 if (node.isPostfix) {
5314 stack.add(getterInstruction); 5321 stack.add(getterInstruction);
5315 } else { 5322 } else {
5316 stack.add(value); 5323 stack.add(value);
5317 } 5324 }
5318 } 5325 }
5319 } 5326 }
5320 } 5327 }
5321 5328
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
5505 } 5512 }
5506 return; 5513 return;
5507 } 5514 }
5508 5515
5509 if (Elements.isInstanceSend(node, elements)) { 5516 if (Elements.isInstanceSend(node, elements)) {
5510 void generateAssignment(HInstruction receiver) { 5517 void generateAssignment(HInstruction receiver) {
5511 // desugars `e.x op= e2` to `e.x = e.x op e2` 5518 // desugars `e.x op= e2` to `e.x = e.x op e2`
5512 generateInstanceGetterWithCompiledReceiver( 5519 generateInstanceGetterWithCompiledReceiver(
5513 node, 5520 node,
5514 elements.getGetterSelectorInComplexSendSet(node), 5521 elements.getGetterSelectorInComplexSendSet(node),
5515 elements.getGetterTypeMaskInComplexSendSet(node), 5522 inferenceResults.typeOfGetter(node, elements),
5516 receiver); 5523 receiver);
5517 HInstruction getterInstruction = pop(); 5524 HInstruction getterInstruction = pop();
5518 if (node.isIfNullAssignment) { 5525 if (node.isIfNullAssignment) {
5519 SsaBranchBuilder brancher = 5526 SsaBranchBuilder brancher =
5520 new SsaBranchBuilder(this, compiler, node); 5527 new SsaBranchBuilder(this, compiler, node);
5521 brancher.handleIfNull(() => stack.add(getterInstruction), () { 5528 brancher.handleIfNull(() => stack.add(getterInstruction), () {
5522 visit(node.arguments.head); 5529 visit(node.arguments.head);
5523 generateInstanceSetterWithCompiledReceiver(node, receiver, pop()); 5530 generateInstanceSetterWithCompiledReceiver(node, receiver, pop());
5524 }); 5531 });
5525 } else { 5532 } else {
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after
5960 !link.isEmpty; 5967 !link.isEmpty;
5961 link = link.tail) { 5968 link = link.tail) {
5962 visit(link.head); 5969 visit(link.head);
5963 inputs.add(pop()); 5970 inputs.add(pop());
5964 } 5971 }
5965 instruction = buildLiteralList(inputs); 5972 instruction = buildLiteralList(inputs);
5966 add(instruction); 5973 add(instruction);
5967 instruction = setRtiIfNeeded(instruction, node); 5974 instruction = setRtiIfNeeded(instruction, node);
5968 } 5975 }
5969 5976
5970 TypeMask type = 5977 TypeMask type = _inferredTypeOfNewList(node);
5971 TypeMaskFactory.inferredForNode(sourceElement, node, compiler);
5972 if (!type.containsAll(compiler.world)) instruction.instructionType = type; 5978 if (!type.containsAll(compiler.world)) instruction.instructionType = type;
5973 stack.add(instruction); 5979 stack.add(instruction);
5974 } 5980 }
5975 5981
5982 _inferredTypeOfNewList(ast.Node node) =>
5983 inferenceResults.typeOfNewList(sourceElement, node) ??
5984 compiler.commonMasks.dynamicType;
5985
5976 visitConditional(ast.Conditional node) { 5986 visitConditional(ast.Conditional node) {
5977 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node); 5987 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler, node);
5978 brancher.handleConditional(() => visit(node.condition), 5988 brancher.handleConditional(() => visit(node.condition),
5979 () => visit(node.thenExpression), () => visit(node.elseExpression)); 5989 () => visit(node.thenExpression), () => visit(node.elseExpression));
5980 } 5990 }
5981 5991
5982 visitStringInterpolation(ast.StringInterpolation node) { 5992 visitStringInterpolation(ast.StringInterpolation node) {
5983 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); 5993 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node);
5984 stringBuilder.visit(node); 5994 stringBuilder.visit(node);
5985 stack.add(stringBuilder.result); 5995 stack.add(stringBuilder.result);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
6059 visit(node.expression); 6069 visit(node.expression);
6060 HInstruction expression = pop(); 6070 HInstruction expression = pop();
6061 pushInvokeStatic(node, helpers.streamIteratorConstructor, 6071 pushInvokeStatic(node, helpers.streamIteratorConstructor,
6062 [expression, graph.addConstantNull(compiler)]); 6072 [expression, graph.addConstantNull(compiler)]);
6063 streamIterator = pop(); 6073 streamIterator = pop();
6064 6074
6065 void buildInitializer() {} 6075 void buildInitializer() {}
6066 6076
6067 HInstruction buildCondition() { 6077 HInstruction buildCondition() {
6068 Selector selector = Selectors.moveNext; 6078 Selector selector = Selectors.moveNext;
6069 TypeMask mask = elements.getMoveNextTypeMask(node); 6079 TypeMask mask = inferenceResults.typeOfIteratorMoveNext(node, elements);
6070 pushInvokeDynamic(node, selector, mask, [streamIterator]); 6080 pushInvokeDynamic(node, selector, mask, [streamIterator]);
6071 HInstruction future = pop(); 6081 HInstruction future = pop();
6072 push(new HAwait(future, 6082 push(new HAwait(future,
6073 new TypeMask.subclass(coreClasses.objectClass, compiler.world))); 6083 new TypeMask.subclass(coreClasses.objectClass, compiler.world)));
6074 return popBoolified(); 6084 return popBoolified();
6075 } 6085 }
6076 6086
6077 void buildBody() { 6087 void buildBody() {
6078 Selector call = Selectors.current; 6088 Selector call = Selectors.current;
6079 TypeMask callMask = elements.getCurrentTypeMask(node); 6089 TypeMask callMask =
6090 inferenceResults.typeOfIteratorCurrent(node, elements);
6080 pushInvokeDynamic(node, call, callMask, [streamIterator]); 6091 pushInvokeDynamic(node, call, callMask, [streamIterator]);
6081 6092
6082 ast.Node identifier = node.declaredIdentifier; 6093 ast.Node identifier = node.declaredIdentifier;
6083 Element variable = elements.getForInVariable(node); 6094 Element variable = elements.getForInVariable(node);
6084 Selector selector = elements.getSelector(identifier); 6095 Selector selector = elements.getSelector(identifier);
6085 TypeMask mask = elements.getTypeMask(identifier);
6086
6087 HInstruction value = pop(); 6096 HInstruction value = pop();
6088 if (identifier.asSend() != null && 6097 if (identifier.asSend() != null &&
6089 Elements.isInstanceSend(identifier, elements)) { 6098 Elements.isInstanceSend(identifier, elements)) {
6099 TypeMask mask = inferenceResults.typeOfSend(identifier, elements);
6090 HInstruction receiver = generateInstanceSendReceiver(identifier); 6100 HInstruction receiver = generateInstanceSendReceiver(identifier);
6091 assert(receiver != null); 6101 assert(receiver != null);
6092 generateInstanceSetterWithCompiledReceiver(null, receiver, value, 6102 generateInstanceSetterWithCompiledReceiver(null, receiver, value,
6093 selector: selector, mask: mask, location: identifier); 6103 selector: selector, mask: mask, location: identifier);
6094 } else { 6104 } else {
6095 generateNonInstanceSetter(null, variable, value, location: identifier); 6105 generateNonInstanceSetter(null, variable, value, location: identifier);
6096 } 6106 }
6097 pop(); // Pop the value pushed by the setter call. 6107 pop(); // Pop the value pushed by the setter call.
6098 6108
6099 visit(node.body); 6109 visit(node.body);
6100 } 6110 }
6101 6111
6102 void buildUpdate() {} 6112 void buildUpdate() {}
6103 ;
6104 6113
6105 buildProtectedByFinally(() { 6114 buildProtectedByFinally(() {
6106 handleLoop( 6115 handleLoop(
6107 node, buildInitializer, buildCondition, buildUpdate, buildBody); 6116 node, buildInitializer, buildCondition, buildUpdate, buildBody);
6108 }, () { 6117 }, () {
6109 pushInvokeDynamic(node, Selectors.cancel, null, [streamIterator]); 6118 pushInvokeDynamic(node, Selectors.cancel, null, [streamIterator]);
6110 push(new HAwait(pop(), 6119 push(new HAwait(pop(),
6111 new TypeMask.subclass(coreClasses.objectClass, compiler.world))); 6120 new TypeMask.subclass(coreClasses.objectClass, compiler.world)));
6112 pop(); 6121 pop();
6113 }); 6122 });
6114 } 6123 }
6115 6124
6116 visitSyncForIn(ast.SyncForIn node) { 6125 visitSyncForIn(ast.SyncForIn node) {
6117 // The 'get iterator' selector for this node has the inferred receiver type. 6126 // The 'get iterator' selector for this node has the inferred receiver type.
6118 // If the receiver supports JavaScript indexing we generate an indexing loop 6127 // If the receiver supports JavaScript indexing we generate an indexing loop
6119 // instead of allocating an iterator object. 6128 // instead of allocating an iterator object.
6120 6129
6121 // This scheme recognizes for-in on direct lists. It does not recognize all 6130 // This scheme recognizes for-in on direct lists. It does not recognize all
6122 // uses of ArrayIterator. They still occur when the receiver is an Iterable 6131 // uses of ArrayIterator. They still occur when the receiver is an Iterable
6123 // with a `get iterator` method that delegate to another Iterable and the 6132 // with a `get iterator` method that delegate to another Iterable and the
6124 // method is inlined. We would require full scalar replacement in that 6133 // method is inlined. We would require full scalar replacement in that
6125 // case. 6134 // case.
6126 6135
6127 TypeMask mask = elements.getIteratorTypeMask(node); 6136 TypeMask mask = inferenceResults.typeOfIterator(node, elements);
6128 6137
6129 ClassWorld classWorld = compiler.world; 6138 ClassWorld classWorld = compiler.world;
6130 if (mask != null && 6139 if (mask != null &&
6131 mask.satisfies(helpers.jsIndexableClass, classWorld) && 6140 mask.satisfies(helpers.jsIndexableClass, classWorld) &&
6132 // String is indexable but not iterable. 6141 // String is indexable but not iterable.
6133 !mask.satisfies(helpers.jsStringClass, classWorld)) { 6142 !mask.satisfies(helpers.jsStringClass, classWorld)) {
6134 return buildSyncForInIndexable(node, mask); 6143 return buildSyncForInIndexable(node, mask);
6135 } 6144 }
6136 buildSyncForInIterator(node); 6145 buildSyncForInIterator(node);
6137 } 6146 }
6138 6147
6139 buildSyncForInIterator(ast.SyncForIn node) { 6148 buildSyncForInIterator(ast.SyncForIn node) {
6140 // Generate a structure equivalent to: 6149 // Generate a structure equivalent to:
6141 // Iterator<E> $iter = <iterable>.iterator; 6150 // Iterator<E> $iter = <iterable>.iterator;
6142 // while ($iter.moveNext()) { 6151 // while ($iter.moveNext()) {
6143 // <declaredIdentifier> = $iter.current; 6152 // <declaredIdentifier> = $iter.current;
6144 // <body> 6153 // <body>
6145 // } 6154 // }
6146 6155
6147 // The iterator is shared between initializer, condition and body. 6156 // The iterator is shared between initializer, condition and body.
6148 HInstruction iterator; 6157 HInstruction iterator;
6149 6158
6150 void buildInitializer() { 6159 void buildInitializer() {
6151 Selector selector = Selectors.iterator; 6160 Selector selector = Selectors.iterator;
6152 TypeMask mask = elements.getIteratorTypeMask(node); 6161 TypeMask mask = inferenceResults.typeOfIterator(node, elements);
6153 visit(node.expression); 6162 visit(node.expression);
6154 HInstruction receiver = pop(); 6163 HInstruction receiver = pop();
6155 pushInvokeDynamic(node, selector, mask, [receiver]); 6164 pushInvokeDynamic(node, selector, mask, [receiver]);
6156 iterator = pop(); 6165 iterator = pop();
6157 } 6166 }
6158 6167
6159 HInstruction buildCondition() { 6168 HInstruction buildCondition() {
6160 Selector selector = Selectors.moveNext; 6169 Selector selector = Selectors.moveNext;
6161 TypeMask mask = elements.getMoveNextTypeMask(node); 6170 TypeMask mask = inferenceResults.typeOfIteratorMoveNext(node, elements);
6162 pushInvokeDynamic(node, selector, mask, [iterator]); 6171 pushInvokeDynamic(node, selector, mask, [iterator]);
6163 return popBoolified(); 6172 return popBoolified();
6164 } 6173 }
6165 6174
6166 void buildBody() { 6175 void buildBody() {
6167 Selector call = Selectors.current; 6176 Selector call = Selectors.current;
6168 TypeMask mask = elements.getCurrentTypeMask(node); 6177 TypeMask mask = inferenceResults.typeOfIteratorCurrent(node, elements);
6169 pushInvokeDynamic(node, call, mask, [iterator]); 6178 pushInvokeDynamic(node, call, mask, [iterator]);
6170 buildAssignLoopVariable(node, pop()); 6179 buildAssignLoopVariable(node, pop());
6171 visit(node.body); 6180 visit(node.body);
6172 } 6181 }
6173 6182
6174 handleLoop(node, buildInitializer, buildCondition, () {}, buildBody); 6183 handleLoop(node, buildInitializer, buildCondition, () {}, buildBody);
6175 } 6184 }
6176 6185
6177 buildAssignLoopVariable(ast.ForIn node, HInstruction value) { 6186 buildAssignLoopVariable(ast.ForIn node, HInstruction value) {
6178 ast.Node identifier = node.declaredIdentifier; 6187 ast.Node identifier = node.declaredIdentifier;
6179 Element variable = elements.getForInVariable(node); 6188 Element variable = elements.getForInVariable(node);
6180 Selector selector = elements.getSelector(identifier); 6189 Selector selector = elements.getSelector(identifier);
6181 TypeMask mask = elements.getTypeMask(identifier);
6182 6190
6183 if (identifier.asSend() != null && 6191 if (identifier.asSend() != null &&
6184 Elements.isInstanceSend(identifier, elements)) { 6192 Elements.isInstanceSend(identifier, elements)) {
6193 TypeMask mask = inferenceResults.typeOfSend(identifier, elements);
6185 HInstruction receiver = generateInstanceSendReceiver(identifier); 6194 HInstruction receiver = generateInstanceSendReceiver(identifier);
6186 assert(receiver != null); 6195 assert(receiver != null);
6187 generateInstanceSetterWithCompiledReceiver(null, receiver, value, 6196 generateInstanceSetterWithCompiledReceiver(null, receiver, value,
6188 selector: selector, mask: mask, location: identifier); 6197 selector: selector, mask: mask, location: identifier);
6189 } else { 6198 } else {
6190 generateNonInstanceSetter(null, variable, value, location: identifier); 6199 generateNonInstanceSetter(null, variable, value, location: identifier);
6191 } 6200 }
6192 pop(); // Discard the value pushed by the setter call. 6201 pop(); // Discard the value pushed by the setter call.
6193 } 6202 }
6194 6203
(...skipping 1350 matching lines...) Expand 10 before | Expand all | Expand 10 after
7545 const _LoopTypeVisitor(); 7554 const _LoopTypeVisitor();
7546 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; 7555 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP;
7547 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; 7556 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP;
7548 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; 7557 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP;
7549 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; 7558 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP;
7550 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; 7559 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
7551 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; 7560 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
7552 int visitSwitchStatement(ast.SwitchStatement node) => 7561 int visitSwitchStatement(ast.SwitchStatement node) =>
7553 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; 7562 HLoopBlockInformation.SWITCH_CONTINUE_LOOP;
7554 } 7563 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/no_such_method_registry.dart ('k') | pkg/compiler/lib/src/ssa/builder_kernel.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698