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

Side by Side Diff: pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 part of dart2js.js_emitter; 5 part of dart2js.js_emitter;
6 6
7 class ParameterStubGenerator { 7 class ParameterStubGenerator {
8 static final Set<Selector> emptySelectorSet = new Set<Selector>(); 8 static final Set<Selector> emptySelectorSet = new Set<Selector>();
9 9
10 final Namer namer; 10 final Namer namer;
11 final Compiler compiler; 11 final Compiler compiler;
12 final JavaScriptBackend backend; 12 final JavaScriptBackend backend;
13 13
14 ParameterStubGenerator(this.compiler, this.namer, this.backend); 14 ParameterStubGenerator(this.compiler, this.namer, this.backend);
15 15
16 Emitter get emitter => backend.emitter.emitter; 16 Emitter get emitter => backend.emitter.emitter;
17 CodeEmitterTask get emitterTask => backend.emitter; 17 CodeEmitterTask get emitterTask => backend.emitter;
18 DiagnosticReporter get reporter => compiler.reporter; 18 DiagnosticReporter get reporter => compiler.reporter;
19 19
20 bool needsSuperGetter(FunctionElement element) => 20 bool needsSuperGetter(FunctionElement element) =>
21 compiler.codegenWorld.methodsNeedingSuperGetter.contains(element); 21 compiler.codegenWorld.methodsNeedingSuperGetter.contains(element);
22 22
23 /** 23 /**
24 * Generates stubs to handle invocation of methods with optional 24 * Generates stubs to handle invocation of methods with optional
25 * arguments. 25 * arguments.
26 * 26 *
27 * A method like `foo([x])` may be invoked by the following 27 * A method like `foo([x])` may be invoked by the following
28 * calls: `foo(), foo(1), foo(x: 1)`. This method generates the stub for the 28 * calls: `foo(), foo(1), foo(x: 1)`. This method generates the stub for the
29 * given [selector] and returns the generated [ParameterStubMethod]. 29 * given [selector] and returns the generated [ParameterStubMethod].
30 * 30 *
31 * Returns null if no stub is needed. 31 * Returns null if no stub is needed.
32 * 32 *
33 * Members may be invoked in two ways: directly, or through a closure. In the 33 * Members may be invoked in two ways: directly, or through a closure. In the
34 * latter case the caller invokes the closure's `call` method. This method 34 * latter case the caller invokes the closure's `call` method. This method
35 * accepts two selectors. The returned stub method has the corresponding 35 * accepts two selectors. The returned stub method has the corresponding
36 * name [ParameterStubMethod.name] and [ParameterStubMethod.callName] set if 36 * name [ParameterStubMethod.name] and [ParameterStubMethod.callName] set if
37 * the input selector is non-null (and the member needs a stub). 37 * the input selector is non-null (and the member needs a stub).
38 */ 38 */
39 ParameterStubMethod generateParameterStub(FunctionElement member, 39 ParameterStubMethod generateParameterStub(
40 Selector selector, 40 FunctionElement member, Selector selector, Selector callSelector) {
41 Selector callSelector) {
42 CallStructure callStructure = selector.callStructure; 41 CallStructure callStructure = selector.callStructure;
43 FunctionSignature parameters = member.functionSignature; 42 FunctionSignature parameters = member.functionSignature;
44 int positionalArgumentCount = callStructure.positionalArgumentCount; 43 int positionalArgumentCount = callStructure.positionalArgumentCount;
45 if (positionalArgumentCount == parameters.parameterCount) { 44 if (positionalArgumentCount == parameters.parameterCount) {
46 assert(callStructure.isUnnamed); 45 assert(callStructure.isUnnamed);
47 return null; 46 return null;
48 } 47 }
49 if (parameters.optionalParametersAreNamed && 48 if (parameters.optionalParametersAreNamed &&
50 callStructure.namedArgumentCount == parameters.optionalParameterCount) { 49 callStructure.namedArgumentCount == parameters.optionalParameterCount) {
51 // If the selector has the same number of named arguments as the element, 50 // If the selector has the same number of named arguments as the element,
(...skipping 10 matching lines...) Expand all
62 int extraArgumentCount = isInterceptedMethod ? 1 : 0; 61 int extraArgumentCount = isInterceptedMethod ? 1 : 0;
63 // Use '$receiver' to avoid clashes with other parameter names. Using 62 // Use '$receiver' to avoid clashes with other parameter names. Using
64 // '$receiver' works because namer.safeVariableName used for getting 63 // '$receiver' works because namer.safeVariableName used for getting
65 // parameter names never returns a name beginning with a single '$'. 64 // parameter names never returns a name beginning with a single '$'.
66 String receiverArgumentName = r'$receiver'; 65 String receiverArgumentName = r'$receiver';
67 66
68 // The parameters that this stub takes. 67 // The parameters that this stub takes.
69 List<jsAst.Parameter> parametersBuffer = 68 List<jsAst.Parameter> parametersBuffer =
70 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); 69 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount);
71 // The arguments that will be passed to the real method. 70 // The arguments that will be passed to the real method.
72 List<jsAst.Expression> argumentsBuffer = 71 List<jsAst.Expression> argumentsBuffer = new List<jsAst.Expression>(
73 new List<jsAst.Expression>( 72 parameters.parameterCount + extraArgumentCount);
74 parameters.parameterCount + extraArgumentCount);
75 73
76 int count = 0; 74 int count = 0;
77 if (isInterceptedMethod) { 75 if (isInterceptedMethod) {
78 count++; 76 count++;
79 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); 77 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName);
80 argumentsBuffer[0] = js('#', receiverArgumentName); 78 argumentsBuffer[0] = js('#', receiverArgumentName);
81 } 79 }
82 80
83 int optionalParameterStart = positionalArgumentCount + extraArgumentCount; 81 int optionalParameterStart = positionalArgumentCount + extraArgumentCount;
84 // Includes extra receiver argument when using interceptor convention 82 // Includes extra receiver argument when using interceptor convention
(...skipping 25 matching lines...) Expand all
110 // down to the native method. 108 // down to the native method.
111 indexOfLastOptionalArgumentInParameters = count; 109 indexOfLastOptionalArgumentInParameters = count;
112 } 110 }
113 argumentsBuffer[count] = emitter.constantReference(value); 111 argumentsBuffer[count] = emitter.constantReference(value);
114 } 112 }
115 } 113 }
116 } 114 }
117 count++; 115 count++;
118 }); 116 });
119 117
120 var body; // List or jsAst.Statement. 118 var body; // List or jsAst.Statement.
121 if (backend.nativeData.hasFixedBackendName(member)) { 119 if (backend.nativeData.hasFixedBackendName(member)) {
122 body = emitterTask.nativeEmitter.generateParameterStubStatements( 120 body = emitterTask.nativeEmitter.generateParameterStubStatements(
123 member, isInterceptedMethod, namer.invocationName(selector), 121 member,
124 parametersBuffer, argumentsBuffer, 122 isInterceptedMethod,
123 namer.invocationName(selector),
124 parametersBuffer,
125 argumentsBuffer,
125 indexOfLastOptionalArgumentInParameters); 126 indexOfLastOptionalArgumentInParameters);
126 } else if (member.isInstanceMember) { 127 } else if (member.isInstanceMember) {
127 if (needsSuperGetter(member)) { 128 if (needsSuperGetter(member)) {
128 ClassElement superClass = member.enclosingClass; 129 ClassElement superClass = member.enclosingClass;
129 jsAst.Name methodName = namer.instanceMethodName(member); 130 jsAst.Name methodName = namer.instanceMethodName(member);
130 // When redirecting, we must ensure that we don't end up in a subclass. 131 // When redirecting, we must ensure that we don't end up in a subclass.
131 // We thus can't just invoke `this.foo$1.call(filledInArguments)`. 132 // We thus can't just invoke `this.foo$1.call(filledInArguments)`.
132 // Instead we need to call the statically resolved target. 133 // Instead we need to call the statically resolved target.
133 // `<class>.prototype.bar$1.call(this, argument0, ...)`. 134 // `<class>.prototype.bar$1.call(this, argument0, ...)`.
134 body = js.statement( 135 body = js.statement('return #.#.call(this, #);', [
135 'return #.#.call(this, #);', 136 backend.emitter
136 [backend.emitter.prototypeAccess(superClass, 137 .prototypeAccess(superClass, hasBeenInstantiated: true),
137 hasBeenInstantiated: true), 138 methodName,
138 methodName, 139 argumentsBuffer
139 argumentsBuffer]); 140 ]);
140 } else { 141 } else {
141 body = js.statement( 142 body = js.statement('return this.#(#);',
142 'return this.#(#);',
143 [namer.instanceMethodName(member), argumentsBuffer]); 143 [namer.instanceMethodName(member), argumentsBuffer]);
144 } 144 }
145 } else { 145 } else {
146 body = js.statement('return #(#)', 146 body = js.statement('return #(#)',
147 [emitter.staticFunctionAccess(member), argumentsBuffer]); 147 [emitter.staticFunctionAccess(member), argumentsBuffer]);
148 } 148 }
149 149
150 jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]); 150 jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]);
151 151
152 jsAst.Name name = member.isStatic ? null : namer.invocationName(selector); 152 jsAst.Name name = member.isStatic ? null : namer.invocationName(selector);
(...skipping 27 matching lines...) Expand all
180 // (4) No stub generated, call is direct. 180 // (4) No stub generated, call is direct.
181 // (5) No stub generated, call is direct. 181 // (5) No stub generated, call is direct.
182 // 182 //
183 // We need to pay attention if this stub is for a function that has been 183 // We need to pay attention if this stub is for a function that has been
184 // invoked from a subclass. Then we cannot just redirect, since that 184 // invoked from a subclass. Then we cannot just redirect, since that
185 // would invoke the methods of the subclass. We have to compile to: 185 // would invoke the methods of the subclass. We have to compile to:
186 // (1) foo$2(a, b) => MyClass.foo$4$c$d.call(this, a, b, null, null) 186 // (1) foo$2(a, b) => MyClass.foo$4$c$d.call(this, a, b, null, null)
187 // (2) foo$3$c(a, b, c) => MyClass.foo$4$c$d(this, a, b, c, null); 187 // (2) foo$3$c(a, b, c) => MyClass.foo$4$c$d(this, a, b, c, null);
188 // (3) foo$3$d(a, b, d) => MyClass.foo$4$c$d(this, a, b, null, d); 188 // (3) foo$3$d(a, b, d) => MyClass.foo$4$c$d(this, a, b, null, d);
189 List<ParameterStubMethod> generateParameterStubs(MethodElement member, 189 List<ParameterStubMethod> generateParameterStubs(MethodElement member,
190 {bool canTearOff: true}) { 190 {bool canTearOff: true}) {
191 if (member.enclosingElement.isClosure) { 191 if (member.enclosingElement.isClosure) {
192 ClosureClassElement cls = member.enclosingElement; 192 ClosureClassElement cls = member.enclosingElement;
193 if (cls.supertype.element == backend.helpers.boundClosureClass) { 193 if (cls.supertype.element == backend.helpers.boundClosureClass) {
194 reporter.internalError(cls.methodElement, 'Bound closure1.'); 194 reporter.internalError(cls.methodElement, 'Bound closure1.');
195 } 195 }
196 if (cls.methodElement.isInstanceMember) { 196 if (cls.methodElement.isInstanceMember) {
197 reporter.internalError(cls.methodElement, 'Bound closure2.'); 197 reporter.internalError(cls.methodElement, 'Bound closure2.');
198 } 198 }
199 } 199 }
200 200
201 // The set of selectors that apply to `member`. For example, for 201 // The set of selectors that apply to `member`. For example, for
202 // a member `foo(x, [y])` the following selectors may apply: 202 // a member `foo(x, [y])` the following selectors may apply:
203 // `foo(x)`, and `foo(x, y)`. 203 // `foo(x)`, and `foo(x, y)`.
204 Map<Selector, SelectorConstraints> selectors; 204 Map<Selector, SelectorConstraints> selectors;
205 // The set of selectors that apply to `member` if it's name was `call`. 205 // The set of selectors that apply to `member` if it's name was `call`.
206 // This happens when a member is torn off. In that case calls to the 206 // This happens when a member is torn off. In that case calls to the
207 // function use the name `call`, and we must be able to handle every 207 // function use the name `call`, and we must be able to handle every
208 // `call` invocation that matches the signature. For example, for 208 // `call` invocation that matches the signature. For example, for
209 // a member `foo(x, [y])` the following selectors would be possible 209 // a member `foo(x, [y])` the following selectors would be possible
210 // call-selectors: `call(x)`, and `call(x, y)`. 210 // call-selectors: `call(x)`, and `call(x, y)`.
211 Map<Selector, SelectorConstraints> callSelectors; 211 Map<Selector, SelectorConstraints> callSelectors;
212 212
213 // Only instance members (not static methods) need stubs. 213 // Only instance members (not static methods) need stubs.
214 if (member.isInstanceMember) { 214 if (member.isInstanceMember) {
215 selectors = compiler.codegenWorld.invocationsByName(member.name); 215 selectors = compiler.codegenWorld.invocationsByName(member.name);
216 } 216 }
217 217
218 if (canTearOff) { 218 if (canTearOff) {
219 String call = namer.closureInvocationSelectorName; 219 String call = namer.closureInvocationSelectorName;
220 callSelectors = compiler.codegenWorld.invocationsByName(call); 220 callSelectors = compiler.codegenWorld.invocationsByName(call);
221 } 221 }
222 222
223 assert(emptySelectorSet.isEmpty); 223 assert(emptySelectorSet.isEmpty);
224 if (selectors == null) selectors = const <Selector, SelectorConstraints>{}; 224 if (selectors == null) selectors = const <Selector, SelectorConstraints>{};
225 if (callSelectors == null) callSelectors = 225 if (callSelectors == null)
226 const <Selector, SelectorConstraints>{}; 226 callSelectors = const <Selector, SelectorConstraints>{};
227 227
228 List<ParameterStubMethod> stubs = <ParameterStubMethod>[]; 228 List<ParameterStubMethod> stubs = <ParameterStubMethod>[];
229 229
230 if (selectors.isEmpty && callSelectors.isEmpty) { 230 if (selectors.isEmpty && callSelectors.isEmpty) {
231 return stubs; 231 return stubs;
232 } 232 }
233 233
234 // For every call-selector the corresponding selector with the name of the 234 // For every call-selector the corresponding selector with the name of the
235 // member. 235 // member.
236 // 236 //
237 // For example, for the call-selector `call(x, y)` the renamed selector 237 // For example, for the call-selector `call(x, y)` the renamed selector
238 // for member `foo` would be `foo(x, y)`. 238 // for member `foo` would be `foo(x, y)`.
239 Set<Selector> renamedCallSelectors = 239 Set<Selector> renamedCallSelectors =
240 callSelectors.isEmpty ? emptySelectorSet : new Set<Selector>(); 240 callSelectors.isEmpty ? emptySelectorSet : new Set<Selector>();
241 241
242 Set<Selector> untypedSelectors = new Set<Selector>(); 242 Set<Selector> untypedSelectors = new Set<Selector>();
243 243
244 // Start with the callSelectors since they imply the generation of the 244 // Start with the callSelectors since they imply the generation of the
245 // non-call version. 245 // non-call version.
246 for (Selector selector in callSelectors.keys) { 246 for (Selector selector in callSelectors.keys) {
247 Selector renamedSelector = new Selector.call( 247 Selector renamedSelector =
248 member.memberName, 248 new Selector.call(member.memberName, selector.callStructure);
249 selector.callStructure);
250 renamedCallSelectors.add(renamedSelector); 249 renamedCallSelectors.add(renamedSelector);
251 250
252 if (!renamedSelector.appliesUnnamed(member, compiler.world)) continue; 251 if (!renamedSelector.appliesUnnamed(member, compiler.world)) continue;
253 252
254 if (untypedSelectors.add(renamedSelector)) { 253 if (untypedSelectors.add(renamedSelector)) {
255 ParameterStubMethod stub = 254 ParameterStubMethod stub =
256 generateParameterStub(member, renamedSelector, selector); 255 generateParameterStub(member, renamedSelector, selector);
257 if (stub != null) { 256 if (stub != null) {
258 stubs.add(stub); 257 stubs.add(stub);
259 } 258 }
(...skipping 15 matching lines...) Expand all
275 generateParameterStub(member, selector, null); 274 generateParameterStub(member, selector, null);
276 if (stub != null) { 275 if (stub != null) {
277 stubs.add(stub); 276 stubs.add(stub);
278 } 277 }
279 } 278 }
280 } 279 }
281 280
282 return stubs; 281 return stubs;
283 } 282 }
284 } 283 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/native_generator.dart ('k') | pkg/compiler/lib/src/js_emitter/program_builder/collector.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698