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

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

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