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

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

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