Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 /// This class should morph into something that makes it easy to build | 7 /// This class should morph into something that makes it easy to build |
| 8 /// JavaScript representations of libraries, class-sides, and instance-sides. | 8 /// JavaScript representations of libraries, class-sides, and instance-sides. |
| 9 /// Initially, it is just a placeholder for code that is moved from | 9 /// Initially, it is just a placeholder for code that is moved from |
| 10 /// [CodeEmitterTask]. | 10 /// [CodeEmitterTask]. |
| 11 class ContainerBuilder extends CodeEmitterHelper { | 11 class ContainerBuilder extends CodeEmitterHelper { |
| 12 final Set<Selector> emptySelectorSet = new Set<Selector>(); | |
| 13 | |
| 12 bool needsSuperGetter(FunctionElement element) => | 14 bool needsSuperGetter(FunctionElement element) => |
| 13 compiler.codegenWorld.methodsNeedingSuperGetter.contains(element); | 15 compiler.codegenWorld.methodsNeedingSuperGetter.contains(element); |
| 14 | 16 |
| 15 /** | 17 /** |
| 16 * Generate stubs to handle invocation of methods with optional | 18 * Generates stubs to handle invocation of methods with optional |
| 17 * arguments. | 19 * arguments. |
| 18 * | 20 * |
| 19 * A method like [: foo([x]) :] may be invoked by the following | 21 * A method like `foo([x])` may be invoked by the following |
| 20 * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this | 22 * calls: `foo(), foo(1), foo(x: 1)`. This method generates the stub for the |
| 21 * function for detailed examples. | 23 * given [selector] and returns the generated [AdapterStubMethod]. |
| 24 * | |
| 25 * Returns null if no stub is needed. | |
| 26 * | |
| 27 * Members may be invoked in two ways: directly, or through a closure. In the | |
| 28 * latter case the caller invokes the closure's `call` method. This method | |
| 29 * accepts two selectors. The returned stub method has the corresponding | |
| 30 * name [AdapterStubMethod.name] and/or [AdapterStubMethod.callName] set if | |
| 31 * the input selector is non-null (and the member needs an adapter). | |
| 22 */ | 32 */ |
| 23 void addParameterStub(FunctionElement member, | 33 AdapterStubMethod generateParameterStub(FunctionElement member, |
| 24 Selector selector, | 34 Selector selector, |
| 25 AddStubFunction addStub) { | 35 Selector callSelector) { |
| 26 FunctionSignature parameters = member.functionSignature; | 36 FunctionSignature parameters = member.functionSignature; |
| 27 int positionalArgumentCount = selector.positionalArgumentCount; | 37 int positionalArgumentCount = selector.positionalArgumentCount; |
| 28 if (positionalArgumentCount == parameters.parameterCount) { | 38 if (positionalArgumentCount == parameters.parameterCount) { |
| 29 assert(selector.namedArgumentCount == 0); | 39 assert(selector.namedArgumentCount == 0); |
| 30 return; | 40 return null; |
| 31 } | 41 } |
| 32 if (parameters.optionalParametersAreNamed | 42 if (parameters.optionalParametersAreNamed |
| 33 && selector.namedArgumentCount == parameters.optionalParameterCount) { | 43 && selector.namedArgumentCount == parameters.optionalParameterCount) { |
| 34 // If the selector has the same number of named arguments as the element, | 44 // If the selector has the same number of named arguments as the element, |
| 35 // we don't need to add a stub. The call site will hit the method | 45 // we don't need to add a stub. The call site will hit the method |
| 36 // directly. | 46 // directly. |
| 37 return; | 47 return null; |
| 38 } | 48 } |
| 39 JavaScriptConstantCompiler handler = backend.constants; | 49 JavaScriptConstantCompiler handler = backend.constants; |
| 40 List<String> names = selector.getOrderedNamedArguments(); | 50 List<String> names = selector.getOrderedNamedArguments(); |
| 41 | 51 |
| 42 bool isInterceptedMethod = backend.isInterceptedMethod(member); | 52 bool isInterceptedMethod = backend.isInterceptedMethod(member); |
| 43 | 53 |
| 44 // If the method is intercepted, we need to also pass the actual receiver. | 54 // If the method is intercepted, we need to also pass the actual receiver. |
| 45 int extraArgumentCount = isInterceptedMethod ? 1 : 0; | 55 int extraArgumentCount = isInterceptedMethod ? 1 : 0; |
| 46 // Use '$receiver' to avoid clashes with other parameter names. Using | 56 // Use '$receiver' to avoid clashes with other parameter names. Using |
| 47 // '$receiver' works because [:namer.safeName:] used for getting parameter | 57 // '$receiver' works because [:namer.safeName:] used for getting parameter |
| 48 // names never returns a name beginning with a single '$'. | 58 // names never returns a name beginning with a single '$'. |
| 49 String receiverArgumentName = r'$receiver'; | 59 String receiverArgumentName = r'$receiver'; |
| 50 | 60 |
| 51 // The parameters that this stub takes. | 61 // The parameters that this stub takes. |
| 52 List<jsAst.Parameter> parametersBuffer = | 62 List<jsAst.Parameter> parametersBuffer = |
| 53 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); | 63 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); |
| 54 // The arguments that will be passed to the real method. | 64 // The arguments that will be passed to the real method. |
| 55 List<jsAst.Expression> argumentsBuffer = | 65 List<jsAst.Expression> argumentsBuffer = |
| 56 new List<jsAst.Expression>( | 66 new List<jsAst.Expression>( |
| 57 parameters.parameterCount + extraArgumentCount); | 67 parameters.parameterCount + extraArgumentCount); |
| 58 String invocationName = namer.invocationName(selector); | 68 String invocationName = namer.invocationName(selector); |
| 59 | 69 |
| 60 int count = 0; | 70 int count = 0; |
| 61 if (isInterceptedMethod) { | 71 if (isInterceptedMethod) { |
| 62 count++; | 72 count++; |
| 63 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); | 73 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); |
| 64 argumentsBuffer[0] = js('#', receiverArgumentName); | 74 argumentsBuffer[0] = js('#', receiverArgumentName); |
| 65 emitter.interceptorEmitter.interceptorInvocationNames.add(invocationName); | |
| 66 } | 75 } |
| 67 | 76 |
| 68 int optionalParameterStart = positionalArgumentCount + extraArgumentCount; | 77 int optionalParameterStart = positionalArgumentCount + extraArgumentCount; |
| 69 // Includes extra receiver argument when using interceptor convention | 78 // Includes extra receiver argument when using interceptor convention |
| 70 int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1; | 79 int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1; |
| 71 | 80 |
| 72 int parameterIndex = 0; | 81 int parameterIndex = 0; |
| 73 parameters.orderedForEachParameter((ParameterElement element) { | 82 parameters.orderedForEachParameter((ParameterElement element) { |
| 74 String jsName = backend.namer.safeName(element.name); | 83 String jsName = backend.namer.safeName(element.name); |
| 75 assert(jsName != receiverArgumentName); | 84 assert(jsName != receiverArgumentName); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 129 'return this.#(#);', | 138 'return this.#(#);', |
| 130 [namer.getNameOfInstanceMember(member), argumentsBuffer]); | 139 [namer.getNameOfInstanceMember(member), argumentsBuffer]); |
| 131 } | 140 } |
| 132 } else { | 141 } else { |
| 133 body = js.statement('return #(#)', | 142 body = js.statement('return #(#)', |
| 134 [emitter.staticFunctionAccess(member), argumentsBuffer]); | 143 [emitter.staticFunctionAccess(member), argumentsBuffer]); |
| 135 } | 144 } |
| 136 | 145 |
| 137 jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]); | 146 jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]); |
| 138 | 147 |
| 139 addStub(selector, function); | 148 String name = namer.invocationName(selector); |
| 149 String callName = | |
| 150 (callSelector != null) ? namer.invocationName(callSelector) : null; | |
| 151 return new AdapterStubMethod(name, callName, function); | |
| 140 } | 152 } |
| 141 | 153 |
| 142 void addParameterStubs(FunctionElement member, AddStubFunction defineStub, | 154 // We fill the lists depending on possible/invoked selectors. For example, |
| 143 [bool canTearOff = false]) { | 155 // take method foo: |
| 156 // foo(a, b, {c, d}); | |
| 157 // | |
| 158 // We may have multiple ways of calling foo: | |
| 159 // (1) foo(1, 2); | |
| 160 // (2) foo(1, 2, c: 3); | |
| 161 // (3) foo(1, 2, d: 4); | |
| 162 // (4) foo(1, 2, c: 3, d: 4); | |
| 163 // (5) foo(1, 2, d: 4, c: 3); | |
| 164 // | |
| 165 // What we generate at the call sites are: | |
| 166 // (1) foo$2(1, 2); | |
| 167 // (2) foo$3$c(1, 2, 3); | |
| 168 // (3) foo$3$d(1, 2, 4); | |
| 169 // (4) foo$4$c$d(1, 2, 3, 4); | |
| 170 // (5) foo$4$c$d(1, 2, 3, 4); | |
| 171 // | |
| 172 // The stubs we generate are (expressed in Dart): | |
| 173 // (1) foo$2(a, b) => foo$4$c$d(a, b, null, null) | |
| 174 // (2) foo$3$c(a, b, c) => foo$4$c$d(a, b, c, null); | |
| 175 // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d); | |
| 176 // (4) No stub generated, call is direct. | |
| 177 // (5) No stub generated, call is direct. | |
| 178 // | |
| 179 // We need to pay attention if this stub is for a function that has been | |
| 180 // invoked from a subclass. Then we cannot just redirect, since that | |
| 181 // would invoke the methods of the subclass. We have to compile to: | |
| 182 // (1) foo$2(a, b) => MyClass.foo$4$c$d.call(this, a, b, null, null) | |
| 183 // (2) foo$3$c(a, b, c) => MyClass.foo$4$c$d(this, a, b, c, null); | |
| 184 // (3) foo$3$d(a, b, d) => MyClass.foo$4$c$d(this, a, b, null, d); | |
| 185 List<AdapterStubMethod> generateParameterStubs(FunctionElement member, | |
|
floitsch
2015/01/30 00:00:14
I'm sorry, but I couldn't resist rewriting this fu
| |
| 186 {bool canTearOff: true}) { | |
| 144 if (member.enclosingElement.isClosure) { | 187 if (member.enclosingElement.isClosure) { |
| 145 ClosureClassElement cls = member.enclosingElement; | 188 ClosureClassElement cls = member.enclosingElement; |
| 146 if (cls.supertype.element == backend.boundClosureClass) { | 189 if (cls.supertype.element == backend.boundClosureClass) { |
| 147 compiler.internalError(cls.methodElement, 'Bound closure1.'); | 190 compiler.internalError(cls.methodElement, 'Bound closure1.'); |
| 148 } | 191 } |
| 149 if (cls.methodElement.isInstanceMember) { | 192 if (cls.methodElement.isInstanceMember) { |
| 150 compiler.internalError(cls.methodElement, 'Bound closure2.'); | 193 compiler.internalError(cls.methodElement, 'Bound closure2.'); |
| 151 } | 194 } |
| 152 } | 195 } |
| 153 | 196 |
| 154 // We fill the lists depending on the selector. For example, | 197 // The set of selectors that apply to `member`. For example, for |
| 155 // take method foo: | 198 // a member `foo(x, [y])` the following selectors may apply: |
| 156 // foo(a, b, {c, d}); | 199 // `foo(x)`, and `foo(x, y)`. |
| 200 Set<Selector> selectors; | |
| 201 // The set of selectors that apply to `member` if it's name was `call`. | |
| 202 // This happens when a member is torn-off. In that case calls to the | |
| 203 // function use the name `call`, and we must be able to handle every | |
| 204 // `call` invocation that matches the signature. For example, for | |
| 205 // a member `foo(x, [y])` the following selectors would be possible | |
| 206 // call-selectors: `call(x)`, and `call(x, y)`. | |
| 207 Set<Selector> callSelectors; | |
| 208 | |
| 209 // Only instance members (not static methods) need stubs. | |
| 210 if (member.isInstanceMember) { | |
| 211 selectors = compiler.codegenWorld.invokedNames[member.name]; | |
| 212 } | |
| 213 | |
| 214 if (canTearOff) { | |
| 215 String call = namer.closureInvocationSelectorName; | |
| 216 callSelectors = compiler.codegenWorld.invokedNames[call]; | |
| 217 } | |
| 218 | |
| 219 assert(emptySelectorSet.isEmpty); | |
| 220 if (selectors == null) selectors = emptySelectorSet; | |
| 221 if (callSelectors == null) callSelectors = emptySelectorSet; | |
| 222 | |
| 223 List<AdapterStubMethod> adapters = <AdapterStubMethod>[]; | |
| 224 | |
| 225 if (selectors.isEmpty && callSelectors.isEmpty) { | |
| 226 return adapters; | |
| 227 } | |
| 228 | |
| 229 // For every call-selector the corresponding selector with the name of the | |
| 230 // member. | |
| 157 // | 231 // |
| 158 // We may have multiple ways of calling foo: | 232 // For example, for the call-selector `call(x, y)` the renamed selector |
| 159 // (1) foo(1, 2); | 233 // for member `foo` would be `foo(x, y)`. |
| 160 // (2) foo(1, 2, c: 3); | 234 Set<Selector> renamedCallSelectors = |
| 161 // (3) foo(1, 2, d: 4); | 235 callSelectors.isEmpty ? emptySelectorSet : new Set<Selector>(); |
| 162 // (4) foo(1, 2, c: 3, d: 4); | |
| 163 // (5) foo(1, 2, d: 4, c: 3); | |
| 164 // | |
| 165 // What we generate at the call sites are: | |
| 166 // (1) foo$2(1, 2); | |
| 167 // (2) foo$3$c(1, 2, 3); | |
| 168 // (3) foo$3$d(1, 2, 4); | |
| 169 // (4) foo$4$c$d(1, 2, 3, 4); | |
| 170 // (5) foo$4$c$d(1, 2, 3, 4); | |
| 171 // | |
| 172 // The stubs we generate are (expressed in Dart): | |
| 173 // (1) foo$2(a, b) => foo$4$c$d(a, b, null, null) | |
| 174 // (2) foo$3$c(a, b, c) => foo$4$c$d(a, b, c, null); | |
| 175 // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d); | |
| 176 // (4) No stub generated, call is direct. | |
| 177 // (5) No stub generated, call is direct. | |
| 178 // | |
| 179 // We need to pay attention if this stub is for a function that has been | |
| 180 // invoked from a subclass. Then we cannot just redirect, since that | |
| 181 // would invoke the methods of the subclass. We have to compile to: | |
| 182 // (1) foo$2(a, b) => MyClass.foo$4$c$d.call(this, a, b, null, null) | |
| 183 // (2) foo$3$c(a, b, c) => MyClass.foo$4$c$d(this, a, b, c, null); | |
| 184 // (3) foo$3$d(a, b, d) => MyClass.foo$4$c$d(this, a, b, null, d); | |
| 185 | 236 |
| 186 Set<Selector> selectors = member.isInstanceMember | 237 Set<Selector> untypedSelectors = new Set<Selector>(); |
| 187 ? compiler.codegenWorld.invokedNames[member.name] | |
| 188 : null; // No stubs needed for static methods. | |
| 189 | 238 |
| 190 /// Returns all closure call selectors renamed to match this member. | 239 // Start with the callSelectors since they imply the generation of the |
| 191 Set<Selector> callSelectorsAsNamed() { | 240 // non-call version. |
| 192 if (!canTearOff) return null; | 241 for (Selector selector in callSelectors) { |
| 193 Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[ | 242 Selector renamedSelector = new Selector.call( |
| 194 namer.closureInvocationSelectorName]; | 243 member.name, member.library, |
| 195 if (callSelectors == null) return null; | 244 selector.argumentCount, selector.namedArguments); |
| 196 return callSelectors.map((Selector callSelector) { | 245 renamedCallSelectors.add(renamedSelector); |
| 197 return new Selector.call( | 246 |
| 198 member.name, member.library, | 247 if (!renamedSelector.appliesUnnamed(member, compiler.world)) continue; |
| 199 callSelector.argumentCount, callSelector.namedArguments); | 248 |
| 200 }).toSet(); | 249 if (untypedSelectors.add(renamedSelector.asUntyped)) { |
| 201 } | 250 AdapterStubMethod adapter = |
| 202 if (selectors == null) { | 251 generateParameterStub(member, renamedSelector, selector); |
| 203 selectors = callSelectorsAsNamed(); | 252 if (adapter != null) { |
| 204 if (selectors == null) return; | 253 adapters.add(adapter); |
| 205 } else { | |
| 206 Set<Selector> callSelectors = callSelectorsAsNamed(); | |
| 207 if (callSelectors != null) { | |
| 208 selectors = selectors.union(callSelectors); | |
| 209 } | |
| 210 } | |
| 211 Set<Selector> untypedSelectors = new Set<Selector>(); | |
| 212 if (selectors != null) { | |
| 213 for (Selector selector in selectors) { | |
| 214 if (!selector.appliesUnnamed(member, compiler.world)) continue; | |
| 215 if (untypedSelectors.add(selector.asUntyped)) { | |
| 216 addParameterStub(member, selector, defineStub); | |
| 217 } | 254 } |
| 218 } | 255 } |
| 219 } | 256 } |
| 220 if (canTearOff) { | 257 |
| 221 selectors = compiler.codegenWorld.invokedNames[ | 258 // Now run through the actual member selectors (eg. `foo$2(x, y)` and not |
| 222 namer.closureInvocationSelectorName]; | 259 // `call$2(x, y)`. Some of them have already been generated because of the |
| 223 if (selectors != null) { | 260 // call-selectors (and they are in the renamedCallSelectors set. |
| 224 for (Selector selector in selectors) { | 261 for (Selector selector in selectors) { |
| 225 selector = new Selector.call( | 262 if (renamedCallSelectors.contains(selector)) continue; |
| 226 member.name, member.library, | 263 if (!selector.appliesUnnamed(member, compiler.world)) continue; |
| 227 selector.argumentCount, selector.namedArguments); | 264 |
| 228 if (!selector.appliesUnnamed(member, compiler.world)) continue; | 265 if (untypedSelectors.add(selector.asUntyped)) { |
| 229 if (untypedSelectors.add(selector)) { | 266 AdapterStubMethod adapter = |
| 230 addParameterStub(member, selector, defineStub); | 267 generateParameterStub(member, selector, null); |
| 231 } | 268 if (adapter != null) { |
| 269 adapters.add(adapter); | |
| 232 } | 270 } |
| 233 } | 271 } |
| 234 } | 272 } |
| 273 | |
| 274 return adapters; | |
| 235 } | 275 } |
| 236 | 276 |
| 237 void addMemberMethod(DartMethod method, ClassBuilder builder) { | 277 void addMemberMethod(DartMethod method, ClassBuilder builder) { |
| 238 final FunctionElement member = method.element; | 278 final FunctionElement member = method.element; |
| 239 String name = method.name; | 279 String name = method.name; |
| 240 final FunctionSignature parameters = member.functionSignature; | 280 final FunctionSignature parameters = member.functionSignature; |
| 241 jsAst.Expression code = method.code; | 281 jsAst.Expression code = method.code; |
| 242 final bool needsStubs = method.needsStubs; | 282 final bool needsStubs = method.needsStubs; |
| 243 final bool canTearOff = method.needsTearOff; | 283 final bool canTearOff = method.needsTearOff; |
| 244 final String tearOffName = method.tearOffName; | 284 final String tearOffName = method.tearOffName; |
| 245 final bool canBeReflected = method.canBeReflected; | 285 final bool canBeReflected = method.canBeReflected; |
| 246 final bool canBeApplied = method.canBeApplied; | 286 final bool canBeApplied = method.canBeApplied; |
| 247 final bool isClosure = method is InstanceMethod && method.isClosure; | 287 final bool isClosure = method is InstanceMethod && method.isClosure; |
| 248 final bool hasSuperAlias = method is InstanceMethod && method.hasSuperAlias; | 288 final bool hasSuperAlias = method is InstanceMethod && method.hasSuperAlias; |
| 249 | 289 |
| 250 final bool needStructuredInfo = | 290 final bool needStructuredInfo = |
| 251 canTearOff || canBeReflected || canBeApplied || hasSuperAlias; | 291 canTearOff || canBeReflected || canBeApplied || hasSuperAlias; |
| 252 | 292 |
| 253 emitter.interceptorEmitter.recordMangledNameOfMemberMethod(member, name); | 293 emitter.interceptorEmitter.recordMangledNameOfMemberMethod(member, name); |
| 254 | 294 |
| 255 if (!needStructuredInfo) { | 295 if (!needStructuredInfo) { |
| 256 compiler.dumpInfoTask.registerElementAst(member, | 296 compiler.dumpInfoTask.registerElementAst(member, |
| 257 builder.addProperty(name, code)); | 297 builder.addProperty(name, code)); |
| 258 if (needsStubs) { | 298 if (needsStubs) { |
| 259 addParameterStubs( | 299 for (AdapterStubMethod adapter in |
| 260 member, | 300 generateParameterStubs(member, canTearOff: false)) { |
| 261 (Selector selector, jsAst.Fun function) { | 301 assert(adapter.callName == null); |
| 262 compiler.dumpInfoTask.registerElementAst(member, | 302 String invocationName = adapter.name; |
| 263 builder.addProperty(namer.invocationName(selector), | 303 emitter.interceptorEmitter |
| 264 function)); | 304 .recordMangledNameOfMemberMethod(member, invocationName); |
| 265 }); | 305 compiler.dumpInfoTask.registerElementAst( |
| 306 member, builder.addProperty(invocationName, adapter.code)); | |
| 307 } | |
| 266 } | 308 } |
| 267 return; | 309 return; |
| 268 } | 310 } |
| 269 emitter.needsStructuredMemberInfo = true; | 311 emitter.needsStructuredMemberInfo = true; |
| 270 | 312 |
| 271 // This element is needed for reflection or needs additional stubs or has a | 313 // This element is needed for reflection or needs additional stubs or has a |
| 272 // super alias. So we need to retain additional information. | 314 // super alias. So we need to retain additional information. |
| 273 | 315 |
| 274 // The information is stored in an array with this format: | 316 // The information is stored in an array with this format: |
| 275 // | 317 // |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 int requiredParameterCount = parameters.requiredParameterCount << 1; | 370 int requiredParameterCount = parameters.requiredParameterCount << 1; |
| 329 if (member.isAccessor) requiredParameterCount++; | 371 if (member.isAccessor) requiredParameterCount++; |
| 330 | 372 |
| 331 int optionalParameterCount = parameters.optionalParameterCount << 1; | 373 int optionalParameterCount = parameters.optionalParameterCount << 1; |
| 332 if (parameters.optionalParametersAreNamed) optionalParameterCount++; | 374 if (parameters.optionalParametersAreNamed) optionalParameterCount++; |
| 333 | 375 |
| 334 // TODO(sra): Don't use LiteralString for non-strings. | 376 // TODO(sra): Don't use LiteralString for non-strings. |
| 335 List tearOffInfo = [new jsAst.LiteralString(callSelectorString)]; | 377 List tearOffInfo = [new jsAst.LiteralString(callSelectorString)]; |
| 336 | 378 |
| 337 if (needsStubs || canTearOff) { | 379 if (needsStubs || canTearOff) { |
| 338 addParameterStubs(member, (Selector selector, jsAst.Fun function) { | 380 for (AdapterStubMethod adapter in |
| 339 expressions.add(function); | 381 generateParameterStubs(member, canTearOff: canTearOff)) { |
| 382 String invocationName = adapter.name; | |
| 383 emitter.interceptorEmitter | |
| 384 .recordMangledNameOfMemberMethod(member, invocationName); | |
| 385 | |
| 386 expressions.add(adapter.code); | |
| 340 if (member.isInstanceMember) { | 387 if (member.isInstanceMember) { |
| 341 Set invokedSelectors = | 388 expressions.add(js.string(invocationName)); |
| 342 compiler.codegenWorld.invokedNames[member.name]; | |
| 343 expressions.add(js.string(namer.invocationName(selector))); | |
| 344 } else { | 389 } else { |
| 390 // TOOD(floitsch): Since we know when reading static data versus | |
| 391 // instance data, we can eliminate this element. | |
| 345 expressions.add(js('null')); | 392 expressions.add(js('null')); |
| 346 // TOOD(ahe): Since we know when reading static data versus instance | |
| 347 // data, we can eliminate this element. | |
| 348 } | 393 } |
| 349 Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[ | 394 String callName = adapter.callName; |
| 350 namer.closureInvocationSelectorName]; | 395 String callSelectorString = (callName == null) ? 'null' : '"$callName"'; |
| 351 Selector callSelector = selector.toCallSelector(); | |
| 352 String callSelectorString = 'null'; | |
| 353 if (canTearOff && callSelectors != null && | |
| 354 callSelectors.contains(callSelector)) { | |
| 355 callSelectorString = '"${namer.invocationName(callSelector)}"'; | |
| 356 } | |
| 357 tearOffInfo.add(new jsAst.LiteralString(callSelectorString)); | 396 tearOffInfo.add(new jsAst.LiteralString(callSelectorString)); |
| 358 }, canTearOff); | 397 } |
| 359 } | 398 } |
| 360 | |
| 361 jsAst.Expression memberTypeExpression; | 399 jsAst.Expression memberTypeExpression; |
| 362 if (canTearOff || canBeReflected) { | 400 if (canTearOff || canBeReflected) { |
| 363 DartType memberType; | 401 DartType memberType; |
| 364 if (member.isGenerativeConstructorBody) { | 402 if (member.isGenerativeConstructorBody) { |
| 365 var body = member; | 403 var body = member; |
| 366 memberType = body.constructor.type; | 404 memberType = body.constructor.type; |
| 367 } else { | 405 } else { |
| 368 memberType = member.type; | 406 memberType = member.type; |
| 369 } | 407 } |
| 370 if (memberType.containsTypeVariables) { | 408 if (memberType.containsTypeVariables) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 429 jsAst.ArrayInitializer arrayInit = | 467 jsAst.ArrayInitializer arrayInit = |
| 430 new jsAst.ArrayInitializer(expressions.toList()); | 468 new jsAst.ArrayInitializer(expressions.toList()); |
| 431 compiler.dumpInfoTask.registerElementAst(member, | 469 compiler.dumpInfoTask.registerElementAst(member, |
| 432 builder.addProperty(name, arrayInit)); | 470 builder.addProperty(name, arrayInit)); |
| 433 } | 471 } |
| 434 | 472 |
| 435 void addMemberField(Field field, ClassBuilder builder) { | 473 void addMemberField(Field field, ClassBuilder builder) { |
| 436 // For now, do nothing. | 474 // For now, do nothing. |
| 437 } | 475 } |
| 438 } | 476 } |
| OLD | NEW |