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

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

Issue 2939033002: Towards compiling Hello World! (Closed)
Patch Set: Fix parameter ordering Created 3 years, 6 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 library dart2js.js_emitter.parameter_stub_generator; 5 library dart2js.js_emitter.parameter_stub_generator;
6 6
7 import '../closure.dart' show ClosureClassElement; 7 import '../closure.dart' show ClosureClassElement;
8 import '../common.dart'; 8 import '../common.dart';
9 import '../common_elements.dart'; 9 import '../common_elements.dart';
10 import '../constants/values.dart'; 10 import '../constants/values.dart';
11 import '../elements/elements.dart'
12 show
13 ClassElement,
14 FunctionElement,
15 FunctionSignature,
16 MethodElement,
17 ParameterElement;
18 import '../elements/entities.dart'; 11 import '../elements/entities.dart';
19 import '../js/js.dart' as jsAst; 12 import '../js/js.dart' as jsAst;
20 import '../js/js.dart' show js; 13 import '../js/js.dart' show js;
21 import '../js_backend/constant_handler_javascript.dart'
22 show JavaScriptConstantCompiler;
23 import '../js_backend/namer.dart' show Namer; 14 import '../js_backend/namer.dart' show Namer;
24 import '../js_backend/native_data.dart'; 15 import '../js_backend/native_data.dart';
25 import '../js_backend/interceptor_data.dart'; 16 import '../js_backend/interceptor_data.dart';
26 import '../universe/call_structure.dart' show CallStructure; 17 import '../universe/call_structure.dart' show CallStructure;
27 import '../universe/selector.dart' show Selector; 18 import '../universe/selector.dart' show Selector;
28 import '../universe/world_builder.dart' 19 import '../universe/world_builder.dart'
29 show CodegenWorldBuilder, SelectorConstraints; 20 show CodegenWorldBuilder, SelectorConstraints;
30 import '../world.dart' show ClosedWorld; 21 import '../world.dart' show ClosedWorld;
31 22
32 import 'model.dart'; 23 import 'model.dart';
33 24
34 import 'code_emitter_task.dart' show CodeEmitterTask, Emitter; 25 import 'code_emitter_task.dart' show CodeEmitterTask, Emitter;
35 26
36 class ParameterStubGenerator { 27 class ParameterStubGenerator {
37 static final Set<Selector> emptySelectorSet = new Set<Selector>(); 28 static final Set<Selector> emptySelectorSet = new Set<Selector>();
38 29
39 final CommonElements _commonElements; 30 final CommonElements _commonElements;
40 final CodeEmitterTask _emitterTask; 31 final CodeEmitterTask _emitterTask;
41 final JavaScriptConstantCompiler _constants;
42 final Namer _namer; 32 final Namer _namer;
43 final NativeData _nativeData; 33 final NativeData _nativeData;
44 final InterceptorData _interceptorData; 34 final InterceptorData _interceptorData;
45 final CodegenWorldBuilder _codegenWorldBuilder; 35 final CodegenWorldBuilder _codegenWorldBuilder;
46 final ClosedWorld _closedWorld; 36 final ClosedWorld _closedWorld;
47 37
48 ParameterStubGenerator( 38 ParameterStubGenerator(
49 this._commonElements, 39 this._commonElements,
50 this._emitterTask, 40 this._emitterTask,
51 this._constants,
52 this._namer, 41 this._namer,
53 this._nativeData, 42 this._nativeData,
54 this._interceptorData, 43 this._interceptorData,
55 this._codegenWorldBuilder, 44 this._codegenWorldBuilder,
56 this._closedWorld); 45 this._closedWorld);
57 46
58 Emitter get _emitter => _emitterTask.emitter; 47 Emitter get _emitter => _emitterTask.emitter;
59 48
60 bool needsSuperGetter(FunctionElement element) => 49 bool needsSuperGetter(FunctionEntity element) =>
61 _codegenWorldBuilder.methodsNeedingSuperGetter.contains(element); 50 _codegenWorldBuilder.methodsNeedingSuperGetter.contains(element);
62 51
63 /** 52 /**
64 * Generates stubs to handle invocation of methods with optional 53 * Generates stubs to handle invocation of methods with optional
65 * arguments. 54 * arguments.
66 * 55 *
67 * A method like `foo([x])` may be invoked by the following 56 * A method like `foo([x])` may be invoked by the following
68 * calls: `foo(), foo(1), foo(x: 1)`. This method generates the stub for the 57 * calls: `foo(), foo(1), foo(x: 1)`. This method generates the stub for the
69 * given [selector] and returns the generated [ParameterStubMethod]. 58 * given [selector] and returns the generated [ParameterStubMethod].
70 * 59 *
71 * Returns null if no stub is needed. 60 * Returns null if no stub is needed.
72 * 61 *
73 * Members may be invoked in two ways: directly, or through a closure. In the 62 * Members may be invoked in two ways: directly, or through a closure. In the
74 * latter case the caller invokes the closure's `call` method. This method 63 * latter case the caller invokes the closure's `call` method. This method
75 * accepts two selectors. The returned stub method has the corresponding 64 * accepts two selectors. The returned stub method has the corresponding
76 * name [ParameterStubMethod.name] and [ParameterStubMethod.callName] set if 65 * name [ParameterStubMethod.name] and [ParameterStubMethod.callName] set if
77 * the input selector is non-null (and the member needs a stub). 66 * the input selector is non-null (and the member needs a stub).
78 */ 67 */
79 ParameterStubMethod generateParameterStub( 68 ParameterStubMethod generateParameterStub(
80 MethodElement member, Selector selector, Selector callSelector) { 69 FunctionEntity member, Selector selector, Selector callSelector) {
81 CallStructure callStructure = selector.callStructure; 70 CallStructure callStructure = selector.callStructure;
82 FunctionSignature parameters = member.functionSignature; 71 ParameterStructure parameterStructure = member.parameterStructure;
83 int positionalArgumentCount = callStructure.positionalArgumentCount; 72 int positionalArgumentCount = callStructure.positionalArgumentCount;
84 if (positionalArgumentCount == parameters.parameterCount) { 73 if (positionalArgumentCount == parameterStructure.totalParameters) {
85 assert(callStructure.isUnnamed); 74 assert(callStructure.isUnnamed);
86 return null; 75 return null;
87 } 76 }
88 if (parameters.optionalParametersAreNamed && 77 if (parameterStructure.namedParameters.isNotEmpty &&
89 callStructure.namedArgumentCount == parameters.optionalParameterCount) { 78 callStructure.namedArgumentCount ==
79 parameterStructure.namedParameters.length) {
90 // If the selector has the same number of named arguments as the element, 80 // If the selector has the same number of named arguments as the element,
91 // we don't need to add a stub. The call site will hit the method 81 // we don't need to add a stub. The call site will hit the method
92 // directly. 82 // directly.
93 return null; 83 return null;
94 } 84 }
85
95 List<String> names = callStructure.getOrderedNamedArguments(); 86 List<String> names = callStructure.getOrderedNamedArguments();
96 87
97 bool isInterceptedMethod = _interceptorData.isInterceptedMethod(member); 88 bool isInterceptedMethod = _interceptorData.isInterceptedMethod(member);
98 89
99 // If the method is intercepted, we need to also pass the actual receiver. 90 // If the method is intercepted, we need to also pass the actual receiver.
100 int extraArgumentCount = isInterceptedMethod ? 1 : 0; 91 int extraArgumentCount = isInterceptedMethod ? 1 : 0;
101 // Use '$receiver' to avoid clashes with other parameter names. Using 92 // Use '$receiver' to avoid clashes with other parameter names. Using
102 // '$receiver' works because namer.safeVariableName used for getting 93 // '$receiver' works because namer.safeVariableName used for getting
103 // parameter names never returns a name beginning with a single '$'. 94 // parameter names never returns a name beginning with a single '$'.
104 String receiverArgumentName = r'$receiver'; 95 String receiverArgumentName = r'$receiver';
105 96
106 // The parameters that this stub takes. 97 // The parameters that this stub takes.
107 List<jsAst.Parameter> parametersBuffer = 98 List<jsAst.Parameter> parametersBuffer =
108 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); 99 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount);
109 // The arguments that will be passed to the real method. 100 // The arguments that will be passed to the real method.
110 List<jsAst.Expression> argumentsBuffer = new List<jsAst.Expression>( 101 List<jsAst.Expression> argumentsBuffer = new List<jsAst.Expression>(
111 parameters.parameterCount + extraArgumentCount); 102 parameterStructure.totalParameters + extraArgumentCount);
112 103
113 int count = 0; 104 int count = 0;
114 if (isInterceptedMethod) { 105 if (isInterceptedMethod) {
115 count++; 106 count++;
116 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); 107 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName);
117 argumentsBuffer[0] = js('#', receiverArgumentName); 108 argumentsBuffer[0] = js('#', receiverArgumentName);
118 } 109 }
119 110
120 int optionalParameterStart = positionalArgumentCount + extraArgumentCount; 111 int optionalParameterStart = positionalArgumentCount + extraArgumentCount;
121 // Includes extra receiver argument when using interceptor convention 112 // Includes extra receiver argument when using interceptor convention
122 int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1; 113 int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1;
123 114
124 parameters.orderedForEachParameter((_element) { 115 _codegenWorldBuilder.forEachParameter(member,
125 ParameterElement element = _element; 116 (_, String name, ConstantValue value) {
126 String jsName = _namer.safeVariableName(element.name); 117 String jsName = _namer.safeVariableName(name);
127 assert(jsName != receiverArgumentName); 118 assert(jsName != receiverArgumentName);
128 if (count < optionalParameterStart) { 119 if (count < optionalParameterStart) {
129 parametersBuffer[count] = new jsAst.Parameter(jsName); 120 parametersBuffer[count] = new jsAst.Parameter(jsName);
130 argumentsBuffer[count] = js('#', jsName); 121 argumentsBuffer[count] = js('#', jsName);
131 } else { 122 } else {
132 int index = names.indexOf(element.name); 123 int index = names.indexOf(name);
133 if (index != -1) { 124 if (index != -1) {
134 indexOfLastOptionalArgumentInParameters = count; 125 indexOfLastOptionalArgumentInParameters = count;
135 // The order of the named arguments is not the same as the 126 // The order of the named arguments is not the same as the
136 // one in the real method (which is in Dart source order). 127 // one in the real method (which is in Dart source order).
137 argumentsBuffer[count] = js('#', jsName); 128 argumentsBuffer[count] = js('#', jsName);
138 parametersBuffer[optionalParameterStart + index] = 129 parametersBuffer[optionalParameterStart + index] =
139 new jsAst.Parameter(jsName); 130 new jsAst.Parameter(jsName);
140 } else { 131 } else {
141 ConstantValue value = _constants.getConstantValue(element.constant);
142 if (value == null) { 132 if (value == null) {
143 argumentsBuffer[count] = 133 argumentsBuffer[count] =
144 _emitter.constantReference(new NullConstantValue()); 134 _emitter.constantReference(new NullConstantValue());
145 } else { 135 } else {
146 if (!value.isNull) { 136 if (!value.isNull) {
147 // If the value is the null constant, we should not pass it 137 // If the value is the null constant, we should not pass it
148 // down to the native method. 138 // down to the native method.
149 indexOfLastOptionalArgumentInParameters = count; 139 indexOfLastOptionalArgumentInParameters = count;
150 } 140 }
151 argumentsBuffer[count] = _emitter.constantReference(value); 141 argumentsBuffer[count] = _emitter.constantReference(value);
152 } 142 }
153 } 143 }
154 } 144 }
155 count++; 145 count++;
156 }); 146 });
157 147
158 var body; // List or jsAst.Statement. 148 var body; // List or jsAst.Statement.
159 if (_nativeData.hasFixedBackendName(member)) { 149 if (_nativeData.hasFixedBackendName(member)) {
160 body = _emitterTask.nativeEmitter.generateParameterStubStatements( 150 body = _emitterTask.nativeEmitter.generateParameterStubStatements(
161 member, 151 member,
162 isInterceptedMethod, 152 isInterceptedMethod,
163 _namer.invocationName(selector), 153 _namer.invocationName(selector),
164 parametersBuffer, 154 parametersBuffer,
165 argumentsBuffer, 155 argumentsBuffer,
166 indexOfLastOptionalArgumentInParameters); 156 indexOfLastOptionalArgumentInParameters);
167 } else if (member.isInstanceMember) { 157 } else if (member.isInstanceMember) {
168 if (needsSuperGetter(member)) { 158 if (needsSuperGetter(member)) {
169 ClassElement superClass = member.enclosingClass; 159 ClassEntity superClass = member.enclosingClass;
170 jsAst.Name methodName = _namer.instanceMethodName(member); 160 jsAst.Name methodName = _namer.instanceMethodName(member);
171 // When redirecting, we must ensure that we don't end up in a subclass. 161 // When redirecting, we must ensure that we don't end up in a subclass.
172 // We thus can't just invoke `this.foo$1.call(filledInArguments)`. 162 // We thus can't just invoke `this.foo$1.call(filledInArguments)`.
173 // Instead we need to call the statically resolved target. 163 // Instead we need to call the statically resolved target.
174 // `<class>.prototype.bar$1.call(this, argument0, ...)`. 164 // `<class>.prototype.bar$1.call(this, argument0, ...)`.
175 body = js.statement('return #.#.call(this, #);', [ 165 body = js.statement('return #.#.call(this, #);', [
176 _emitterTask.prototypeAccess(superClass, hasBeenInstantiated: true), 166 _emitterTask.prototypeAccess(superClass, hasBeenInstantiated: true),
177 methodName, 167 methodName,
178 argumentsBuffer 168 argumentsBuffer
179 ]); 169 ]);
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 generateParameterStub(member, selector, null); 307 generateParameterStub(member, selector, null);
318 if (stub != null) { 308 if (stub != null) {
319 stubs.add(stub); 309 stubs.add(stub);
320 } 310 }
321 } 311 }
322 } 312 }
323 313
324 return stubs; 314 return stubs;
325 } 315 }
326 } 316 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698