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

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

Issue 1375213003: dart2js cps: Maintain parent pointers instead of recomputing them. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Rebase Created 5 years, 2 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 library dart2js.unsugar_cps; 1 library dart2js.unsugar_cps;
2 2
3 import '../../cps_ir/cps_ir_nodes.dart'; 3 import '../../cps_ir/cps_ir_nodes.dart';
4 4
5 import '../../cps_ir/optimizers.dart' show ParentVisitor, Pass; 5 import '../../cps_ir/optimizers.dart' show ParentVisitor, Pass;
6 import '../../constants/values.dart'; 6 import '../../constants/values.dart';
7 import '../../elements/elements.dart'; 7 import '../../elements/elements.dart';
8 import '../../js_backend/codegen/glue.dart'; 8 import '../../js_backend/codegen/glue.dart';
9 import '../../universe/selector.dart' show Selector; 9 import '../../universe/selector.dart' show Selector;
10 import '../../cps_ir/cps_ir_builder.dart' show ThisParameterLocal; 10 import '../../cps_ir/cps_ir_builder.dart' show ThisParameterLocal;
11 import '../../cps_ir/cps_fragment.dart';
11 12
12 class ExplicitReceiverParameterEntity implements Local { 13 class ExplicitReceiverParameterEntity implements Local {
13 String get name => 'receiver'; 14 String get name => 'receiver';
14 final ExecutableElement executableContext; 15 final ExecutableElement executableContext;
15 ExplicitReceiverParameterEntity(this.executableContext); 16 ExplicitReceiverParameterEntity(this.executableContext);
16 toString() => 'ExplicitReceiverParameterEntity($executableContext)'; 17 toString() => 'ExplicitReceiverParameterEntity($executableContext)';
17 } 18 }
18 19
19 /// Suggested name for an interceptor. 20 /// Suggested name for an interceptor.
20 class InterceptorEntity extends Entity { 21 class InterceptorEntity extends Entity {
21 Entity interceptedVariable; 22 Entity interceptedVariable;
22 23
23 InterceptorEntity(this.interceptedVariable); 24 InterceptorEntity(this.interceptedVariable);
24 25
25 String get name => interceptedVariable.name + '_'; 26 String get name => interceptedVariable.name + '_';
26 } 27 }
27 28
28
29 /// Rewrites the initial CPS IR to make Dart semantics explicit and inserts 29 /// Rewrites the initial CPS IR to make Dart semantics explicit and inserts
30 /// special nodes that respect JavaScript behavior. 30 /// special nodes that respect JavaScript behavior.
31 /// 31 ///
32 /// Performs the following rewrites: 32 /// Performs the following rewrites:
33 /// - Add interceptors at call sites that use interceptor calling convention. 33 /// - Add interceptors at call sites that use interceptor calling convention.
34 /// - Add explicit receiver argument for methods that are called in interceptor 34 /// - Add explicit receiver argument for methods that are called in interceptor
35 /// calling convention. 35 /// calling convention.
36 /// - Convert two-parameter exception handlers to one-parameter ones. 36 /// - Convert two-parameter exception handlers to one-parameter ones.
37 class UnsugarVisitor extends RecursiveVisitor implements Pass { 37 class UnsugarVisitor extends TrampolineRecursiveVisitor implements Pass {
38 Glue _glue; 38 Glue _glue;
39 ParentVisitor _parentVisitor = new ParentVisitor();
40 39
41 Parameter thisParameter; 40 Parameter thisParameter;
42 Parameter explicitReceiverParameter; 41 Parameter explicitReceiverParameter;
43 42
44 // In a catch block, rethrow implicitly throws the block's exception 43 // In a catch block, rethrow implicitly throws the block's exception
45 // parameter. This is the exception parameter when nested in a catch 44 // parameter. This is the exception parameter when nested in a catch
46 // block and null otherwise. 45 // block and null otherwise.
47 Parameter _exceptionParameter = null; 46 Parameter _exceptionParameter = null;
48 47
49 UnsugarVisitor(this._glue); 48 UnsugarVisitor(this._glue);
(...skipping 15 matching lines...) Expand all
65 function.parameters.length == 1 && 64 function.parameters.length == 1 &&
66 !_glue.operatorEqHandlesNullArgument(function.element)) { 65 !_glue.operatorEqHandlesNullArgument(function.element)) {
67 // Insert the null check that the language semantics requires us to 66 // Insert the null check that the language semantics requires us to
68 // perform before calling operator ==. 67 // perform before calling operator ==.
69 insertEqNullCheck(function); 68 insertEqNullCheck(function);
70 } 69 }
71 70
72 if (inInterceptedMethod) { 71 if (inInterceptedMethod) {
73 ThisParameterLocal holder = thisParameter.hint; 72 ThisParameterLocal holder = thisParameter.hint;
74 explicitReceiverParameter = new Parameter( 73 explicitReceiverParameter = new Parameter(
75 new ExplicitReceiverParameterEntity( 74 new ExplicitReceiverParameterEntity(holder.executableContext));
76 holder.executableContext)); 75 explicitReceiverParameter.parent = function;
77 function.parameters.insert(0, explicitReceiverParameter); 76 function.parameters.insert(0, explicitReceiverParameter);
78 } 77 }
79 78
80 // Set all parent pointers.
81 _parentVisitor.visit(function);
82
83 if (inInterceptedMethod && methodUsesReceiverArgument(function.element)) { 79 if (inInterceptedMethod && methodUsesReceiverArgument(function.element)) {
84 explicitReceiverParameter.substituteFor(thisParameter); 80 explicitReceiverParameter.substituteFor(thisParameter);
85 } 81 }
86 82
87 visit(function); 83 visit(function);
88 } 84 }
89 85
90 Constant get trueConstant { 86 Constant get trueConstant {
91 return new Constant(new TrueConstantValue()); 87 return new Constant(new TrueConstantValue());
92 } 88 }
93 89
94 Constant get falseConstant { 90 Constant get falseConstant {
95 return new Constant(new FalseConstantValue()); 91 return new Constant(new FalseConstantValue());
96 } 92 }
97 93
98 Constant get nullConstant { 94 Constant get nullConstant {
99 return new Constant(new NullConstantValue()); 95 return new Constant(new NullConstantValue());
100 } 96 }
101 97
102 void insertLetPrim(Primitive primitive, Expression node) { 98 void insertLetPrim(Primitive primitive, Expression node) {
103 LetPrim let = new LetPrim(primitive); 99 LetPrim let = new LetPrim(primitive);
104 InteriorNode parent = node.parent; 100 let.insertAbove(node);
105 parent.body = let;
106 let.body = node;
107 node.parent = let;
108 let.parent = parent;
109 } 101 }
110 102
111 void insertEqNullCheck(FunctionDefinition function) { 103 void insertEqNullCheck(FunctionDefinition function) {
112 // Replace 104 // Replace
113 // 105 //
114 // body; 106 // body;
115 // 107 //
116 // with 108 // with
117 // 109 //
118 // if (identical(arg, null)) 110 // if (identical(arg, null))
119 // return false; 111 // return false;
120 // else 112 // else
121 // body; 113 // body;
122 // 114 //
123 Continuation originalBody = new Continuation(<Parameter>[]); 115 CpsFragment cps = new CpsFragment();
124 originalBody.body = function.body; 116 Primitive isNull = cps.applyBuiltin(
125
126 Continuation returnFalse = new Continuation(<Parameter>[]);
127 Primitive falsePrimitive = falseConstant;
128 returnFalse.body =
129 new LetPrim(falsePrimitive,
130 new InvokeContinuation(
131 function.returnContinuation, <Primitive>[falsePrimitive]));
132
133 Primitive nullPrimitive = nullConstant;
134 Primitive test = new ApplyBuiltinOperator(
135 BuiltinOperator.Identical, 117 BuiltinOperator.Identical,
136 <Primitive>[function.parameters.single, nullPrimitive], 118 <Primitive>[function.parameters.single, cps.makeNull()]);
137 function.parameters.single.sourceInformation); 119 CpsFragment trueBranch = cps.ifTruthy(isNull);
138 120 trueBranch.invokeContinuation(function.returnContinuation,
139 Expression newBody = 121 <Primitive>[trueBranch.makeFalse()]);
140 new LetCont.many(<Continuation>[returnFalse, originalBody], 122 cps.insertAbove(function.body);
141 new LetPrim(nullPrimitive,
142 new LetPrim(test,
143 new Branch.loose(test, returnFalse, originalBody))));
144 function.body = newBody;
145 } 123 }
146 124
147 /// Insert a static call to [function] at the point of [node] with result 125 /// Insert a static call to [function] at the point of [node] with result
148 /// [result]. 126 /// [result].
149 /// 127 ///
150 /// Rewrite [node] to 128 /// Rewrite [node] to
151 /// 129 ///
152 /// let cont continuation(result) = node 130 /// let cont continuation(result) = node
153 /// in invoke function arguments continuation 131 /// in invoke function arguments continuation
154 void insertStaticCall(FunctionElement function, List<Primitive> arguments, 132 void insertStaticCall(FunctionElement function, List<Primitive> arguments,
155 Parameter result, 133 Parameter result, Expression node) {
156 Expression node) {
157 InteriorNode parent = node.parent; 134 InteriorNode parent = node.parent;
158 Continuation continuation = new Continuation([result]); 135 Continuation continuation = new Continuation([result]);
159 continuation.body = node;
160 _parentVisitor.processContinuation(continuation);
161 136
162 Selector selector = new Selector.fromElement(function); 137 Selector selector = new Selector.fromElement(function);
163 // TODO(johnniwinther): Come up with an implementation of SourceInformation 138 // TODO(johnniwinther): Come up with an implementation of SourceInformation
164 // for calls such as this one that don't appear in the original source. 139 // for calls such as this one that don't appear in the original source.
165 InvokeStatic invoke = new InvokeStatic( 140 InvokeStatic invoke = new InvokeStatic(
166 function, selector, arguments, continuation, null); 141 function, selector, arguments, continuation, null);
167 _parentVisitor.processInvokeStatic(invoke);
168 142
169 LetCont letCont = new LetCont(continuation, invoke); 143 LetCont letCont = new LetCont(continuation, invoke);
170 _parentVisitor.processLetCont(letCont);
171 144
172 parent.body = letCont; 145 parent.body = letCont;
173 letCont.parent = parent; 146 letCont.parent = parent;
147 continuation.body = node;
148 node.parent = continuation;
174 } 149 }
175 150
176 @override 151 @override
177 Expression traverseLetHandler(LetHandler node) { 152 Expression traverseLetHandler(LetHandler node) {
178 assert(node.handler.parameters.length == 2); 153 assert(node.handler.parameters.length == 2);
179 Parameter previousExceptionParameter = _exceptionParameter; 154 Parameter previousExceptionParameter = _exceptionParameter;
180 155
181 // BEFORE: Handlers have two parameters, exception and stack trace. 156 // BEFORE: Handlers have two parameters, exception and stack trace.
182 // AFTER: Handlers have a single parameter, which is unwrapped to get 157 // AFTER: Handlers have a single parameter, which is unwrapped to get
183 // the exception and stack trace. 158 // the exception and stack trace.
(...skipping 19 matching lines...) Expand all
203 node.handler.parameters.removeLast(); 178 node.handler.parameters.removeLast();
204 179
205 visit(node.handler); 180 visit(node.handler);
206 _exceptionParameter = previousExceptionParameter; 181 _exceptionParameter = previousExceptionParameter;
207 182
208 return node.body; 183 return node.body;
209 } 184 }
210 185
211 processThrow(Throw node) { 186 processThrow(Throw node) {
212 // The subexpression of throw is wrapped in the JavaScript output. 187 // The subexpression of throw is wrapped in the JavaScript output.
213 Parameter value = new Parameter(null); 188 Parameter wrappedException = new Parameter(null);
214 insertStaticCall(_glue.getWrapExceptionHelper(), [node.value.definition], 189 insertStaticCall(_glue.getWrapExceptionHelper(), [node.value.definition],
215 value, node); 190 wrappedException, node);
216 node.value.unlink(); 191 node.value.changeTo(wrappedException);
217 node.value = new Reference<Primitive>(value);
218 } 192 }
219 193
220 processRethrow(Rethrow node) { 194 processRethrow(Rethrow node) {
221 // Rethrow can only appear in a catch block. It throws that block's 195 // Rethrow can only appear in a catch block. It throws that block's
222 // (wrapped) caught exception. 196 // (wrapped) caught exception.
223 Throw replacement = new Throw(_exceptionParameter); 197 Throw replacement = new Throw(_exceptionParameter);
224 InteriorNode parent = node.parent; 198 InteriorNode parent = node.parent;
225 parent.body = replacement; 199 parent.body = replacement;
226 replacement.parent = parent; 200 replacement.parent = parent;
227 // The original rethrow does not have any references that we need to 201 // The original rethrow does not have any references that we need to
(...skipping 27 matching lines...) Expand all
255 } else { 229 } else {
256 LetCont contBinding = node.parent; 230 LetCont contBinding = node.parent;
257 newReceiver = new Interceptor(receiver, node.sourceInformation) 231 newReceiver = new Interceptor(receiver, node.sourceInformation)
258 ..interceptedClasses.addAll(_glue.getInterceptedClassesOn(selector)); 232 ..interceptedClasses.addAll(_glue.getInterceptedClassesOn(selector));
259 if (receiver.hint != null) { 233 if (receiver.hint != null) {
260 newReceiver.hint = new InterceptorEntity(receiver.hint); 234 newReceiver.hint = new InterceptorEntity(receiver.hint);
261 } 235 }
262 insertLetPrim(newReceiver, contBinding); 236 insertLetPrim(newReceiver, contBinding);
263 } 237 }
264 node.arguments.insert(0, node.receiver); 238 node.arguments.insert(0, node.receiver);
265 node.receiver = new Reference<Primitive>(newReceiver); 239 node.receiver = new Reference<Primitive>(newReceiver)..parent = node;
266 node.receiverIsIntercepted = true; 240 node.receiverIsIntercepted = true;
267 } 241 }
268 242
269 processInvokeMethodDirectly(InvokeMethodDirectly node) { 243 processInvokeMethodDirectly(InvokeMethodDirectly node) {
270 if (!_glue.isInterceptedMethod(node.target)) return; 244 if (!_glue.isInterceptedMethod(node.target)) return;
271 245
272 Selector selector = node.selector; 246 Selector selector = node.selector;
273 Primitive receiver = node.receiver.definition; 247 Primitive receiver = node.receiver.definition;
274 Primitive newReceiver; 248 Primitive newReceiver;
275 249
276 if (receiver == explicitReceiverParameter) { 250 if (receiver == explicitReceiverParameter) {
277 // If the receiver is the explicit receiver, we are calling a method in 251 // If the receiver is the explicit receiver, we are calling a method in
278 // the same interceptor: 252 // the same interceptor:
279 // Change 'receiver.foo()' to 'this.foo(receiver)'. 253 // Change 'receiver.foo()' to 'this.foo(receiver)'.
280 newReceiver = thisParameter; 254 newReceiver = thisParameter;
281 } else { 255 } else {
282 LetCont contBinding = node.parent; 256 LetCont contBinding = node.parent;
283 newReceiver = new Interceptor(receiver, node.sourceInformation) 257 newReceiver = new Interceptor(receiver, node.sourceInformation)
284 ..interceptedClasses.addAll(_glue.getInterceptedClassesOn(selector)); 258 ..interceptedClasses.addAll(_glue.getInterceptedClassesOn(selector));
285 if (receiver.hint != null) { 259 if (receiver.hint != null) {
286 newReceiver.hint = new InterceptorEntity(receiver.hint); 260 newReceiver.hint = new InterceptorEntity(receiver.hint);
287 } 261 }
288 insertLetPrim(newReceiver, contBinding); 262 insertLetPrim(newReceiver, contBinding);
289 } 263 }
290 node.arguments.insert(0, node.receiver); 264 node.arguments.insert(0, node.receiver);
291 node.receiver = new Reference<Primitive>(newReceiver); 265 node.receiver = new Reference<Primitive>(newReceiver)..parent = node;
292 } 266 }
293 267
294 processInterceptor(Interceptor node) { 268 processInterceptor(Interceptor node) {
295 _glue.registerSpecializedGetInterceptor(node.interceptedClasses); 269 _glue.registerSpecializedGetInterceptor(node.interceptedClasses);
296 } 270 }
297 } 271 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698