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

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

Issue 1312393002: dart2js cps: Use 'this' instead of receiver when possible. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Cleanup Created 5 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 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; 5 import '../../cps_ir/optimizers.dart' show ParentVisitor;
6 import '../../constants/values.dart'; 6 import '../../constants/values.dart';
7 import '../../elements/elements.dart'; 7 import '../../elements/elements.dart';
8 import '../../io/source_information.dart'; 8 import '../../io/source_information.dart';
9 import '../../js_backend/codegen/glue.dart'; 9 import '../../js_backend/codegen/glue.dart';
10 import '../../universe/universe.dart' show Selector; 10 import '../../universe/universe.dart' show Selector;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 45
46 Map<Primitive, Interceptor> interceptors = <Primitive, Interceptor>{}; 46 Map<Primitive, Interceptor> interceptors = <Primitive, Interceptor>{};
47 47
48 // In a catch block, rethrow implicitly throws the block's exception 48 // In a catch block, rethrow implicitly throws the block's exception
49 // parameter. This is the exception parameter when nested in a catch 49 // parameter. This is the exception parameter when nested in a catch
50 // block and null otherwise. 50 // block and null otherwise.
51 Parameter _exceptionParameter = null; 51 Parameter _exceptionParameter = null;
52 52
53 UnsugarVisitor(this._glue); 53 UnsugarVisitor(this._glue);
54 54
55 bool methodUsesReceiverArgument(FunctionElement function) {
56 assert(_glue.isInterceptedMethod(function));
57 ClassElement clazz = function.enclosingClass.declaration;
58 return _glue.isInterceptorClass(clazz) ||
59 _glue.isUsedAsMixin(clazz);
60 }
61
55 void rewrite(FunctionDefinition function) { 62 void rewrite(FunctionDefinition function) {
63 thisParameter = function.thisParameter;
56 bool inInterceptedMethod = _glue.isInterceptedMethod(function.element); 64 bool inInterceptedMethod = _glue.isInterceptedMethod(function.element);
57 65
58 if (function.element.name == '==' && 66 if (function.element.name == '==' &&
59 function.parameters.length == 1 && 67 function.parameters.length == 1 &&
60 !_glue.operatorEqHandlesNullArgument(function.element)) { 68 !_glue.operatorEqHandlesNullArgument(function.element)) {
61 // Insert the null check that the language semantics requires us to 69 // Insert the null check that the language semantics requires us to
62 // perform before calling operator ==. 70 // perform before calling operator ==.
63 insertEqNullCheck(function); 71 insertEqNullCheck(function);
64 } 72 }
65 73
66 if (inInterceptedMethod) { 74 if (inInterceptedMethod) {
67 thisParameter = function.thisParameter;
68 ThisParameterLocal holder = thisParameter.hint; 75 ThisParameterLocal holder = thisParameter.hint;
69 explicitReceiverParameter = new Parameter( 76 explicitReceiverParameter = new Parameter(
70 new ExplicitReceiverParameterEntity( 77 new ExplicitReceiverParameterEntity(
71 holder.executableContext)); 78 holder.executableContext));
72 function.parameters.insert(0, explicitReceiverParameter); 79 function.parameters.insert(0, explicitReceiverParameter);
73 } 80 }
74 81
75 // Set all parent pointers. 82 // Set all parent pointers.
76 _parentVisitor.visit(function); 83 _parentVisitor.visit(function);
77 84
78 if (inInterceptedMethod) { 85 if (inInterceptedMethod && methodUsesReceiverArgument(function.element)) {
79 explicitReceiverParameter.substituteFor(thisParameter); 86 explicitReceiverParameter.substituteFor(thisParameter);
80 } 87 }
81 88
82 visit(function); 89 visit(function);
83 } 90 }
84 91
85 Constant get trueConstant { 92 Constant get trueConstant {
86 return new Constant(new TrueConstantValue()); 93 return new Constant(new TrueConstantValue());
87 } 94 }
88 95
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 235
229 /// Returns an interceptor for the given value, capable of responding to 236 /// Returns an interceptor for the given value, capable of responding to
230 /// [selector]. 237 /// [selector].
231 /// 238 ///
232 /// A single getInterceptor call will be created per primitive, bound 239 /// A single getInterceptor call will be created per primitive, bound
233 /// immediately after the primitive is bound. 240 /// immediately after the primitive is bound.
234 /// 241 ///
235 /// The type propagation pass will later narrow the set of interceptors 242 /// The type propagation pass will later narrow the set of interceptors
236 /// based on the input type, and the let sinking pass will propagate the 243 /// based on the input type, and the let sinking pass will propagate the
237 /// getInterceptor call closer to its use when this is profitable. 244 /// getInterceptor call closer to its use when this is profitable.
238 Interceptor getInterceptorFor(Primitive prim, Selector selector, 245 Primitive getInterceptorFor(Primitive prim, Selector selector,
239 SourceInformation sourceInformation) { 246 SourceInformation sourceInformation) {
247 if (prim == explicitReceiverParameter) {
248 // If the receiver is the explicit receiver, we are calling a method in
249 // the same interceptor.
250 return thisParameter;
251 }
240 assert(prim is! Interceptor); 252 assert(prim is! Interceptor);
241 Interceptor interceptor = interceptors[prim]; 253 Interceptor interceptor = interceptors[prim];
242 if (interceptor == null) { 254 if (interceptor == null) {
243 interceptor = new Interceptor(prim, sourceInformation); 255 interceptor = new Interceptor(prim, sourceInformation);
244 interceptors[prim] = interceptor; 256 interceptors[prim] = interceptor;
245 InteriorNode parent = prim.parent; 257 InteriorNode parent = prim.parent;
246 insertLetPrim(interceptor, parent.body); 258 insertLetPrim(interceptor, parent.body);
247 if (prim.hint != null) { 259 if (prim.hint != null) {
248 interceptor.hint = new InterceptorEntity(prim.hint); 260 interceptor.hint = new InterceptorEntity(prim.hint);
249 } 261 }
250 } 262 }
251 // Add the interceptor classes that can respond to the given selector. 263 // Add the interceptor classes that can respond to the given selector.
252 interceptor.interceptedClasses.addAll( 264 interceptor.interceptedClasses.addAll(
253 _glue.getInterceptedClassesOn(selector)); 265 _glue.getInterceptedClassesOn(selector));
254 return interceptor; 266 return interceptor;
255 } 267 }
256 268
257 processInvokeMethod(InvokeMethod node) { 269 processInvokeMethod(InvokeMethod node) {
258 Selector selector = node.selector; 270 if (_glue.isInterceptedSelector(node.selector)) {
259 if (!_glue.isInterceptedSelector(selector)) return; 271 // Rewrite `x.foo()` => `INTERCEPTOR.foo(x, ..)`.
260 272 Primitive receiver = node.receiver.definition;
261 Primitive receiver = node.receiver.definition; 273 Primitive newReceiver =
262 Primitive newReceiver; 274 getInterceptorFor(receiver, node.selector, node.sourceInformation);
263 275 node.arguments.insert(0, node.receiver);
264 if (receiver == explicitReceiverParameter) { 276 node.receiver = new Reference<Primitive>(newReceiver);
265 // If the receiver is the explicit receiver, we are calling a method in
266 // the same interceptor:
267 // Change 'receiver.foo()' to 'this.foo(receiver)'.
268 newReceiver = thisParameter;
269 } else {
270 newReceiver = getInterceptorFor(
271 receiver, node.selector, node.sourceInformation);
272 } 277 }
273
274 node.arguments.insert(0, node.receiver);
275 node.receiver = new Reference<Primitive>(newReceiver);
276 } 278 }
277 279
278 processInvokeMethodDirectly(InvokeMethodDirectly node) { 280 processInvokeMethodDirectly(InvokeMethodDirectly node) {
279 if (_glue.isInterceptedMethod(node.target)) { 281 if (_glue.isInterceptedMethod(node.target)) {
280 Primitive nullPrim = nullConstant; 282 // Rewrite `x.foo()` => `INTERCEPTOR.foo(x, ..)`.
281 insertLetPrim(nullPrim, node); 283 Primitive receiver = node.receiver.definition;
284 Primitive newReceiver =
285 getInterceptorFor(receiver, node.selector, node.sourceInformation);
282 node.arguments.insert(0, node.receiver); 286 node.arguments.insert(0, node.receiver);
283 // TODO(sra): `null` is not adequate. Interceptors project the class 287 node.receiver = new Reference<Primitive>(newReceiver);
284 // hierarchy onto an interceptor hierarchy. A super call that does a
285 // method call will use the javascript 'this' parameter to avoid calling
286 // getInterceptor again, so the receiver must be the interceptor (likely
287 // `this`), not `null`.
288 node.receiver = new Reference<Primitive>(nullPrim);
289 } 288 }
290 } 289 }
291 290
292 processBranch(Branch node) { 291 processBranch(Branch node) {
293 // TODO(karlklose): implement the checked mode part of boolean conversion. 292 // TODO(karlklose): implement the checked mode part of boolean conversion.
294 InteriorNode parent = node.parent; 293 InteriorNode parent = node.parent;
295 IsTrue condition = node.condition; 294 IsTrue condition = node.condition;
296 295
297 // Do not rewrite conditions that are foreign code. 296 // Do not rewrite conditions that are foreign code.
298 // It is redundant, and causes infinite recursion (if not optimized) 297 // It is redundant, and causes infinite recursion (if not optimized)
(...skipping 22 matching lines...) Expand all
321 condition.value.unlink(); 320 condition.value.unlink();
322 node.trueContinuation.unlink(); 321 node.trueContinuation.unlink();
323 node.falseContinuation.unlink(); 322 node.falseContinuation.unlink();
324 parent.body = newNode; 323 parent.body = newNode;
325 } 324 }
326 325
327 processInterceptor(Interceptor node) { 326 processInterceptor(Interceptor node) {
328 _glue.registerSpecializedGetInterceptor(node.interceptedClasses); 327 _glue.registerSpecializedGetInterceptor(node.interceptedClasses);
329 } 328 }
330 } 329 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698