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

Side by Side Diff: pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart

Issue 1761903002: dart2js cps: Keep interceptors in a separate field. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Rebase Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/js_backend/codegen/unsugar.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 library tree_ir_builder; 5 library tree_ir_builder;
6 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../constants/values.dart'; 8 import '../constants/values.dart';
9 import '../cps_ir/cps_ir_nodes.dart' as cps_ir; 9 import '../cps_ir/cps_ir_nodes.dart' as cps_ir;
10 import '../elements/elements.dart'; 10 import '../elements/elements.dart';
11 import 'package:js_ast/js_ast.dart' as js; 11 import 'package:js_ast/js_ast.dart' as js;
12 import '../js_backend/codegen/glue.dart';
12 13
13 import 'tree_ir_nodes.dart'; 14 import 'tree_ir_nodes.dart';
14 15
15 typedef Statement NodeCallback(Statement next); 16 typedef Statement NodeCallback(Statement next);
16 17
17 /** 18 /**
18 * Builder translates from CPS-based IR to direct-style Tree. 19 * Builder translates from CPS-based IR to direct-style Tree.
19 * 20 *
20 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced 21 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced
21 * non-exit continuation `Cont(v, body)` is translated into a direct-style call 22 * non-exit continuation `Cont(v, body)` is translated into a direct-style call
(...skipping 19 matching lines...) Expand all
41 * Block arguments are later replaced with data flow during the Tree-to-Tree 42 * Block arguments are later replaced with data flow during the Tree-to-Tree
42 * translation out of SSA. Jumps are eliminated during the Tree-to-Tree 43 * translation out of SSA. Jumps are eliminated during the Tree-to-Tree
43 * control-flow recognition. 44 * control-flow recognition.
44 * 45 *
45 * Otherwise, the output of Builder looks very much like the input. In 46 * Otherwise, the output of Builder looks very much like the input. In
46 * particular, intermediate values and blocks used for local control flow are 47 * particular, intermediate values and blocks used for local control flow are
47 * still all named. 48 * still all named.
48 */ 49 */
49 class Builder implements cps_ir.Visitor/*<NodeCallback|Node>*/ { 50 class Builder implements cps_ir.Visitor/*<NodeCallback|Node>*/ {
50 final InternalErrorFunction internalError; 51 final InternalErrorFunction internalError;
52 final Glue glue;
51 53
52 final Map<cps_ir.Primitive, Variable> primitive2variable = 54 final Map<cps_ir.Primitive, Variable> primitive2variable =
53 <cps_ir.Primitive, Variable>{}; 55 <cps_ir.Primitive, Variable>{};
54 final Map<cps_ir.MutableVariable, Variable> mutable2variable = 56 final Map<cps_ir.MutableVariable, Variable> mutable2variable =
55 <cps_ir.MutableVariable, Variable>{}; 57 <cps_ir.MutableVariable, Variable>{};
56 final Set<cps_ir.Constant> inlinedConstants = new Set<cps_ir.Constant>(); 58 final Set<cps_ir.Constant> inlinedConstants = new Set<cps_ir.Constant>();
57 59
58 // Continuations with more than one use are replaced with Tree labels. This 60 // Continuations with more than one use are replaced with Tree labels. This
59 // is the mapping from continuations to labels. 61 // is the mapping from continuations to labels.
60 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{}; 62 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{};
61 63
62 ExecutableElement currentElement; 64 ExecutableElement currentElement;
63 /// The 'this' Parameter for currentElement or the enclosing method. 65 /// The parameter to be translated to 'this'. This can either be the receiver
66 /// parameter, the interceptor parameter, or null if the method has neither.
64 cps_ir.Parameter thisParameter; 67 cps_ir.Parameter thisParameter;
65 cps_ir.Continuation returnContinuation; 68 cps_ir.Continuation returnContinuation;
66 69
67 Builder parent; 70 Builder(this.internalError, this.glue);
68
69 Builder(this.internalError, [this.parent]);
70
71 Builder createInnerBuilder() {
72 return new Builder(internalError, this);
73 }
74 71
75 /// Variable used in [buildPhiAssignments] as a temporary when swapping 72 /// Variable used in [buildPhiAssignments] as a temporary when swapping
76 /// variables. 73 /// variables.
77 Variable phiTempVar; 74 Variable phiTempVar;
78 75
79 Variable addMutableVariable(cps_ir.MutableVariable irVariable) { 76 Variable addMutableVariable(cps_ir.MutableVariable irVariable) {
80 assert(!mutable2variable.containsKey(irVariable)); 77 assert(!mutable2variable.containsKey(irVariable));
81 Variable variable = new Variable(currentElement, irVariable.hint); 78 Variable variable = new Variable(currentElement, irVariable.hint);
82 mutable2variable[irVariable] = variable; 79 mutable2variable[irVariable] = variable;
83 return variable; 80 return variable;
84 } 81 }
85 82
86 Variable getMutableVariable(cps_ir.MutableVariable mutableVariable) { 83 Variable getMutableVariable(cps_ir.MutableVariable mutableVariable) {
87 if (!mutable2variable.containsKey(mutableVariable)) {
88 return parent.getMutableVariable(mutableVariable)..isCaptured = true;
89 }
90 return mutable2variable[mutableVariable]; 84 return mutable2variable[mutableVariable];
91 } 85 }
92 86
93 VariableUse getMutableVariableUse( 87 VariableUse getMutableVariableUse(
94 cps_ir.Reference<cps_ir.MutableVariable> reference) { 88 cps_ir.Reference<cps_ir.MutableVariable> reference) {
95 Variable variable = getMutableVariable(reference.definition); 89 Variable variable = getMutableVariable(reference.definition);
96 return new VariableUse(variable); 90 return new VariableUse(variable);
97 } 91 }
98 92
99 /// Obtains the variable representing the given primitive. Returns null for 93 /// Obtains the variable representing the given primitive. Returns null for
(...skipping 21 matching lines...) Expand all
121 115
122 Expression getVariableUseOrNull( 116 Expression getVariableUseOrNull(
123 cps_ir.Reference<cps_ir.Primitive> reference) { 117 cps_ir.Reference<cps_ir.Primitive> reference) {
124 return reference == null ? null : getVariableUse(reference); 118 return reference == null ? null : getVariableUse(reference);
125 } 119 }
126 120
127 Label getLabel(cps_ir.Continuation cont) { 121 Label getLabel(cps_ir.Continuation cont) {
128 return labels.putIfAbsent(cont, () => new Label()); 122 return labels.putIfAbsent(cont, () => new Label());
129 } 123 }
130 124
131 Variable addFunctionParameter(cps_ir.Parameter parameter) {
132 return getVariable(parameter);
133 }
134
135 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { 125 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) {
136 currentElement = node.element; 126 currentElement = node.element;
137 if (parent != null) { 127 List<Variable> parameters = node.parameters.map(getVariable).toList();
138 // Local function's 'this' refers to enclosing method's 'this' 128 if (node.interceptorParameter != null) {
139 thisParameter = parent.thisParameter; 129 parameters.insert(0, getVariable(node.receiverParameter));
130 thisParameter = glue.methodUsesReceiverArgument(node.element)
131 ? node.interceptorParameter
132 : node.receiverParameter;
140 } else { 133 } else {
141 thisParameter = node.thisParameter; 134 thisParameter = node.receiverParameter;
142 } 135 }
143 List<Variable> parameters =
144 node.parameters.map(addFunctionParameter).toList();
145 returnContinuation = node.returnContinuation; 136 returnContinuation = node.returnContinuation;
146 phiTempVar = new Variable(node.element, null); 137 phiTempVar = new Variable(node.element, null);
147 Statement body = translateExpression(node.body); 138 Statement body = translateExpression(node.body);
148 return new FunctionDefinition(node.element, parameters, body); 139 return new FunctionDefinition(node.element, parameters, body);
149 } 140 }
150 141
151 /// Returns a list of variables corresponding to the arguments to a method 142 /// Returns a list of variables corresponding to the arguments to a method
152 /// call or similar construct. 143 /// call or similar construct.
153 /// 144 ///
154 /// The `readCount` for these variables will be incremented. 145 /// The `readCount` for these variables will be incremented.
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 getVariableUse(node.indexRef), 605 getVariableUse(node.indexRef),
615 getVariableUse(node.valueRef)); 606 getVariableUse(node.valueRef));
616 } 607 }
617 608
618 Expression visitInvokeStatic(cps_ir.InvokeStatic node) { 609 Expression visitInvokeStatic(cps_ir.InvokeStatic node) {
619 List<Expression> arguments = translateArguments(node.argumentRefs); 610 List<Expression> arguments = translateArguments(node.argumentRefs);
620 return new InvokeStatic(node.target, node.selector, arguments, 611 return new InvokeStatic(node.target, node.selector, arguments,
621 node.sourceInformation); 612 node.sourceInformation);
622 } 613 }
623 614
615 List<Expression> insertReceiverArgument(Expression receiver,
616 List<Expression> arguments) {
617 return new List<Expression>.generate(arguments.length + 1,
618 (n) => n == 0 ? receiver : arguments[n - 1],
619 growable: false);
620 }
621
624 Expression visitInvokeMethod(cps_ir.InvokeMethod node) { 622 Expression visitInvokeMethod(cps_ir.InvokeMethod node) {
625 if (node.callingConvention == cps_ir.CallingConvention.OneShotIntercepted) { 623 switch (node.callingConvention) {
626 List<Expression> arguments = new List.generate( 624 case cps_ir.CallingConvention.Normal:
627 1 + node.argumentRefs.length, 625 InvokeMethod invoke = new InvokeMethod(
628 (n) => getVariableUse(n == 0 ? node.receiverRef : node.argumentRefs[n - 1]), 626 getVariableUse(node.receiverRef),
629 growable: false); 627 node.selector,
630 return new OneShotInterceptor(node.selector, node.mask, arguments, 628 node.mask,
631 node.sourceInformation); 629 translateArguments(node.argumentRefs),
630 node.sourceInformation);
631 invoke.receiverIsNotNull = !node.receiver.type.isNullable;
632 return invoke;
633
634 case cps_ir.CallingConvention.Intercepted:
635 List<Expression> arguments = insertReceiverArgument(
636 getVariableUse(node.receiverRef),
637 translateArguments(node.argumentRefs));
638 InvokeMethod invoke = new InvokeMethod(
639 getVariableUse(node.interceptorRef),
640 node.selector,
641 node.mask,
642 arguments,
643 node.sourceInformation);
644 // Sometimes we know the Dart receiver is non-null because it has been
645 // refined, which implies that the JS receiver also can not be null at
646 // the use-site. Interceptors are not refined, so this information is
647 // not always available on the JS receiver.
648 // Also check the JS receiver's type, however, because sometimes we know
649 // an interceptor is non-null because it intercepts JSNull.
650 invoke.receiverIsNotNull =
651 !node.receiver.type.isNullable ||
652 !node.interceptor.type.isNullable;
653 return invoke;
654
655 case cps_ir.CallingConvention.DummyIntercepted:
656 List<Expression> arguments = insertReceiverArgument(
657 new Constant(new IntConstantValue(0)),
658 translateArguments(node.argumentRefs));
659 InvokeMethod invoke = new InvokeMethod(
660 getVariableUse(node.receiverRef),
661 node.selector,
662 node.mask,
663 arguments,
664 node.sourceInformation);
665 invoke.receiverIsNotNull = !node.receiver.type.isNullable;
666 return invoke;
667
668 case cps_ir.CallingConvention.OneShotIntercepted:
669 List<Expression> arguments = insertReceiverArgument(
670 getVariableUse(node.receiverRef),
671 translateArguments(node.argumentRefs));
672 return new OneShotInterceptor(
673 node.selector,
674 node.mask,
675 arguments,
676 node.sourceInformation);
632 } 677 }
633 InvokeMethod invoke = new InvokeMethod(
634 getVariableUse(node.receiverRef),
635 node.selector,
636 node.mask,
637 translateArguments(node.argumentRefs),
638 node.sourceInformation);
639 // Sometimes we know the Dart receiver is non-null because it has been
640 // refined, which implies that the JS receiver also can not be null at the
641 // use-site. Interceptors are not refined, so this information is not
642 // always available on the JS receiver.
643 // Also check the JS receiver's type, however, because sometimes we know an
644 // interceptor is non-null because it intercepts JSNull.
645 invoke.receiverIsNotNull =
646 !node.dartReceiver.type.isNullable ||
647 !node.receiver.type.isNullable;
648 return invoke;
649 } 678 }
650 679
651 Expression visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly node) { 680 Expression visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly node) {
652 Expression receiver = getVariableUse(node.receiverRef); 681 if (node.interceptorRef != null) {
653 List<Expression> arguments = translateArguments(node.argumentRefs); 682 return new InvokeMethodDirectly(getVariableUse(node.interceptorRef),
654 return new InvokeMethodDirectly(receiver, node.target, 683 node.target,
655 node.selector, arguments, node.sourceInformation); 684 node.selector,
685 insertReceiverArgument(getVariableUse(node.receiverRef),
686 translateArguments(node.argumentRefs)),
687 node.sourceInformation);
688 } else {
689 return new InvokeMethodDirectly(getVariableUse(node.receiverRef),
690 node.target,
691 node.selector,
692 translateArguments(node.argumentRefs),
693 node.sourceInformation);
694 }
656 } 695 }
657 696
658 Expression visitTypeCast(cps_ir.TypeCast node) { 697 Expression visitTypeCast(cps_ir.TypeCast node) {
659 Expression value = getVariableUse(node.valueRef); 698 Expression value = getVariableUse(node.valueRef);
660 List<Expression> typeArgs = translateArguments(node.typeArgumentRefs); 699 List<Expression> typeArgs = translateArguments(node.typeArgumentRefs);
661 return new TypeOperator(value, node.dartType, typeArgs, isTypeTest: false); 700 return new TypeOperator(value, node.dartType, typeArgs, isTypeTest: false);
662 } 701 }
663 702
664 Expression visitInvokeConstructor(cps_ir.InvokeConstructor node) { 703 Expression visitInvokeConstructor(cps_ir.InvokeConstructor node) {
665 List<Expression> arguments = translateArguments(node.argumentRefs); 704 List<Expression> arguments = translateArguments(node.argumentRefs);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 781
743 visitFunctionDefinition(cps_ir.FunctionDefinition node) { 782 visitFunctionDefinition(cps_ir.FunctionDefinition node) {
744 unexpectedNode(node); 783 unexpectedNode(node);
745 } 784 }
746 visitParameter(cps_ir.Parameter node) => unexpectedNode(node); 785 visitParameter(cps_ir.Parameter node) => unexpectedNode(node);
747 visitContinuation(cps_ir.Continuation node) => unexpectedNode(node); 786 visitContinuation(cps_ir.Continuation node) => unexpectedNode(node);
748 visitMutableVariable(cps_ir.MutableVariable node) => unexpectedNode(node); 787 visitMutableVariable(cps_ir.MutableVariable node) => unexpectedNode(node);
749 visitRethrow(cps_ir.Rethrow node) => unexpectedNode(node); 788 visitRethrow(cps_ir.Rethrow node) => unexpectedNode(node);
750 visitBoundsCheck(cps_ir.BoundsCheck node) => unexpectedNode(node); 789 visitBoundsCheck(cps_ir.BoundsCheck node) => unexpectedNode(node);
751 } 790 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/codegen/unsugar.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698