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

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

Issue 1313783003: dart2js cps: Generate interceptors at use-site and share afterwards. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Revert patch #3. I read Golem results backwards. 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 25 matching lines...) Expand all
36 /// - Add explicit receiver argument for methods that are called in interceptor 36 /// - Add explicit receiver argument for methods that are called in interceptor
37 /// calling convention. 37 /// calling convention.
38 /// - Convert two-parameter exception handlers to one-parameter ones. 38 /// - Convert two-parameter exception handlers to one-parameter ones.
39 class UnsugarVisitor extends RecursiveVisitor { 39 class UnsugarVisitor extends RecursiveVisitor {
40 Glue _glue; 40 Glue _glue;
41 ParentVisitor _parentVisitor = new ParentVisitor(); 41 ParentVisitor _parentVisitor = new ParentVisitor();
42 42
43 Parameter thisParameter; 43 Parameter thisParameter;
44 Parameter explicitReceiverParameter; 44 Parameter explicitReceiverParameter;
45 45
46 Map<Primitive, Interceptor> interceptors = <Primitive, Interceptor>{};
47
48 // In a catch block, rethrow implicitly throws the block's exception 46 // In a catch block, rethrow implicitly throws the block's exception
49 // parameter. This is the exception parameter when nested in a catch 47 // parameter. This is the exception parameter when nested in a catch
50 // block and null otherwise. 48 // block and null otherwise.
51 Parameter _exceptionParameter = null; 49 Parameter _exceptionParameter = null;
52 50
53 UnsugarVisitor(this._glue); 51 UnsugarVisitor(this._glue);
54 52
55 bool methodUsesReceiverArgument(FunctionElement function) { 53 bool methodUsesReceiverArgument(FunctionElement function) {
56 assert(_glue.isInterceptedMethod(function)); 54 assert(_glue.isInterceptedMethod(function));
57 ClassElement clazz = function.enclosingClass.declaration; 55 ClassElement clazz = function.enclosingClass.declaration;
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 // Rethrow can only appear in a catch block. It throws that block's 224 // Rethrow can only appear in a catch block. It throws that block's
227 // (wrapped) caught exception. 225 // (wrapped) caught exception.
228 Throw replacement = new Throw(_exceptionParameter); 226 Throw replacement = new Throw(_exceptionParameter);
229 InteriorNode parent = node.parent; 227 InteriorNode parent = node.parent;
230 parent.body = replacement; 228 parent.body = replacement;
231 replacement.parent = parent; 229 replacement.parent = parent;
232 // The original rethrow does not have any references that we need to 230 // The original rethrow does not have any references that we need to
233 // worry about unlinking. 231 // worry about unlinking.
234 } 232 }
235 233
236 /// Returns an interceptor for the given value, capable of responding to 234 processInvokeMethod(InvokeMethod node) {
237 /// [selector]. 235 Selector selector = node.selector;
238 /// 236 if (!_glue.isInterceptedSelector(selector)) return;
239 /// A single getInterceptor call will be created per primitive, bound 237
240 /// immediately after the primitive is bound. 238 Primitive receiver = node.receiver.definition;
241 /// 239 Primitive newReceiver;
242 /// The type propagation pass will later narrow the set of interceptors 240
243 /// based on the input type, and the let sinking pass will propagate the 241 if (receiver == explicitReceiverParameter) {
244 /// getInterceptor call closer to its use when this is profitable.
245 Primitive getInterceptorFor(Primitive prim, Selector selector,
246 SourceInformation sourceInformation) {
247 if (prim == explicitReceiverParameter) {
248 // If the receiver is the explicit receiver, we are calling a method in 242 // If the receiver is the explicit receiver, we are calling a method in
249 // the same interceptor. 243 // the same interceptor:
250 return thisParameter; 244 // Change 'receiver.foo()' to 'this.foo(receiver)'.
245 newReceiver = thisParameter;
246 } else {
247 LetCont contBinding = node.parent;
248 newReceiver = new Interceptor(receiver, node.sourceInformation)
249 ..interceptedClasses.addAll(_glue.getInterceptedClassesOn(selector));
250 if (receiver.hint != null) {
251 newReceiver.hint = new InterceptorEntity(receiver.hint);
252 }
253 insertLetPrim(newReceiver, contBinding);
251 } 254 }
252 assert(prim is! Interceptor); 255 node.arguments.insert(0, node.receiver);
253 Interceptor interceptor = interceptors[prim]; 256 node.receiver = new Reference<Primitive>(newReceiver);
254 if (interceptor == null) {
255 interceptor = new Interceptor(prim, sourceInformation);
256 interceptors[prim] = interceptor;
257 InteriorNode parent = prim.parent;
258 insertLetPrim(interceptor, parent.body);
259 if (prim.hint != null) {
260 interceptor.hint = new InterceptorEntity(prim.hint);
261 }
262 }
263 // Add the interceptor classes that can respond to the given selector.
264 interceptor.interceptedClasses.addAll(
265 _glue.getInterceptedClassesOn(selector));
266 return interceptor;
267 }
268
269 processInvokeMethod(InvokeMethod node) {
270 if (_glue.isInterceptedSelector(node.selector)) {
271 // Rewrite `x.foo()` => `INTERCEPTOR.foo(x, ..)`.
272 Primitive receiver = node.receiver.definition;
273 Primitive newReceiver =
274 getInterceptorFor(receiver, node.selector, node.sourceInformation);
275 node.arguments.insert(0, node.receiver);
276 node.receiver = new Reference<Primitive>(newReceiver);
277 }
278 } 257 }
279 258
280 processInvokeMethodDirectly(InvokeMethodDirectly node) { 259 processInvokeMethodDirectly(InvokeMethodDirectly node) {
281 if (_glue.isInterceptedMethod(node.target)) { 260 if (!_glue.isInterceptedMethod(node.target)) return;
282 // Rewrite `x.foo()` => `INTERCEPTOR.foo(x, ..)`. 261
283 Primitive receiver = node.receiver.definition; 262 Selector selector = node.selector;
284 Primitive newReceiver = 263 Primitive receiver = node.receiver.definition;
285 getInterceptorFor(receiver, node.selector, node.sourceInformation); 264 Primitive newReceiver;
286 node.arguments.insert(0, node.receiver); 265
287 node.receiver = new Reference<Primitive>(newReceiver); 266 if (receiver == explicitReceiverParameter) {
267 // If the receiver is the explicit receiver, we are calling a method in
268 // the same interceptor:
269 // Change 'receiver.foo()' to 'this.foo(receiver)'.
270 newReceiver = thisParameter;
271 } else {
272 LetCont contBinding = node.parent;
273 newReceiver = new Interceptor(receiver, node.sourceInformation)
274 ..interceptedClasses.addAll(_glue.getInterceptedClassesOn(selector));
275 if (receiver.hint != null) {
276 newReceiver.hint = new InterceptorEntity(receiver.hint);
277 }
278 insertLetPrim(newReceiver, contBinding);
288 } 279 }
280 node.arguments.insert(0, node.receiver);
281 node.receiver = new Reference<Primitive>(newReceiver);
289 } 282 }
290 283
291 processBranch(Branch node) { 284 processBranch(Branch node) {
292 // TODO(karlklose): implement the checked mode part of boolean conversion. 285 // TODO(karlklose): implement the checked mode part of boolean conversion.
293 InteriorNode parent = node.parent; 286 InteriorNode parent = node.parent;
294 IsTrue condition = node.condition; 287 IsTrue condition = node.condition;
295 288
296 // Do not rewrite conditions that are foreign code. 289 // Do not rewrite conditions that are foreign code.
297 // It is redundant, and causes infinite recursion (if not optimized) 290 // It is redundant, and causes infinite recursion (if not optimized)
298 // in the implementation of identical, which itself contains a condition. 291 // in the implementation of identical, which itself contains a condition.
(...skipping 21 matching lines...) Expand all
320 condition.value.unlink(); 313 condition.value.unlink();
321 node.trueContinuation.unlink(); 314 node.trueContinuation.unlink();
322 node.falseContinuation.unlink(); 315 node.falseContinuation.unlink();
323 parent.body = newNode; 316 parent.body = newNode;
324 } 317 }
325 318
326 processInterceptor(Interceptor node) { 319 processInterceptor(Interceptor node) {
327 _glue.registerSpecializedGetInterceptor(node.interceptedClasses); 320 _glue.registerSpecializedGetInterceptor(node.interceptedClasses);
328 } 321 }
329 } 322 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/codegen/task.dart ('k') | tests/compiler/dart2js_extra/dart2js_extra.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698