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

Side by Side Diff: pkg/compiler/lib/src/js_backend/codegen/unsugar.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
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 Pass; 5 import '../../cps_ir/optimizers.dart' show 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;
11 import '../../cps_ir/cps_fragment.dart'; 10 import '../../cps_ir/cps_fragment.dart';
12 import '../../common/names.dart'; 11 import '../../common/names.dart';
13 12
14 class ExplicitReceiverParameterEntity implements Local { 13 class ExplicitReceiverParameterEntity implements Local {
15 String get name => 'receiver'; 14 String get name => 'receiver';
16 final ExecutableElement executableContext; 15 final ExecutableElement executableContext;
17 ExplicitReceiverParameterEntity(this.executableContext); 16 ExplicitReceiverParameterEntity(this.executableContext);
18 toString() => 'ExplicitReceiverParameterEntity($executableContext)'; 17 toString() => 'ExplicitReceiverParameterEntity($executableContext)';
19 } 18 }
20 19
(...skipping 10 matching lines...) Expand all
31 /// special nodes that respect JavaScript behavior. 30 /// special nodes that respect JavaScript behavior.
32 /// 31 ///
33 /// Performs the following rewrites: 32 /// Performs the following rewrites:
34 /// - Add interceptors at call sites that use interceptor calling convention. 33 /// - Add interceptors at call sites that use interceptor calling convention.
35 /// - Add explicit receiver argument for methods that are called in interceptor 34 /// - Add explicit receiver argument for methods that are called in interceptor
36 /// calling convention. 35 /// calling convention.
37 /// - Convert two-parameter exception handlers to one-parameter ones. 36 /// - Convert two-parameter exception handlers to one-parameter ones.
38 class UnsugarVisitor extends TrampolineRecursiveVisitor implements Pass { 37 class UnsugarVisitor extends TrampolineRecursiveVisitor implements Pass {
39 Glue _glue; 38 Glue _glue;
40 39
41 Parameter thisParameter; 40 FunctionDefinition function;
42 Parameter explicitReceiverParameter; 41
42 Parameter get receiverParameter => function.receiverParameter;
43
44 /// The interceptor of the receiver. For some methods, this is the receiver
45 /// itself, for others, it is the interceptor parameter.
46 Parameter receiverInterceptor;
43 47
44 // In a catch block, rethrow implicitly throws the block's exception 48 // In a catch block, rethrow implicitly throws the block's exception
45 // parameter. This is the exception parameter when nested in a catch 49 // parameter. This is the exception parameter when nested in a catch
46 // block and null otherwise. 50 // block and null otherwise.
47 Parameter _exceptionParameter = null; 51 Parameter _exceptionParameter = null;
48 52
49 UnsugarVisitor(this._glue); 53 UnsugarVisitor(this._glue);
50 54
51 String get passName => 'Unsugaring'; 55 String get passName => 'Unsugaring';
52 56
53 bool methodUsesReceiverArgument(FunctionElement function) {
54 assert(_glue.isInterceptedMethod(function));
55 ClassElement clazz = function.enclosingClass.declaration;
56 return _glue.isInterceptorClass(clazz) ||
57 _glue.isUsedAsMixin(clazz);
58 }
59
60 void rewrite(FunctionDefinition function) { 57 void rewrite(FunctionDefinition function) {
61 thisParameter = function.thisParameter; 58 this.function = function;
62 bool inInterceptedMethod = _glue.isInterceptedMethod(function.element); 59 bool inInterceptedMethod = _glue.isInterceptedMethod(function.element);
63 60
64 if (function.element.name == '==' && 61 if (function.element.name == '==' &&
65 function.parameters.length == 1 && 62 function.parameters.length == 1 &&
66 !_glue.operatorEqHandlesNullArgument(function.element)) { 63 !_glue.operatorEqHandlesNullArgument(function.element)) {
67 // Insert the null check that the language semantics requires us to 64 // Insert the null check that the language semantics requires us to
68 // perform before calling operator ==. 65 // perform before calling operator ==.
69 insertEqNullCheck(function); 66 insertEqNullCheck(function);
70 } 67 }
71 68
72 if (inInterceptedMethod) { 69 if (inInterceptedMethod) {
73 ThisParameterLocal holder = thisParameter.hint; 70 function.interceptorParameter = new Parameter(null)..parent = function;
74 explicitReceiverParameter = new Parameter( 71 // Since the receiver won't be compiled to "this", set a hint on it
75 new ExplicitReceiverParameterEntity(holder.executableContext)); 72 // so the parameter gets a meaningful name.
76 explicitReceiverParameter.parent = function; 73 function.receiverParameter.hint =
77 function.parameters.insert(0, explicitReceiverParameter); 74 new ExplicitReceiverParameterEntity(function.element);
78 } 75 // If we need an interceptor for the receiver, use the receiver itself
79 76 // if possible, otherwise the interceptor argument.
80 if (inInterceptedMethod && methodUsesReceiverArgument(function.element)) { 77 receiverInterceptor = _glue.methodUsesReceiverArgument(function.element)
81 thisParameter.replaceUsesWith(explicitReceiverParameter); 78 ? function.interceptorParameter
79 : receiverParameter;
82 } 80 }
83 81
84 visit(function); 82 visit(function);
85 } 83 }
86 84
87 Constant get trueConstant { 85 Constant get trueConstant {
88 return new Constant(new TrueConstantValue()); 86 return new Constant(new TrueConstantValue());
89 } 87 }
90 88
91 Constant get falseConstant { 89 Constant get falseConstant {
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 node.argumentRefs.length == 1 && 202 node.argumentRefs.length == 1 &&
205 isNullConstant(node.argument(0))) { 203 isNullConstant(node.argument(0))) {
206 node.replaceWith(new ApplyBuiltinOperator( 204 node.replaceWith(new ApplyBuiltinOperator(
207 BuiltinOperator.Identical, 205 BuiltinOperator.Identical,
208 [node.receiver, node.argument(0)], 206 [node.receiver, node.argument(0)],
209 node.sourceInformation)); 207 node.sourceInformation));
210 return; 208 return;
211 } 209 }
212 210
213 Primitive receiver = node.receiver; 211 Primitive receiver = node.receiver;
214 Primitive newReceiver; 212 Primitive interceptor;
215 213
216 if (receiver == explicitReceiverParameter) { 214 if (receiver == receiverParameter && receiverInterceptor != null) {
217 // If the receiver is the explicit receiver, we are calling a method in 215 // TODO(asgerf): This could be done by GVN.
216 // If the receiver is 'this', we are calling a method in
218 // the same interceptor: 217 // the same interceptor:
219 // Change 'receiver.foo()' to 'this.foo(receiver)'. 218 // Change 'receiver.foo()' to 'this.foo(receiver)'.
220 newReceiver = thisParameter; 219 interceptor = receiverInterceptor;
221 } else { 220 } else {
222 newReceiver = new Interceptor(receiver, node.sourceInformation); 221 interceptor = new Interceptor(receiver, node.sourceInformation);
223 if (receiver.hint != null) { 222 if (receiver.hint != null) {
224 newReceiver.hint = new InterceptorEntity(receiver.hint); 223 interceptor.hint = new InterceptorEntity(receiver.hint);
225 } 224 }
226 new LetPrim(newReceiver).insertAbove(node.parent); 225 new LetPrim(interceptor).insertAbove(node.parent);
227 } 226 }
228 node.argumentRefs.insert(0, node.receiverRef); 227 assert(node.interceptorRef == null);
229 node.receiverRef = new Reference<Primitive>(newReceiver)..parent = node; 228 node.makeIntercepted(interceptor);
230 node.callingConvention = CallingConvention.Intercepted;
231 } 229 }
232 230
233 processInvokeMethodDirectly(InvokeMethodDirectly node) { 231 processInvokeMethodDirectly(InvokeMethodDirectly node) {
234 if (!_glue.isInterceptedMethod(node.target)) return; 232 if (!_glue.isInterceptedMethod(node.target)) return;
235 233
236 Primitive receiver = node.receiver; 234 Primitive receiver = node.receiver;
237 Primitive newReceiver; 235 Primitive interceptor;
238 236
239 if (receiver == explicitReceiverParameter) { 237 if (receiver == receiverParameter && receiverInterceptor != null) {
240 // If the receiver is the explicit receiver, we are calling a method in 238 // If the receiver is 'this', we are calling a method in
241 // the same interceptor: 239 // the same interceptor:
242 // Change 'receiver.foo()' to 'this.foo(receiver)'. 240 // Change 'receiver.foo()' to 'this.foo(receiver)'.
243 newReceiver = thisParameter; 241 interceptor = receiverInterceptor;
244 } else { 242 } else {
245 newReceiver = new Interceptor(receiver, node.sourceInformation); 243 interceptor = new Interceptor(receiver, node.sourceInformation);
246 if (receiver.hint != null) { 244 if (receiver.hint != null) {
247 newReceiver.hint = new InterceptorEntity(receiver.hint); 245 interceptor.hint = new InterceptorEntity(receiver.hint);
248 } 246 }
249 new LetPrim(newReceiver).insertAbove(node.parent); 247 new LetPrim(interceptor).insertAbove(node.parent);
250 } 248 }
251 node.argumentRefs.insert(0, node.receiverRef); 249 assert(node.interceptorRef == null);
252 node.receiverRef = new Reference<Primitive>(newReceiver)..parent = node; 250 node.makeIntercepted(interceptor);
253 node.callingConvention = CallingConvention.Intercepted;
254 } 251 }
255 } 252 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/codegen/task.dart ('k') | pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698