| 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]. |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 indexOfLastOptionalArgumentInParameters = count; | 109 indexOfLastOptionalArgumentInParameters = count; |
| 110 } | 110 } |
| 111 argumentsBuffer[count] = task.constantReference(value); | 111 argumentsBuffer[count] = task.constantReference(value); |
| 112 } | 112 } |
| 113 } | 113 } |
| 114 } | 114 } |
| 115 count++; | 115 count++; |
| 116 }); | 116 }); |
| 117 | 117 |
| 118 var body; // List or jsAst.Statement. | 118 var body; // List or jsAst.Statement. |
| 119 if (member.hasFixedBackendName()) { | 119 if (member.hasFixedBackendName) { |
| 120 body = task.nativeEmitter.generateParameterStubStatements( | 120 body = task.nativeEmitter.generateParameterStubStatements( |
| 121 member, isInterceptedMethod, invocationName, | 121 member, isInterceptedMethod, invocationName, |
| 122 parametersBuffer, argumentsBuffer, | 122 parametersBuffer, argumentsBuffer, |
| 123 indexOfLastOptionalArgumentInParameters); | 123 indexOfLastOptionalArgumentInParameters); |
| 124 } else if (member.isInstanceMember()) { | 124 } else if (member.isInstanceMember) { |
| 125 if (needsSuperGetter(member)) { | 125 if (needsSuperGetter(member)) { |
| 126 ClassElement superClass = member.getEnclosingClass(); | 126 ClassElement superClass = member.enclosingClass; |
| 127 String methodName = namer.getNameOfInstanceMember(member); | 127 String methodName = namer.getNameOfInstanceMember(member); |
| 128 // When redirecting, we must ensure that we don't end up in a subclass. | 128 // When redirecting, we must ensure that we don't end up in a subclass. |
| 129 // We thus can't just invoke `this.foo$1.call(filledInArguments)`. | 129 // We thus can't just invoke `this.foo$1.call(filledInArguments)`. |
| 130 // Instead we need to call the statically resolved target. | 130 // Instead we need to call the statically resolved target. |
| 131 // `<class>.prototype.bar$1.call(this, argument0, ...)`. | 131 // `<class>.prototype.bar$1.call(this, argument0, ...)`. |
| 132 body = js.statement( | 132 body = js.statement( |
| 133 'return #.prototype.#.call(this, #);', | 133 'return #.prototype.#.call(this, #);', |
| 134 [backend.namer.elementAccess(superClass), methodName, | 134 [backend.namer.elementAccess(superClass), methodName, |
| 135 argumentsBuffer]); | 135 argumentsBuffer]); |
| 136 } else { | 136 } else { |
| 137 body = js.statement( | 137 body = js.statement( |
| 138 'return this.#(#);', | 138 'return this.#(#);', |
| 139 [namer.getNameOfInstanceMember(member), argumentsBuffer]); | 139 [namer.getNameOfInstanceMember(member), argumentsBuffer]); |
| 140 } | 140 } |
| 141 } else { | 141 } else { |
| 142 body = js.statement('return #(#)', | 142 body = js.statement('return #(#)', |
| 143 [namer.elementAccess(member), argumentsBuffer]); | 143 [namer.elementAccess(member), argumentsBuffer]); |
| 144 } | 144 } |
| 145 | 145 |
| 146 jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]); | 146 jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]); |
| 147 | 147 |
| 148 addStub(selector, function); | 148 addStub(selector, function); |
| 149 } | 149 } |
| 150 | 150 |
| 151 void addParameterStubs(FunctionElement member, AddStubFunction defineStub, | 151 void addParameterStubs(FunctionElement member, AddStubFunction defineStub, |
| 152 [bool canTearOff = false]) { | 152 [bool canTearOff = false]) { |
| 153 if (member.enclosingElement.isClosure()) { | 153 if (member.enclosingElement.isClosure) { |
| 154 ClosureClassElement cls = member.enclosingElement; | 154 ClosureClassElement cls = member.enclosingElement; |
| 155 if (cls.supertype.element == compiler.boundClosureClass) { | 155 if (cls.supertype.element == compiler.boundClosureClass) { |
| 156 compiler.internalError(cls.methodElement, 'Bound closure1.'); | 156 compiler.internalError(cls.methodElement, 'Bound closure1.'); |
| 157 } | 157 } |
| 158 if (cls.methodElement.isInstanceMember()) { | 158 if (cls.methodElement.isInstanceMember) { |
| 159 compiler.internalError(cls.methodElement, 'Bound closure2.'); | 159 compiler.internalError(cls.methodElement, 'Bound closure2.'); |
| 160 } | 160 } |
| 161 } | 161 } |
| 162 | 162 |
| 163 // We fill the lists depending on the selector. For example, | 163 // We fill the lists depending on the selector. For example, |
| 164 // take method foo: | 164 // take method foo: |
| 165 // foo(a, b, {c, d}); | 165 // foo(a, b, {c, d}); |
| 166 // | 166 // |
| 167 // We may have multiple ways of calling foo: | 167 // We may have multiple ways of calling foo: |
| 168 // (1) foo(1, 2); | 168 // (1) foo(1, 2); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 185 // (4) No stub generated, call is direct. | 185 // (4) No stub generated, call is direct. |
| 186 // (5) No stub generated, call is direct. | 186 // (5) No stub generated, call is direct. |
| 187 // | 187 // |
| 188 // We need to pay attention if this stub is for a function that has been | 188 // We need to pay attention if this stub is for a function that has been |
| 189 // invoked from a subclass. Then we cannot just redirect, since that | 189 // invoked from a subclass. Then we cannot just redirect, since that |
| 190 // would invoke the methods of the subclass. We have to compile to: | 190 // would invoke the methods of the subclass. We have to compile to: |
| 191 // (1) foo$2(a, b) => MyClass.foo$4$c$d.call(this, a, b, null, null) | 191 // (1) foo$2(a, b) => MyClass.foo$4$c$d.call(this, a, b, null, null) |
| 192 // (2) foo$3$c(a, b, c) => MyClass.foo$4$c$d(this, a, b, c, null); | 192 // (2) foo$3$c(a, b, c) => MyClass.foo$4$c$d(this, a, b, c, null); |
| 193 // (3) foo$3$d(a, b, d) => MyClass.foo$4$c$d(this, a, b, null, d); | 193 // (3) foo$3$d(a, b, d) => MyClass.foo$4$c$d(this, a, b, null, d); |
| 194 | 194 |
| 195 Set<Selector> selectors = member.isInstanceMember() | 195 Set<Selector> selectors = member.isInstanceMember |
| 196 ? compiler.codegenWorld.invokedNames[member.name] | 196 ? compiler.codegenWorld.invokedNames[member.name] |
| 197 : null; // No stubs needed for static methods. | 197 : null; // No stubs needed for static methods. |
| 198 | 198 |
| 199 /// Returns all closure call selectors renamed to match this member. | 199 /// Returns all closure call selectors renamed to match this member. |
| 200 Set<Selector> callSelectorsAsNamed() { | 200 Set<Selector> callSelectorsAsNamed() { |
| 201 if (!canTearOff) return null; | 201 if (!canTearOff) return null; |
| 202 Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[ | 202 Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[ |
| 203 namer.closureInvocationSelectorName]; | 203 namer.closureInvocationSelectorName]; |
| 204 if (callSelectors == null) return null; | 204 if (callSelectors == null) return null; |
| 205 return callSelectors.map((Selector callSelector) { | 205 return callSelectors.map((Selector callSelector) { |
| 206 return new Selector.call( | 206 return new Selector.call( |
| 207 member.name, member.getLibrary(), | 207 member.name, member.library, |
| 208 callSelector.argumentCount, callSelector.namedArguments); | 208 callSelector.argumentCount, callSelector.namedArguments); |
| 209 }).toSet(); | 209 }).toSet(); |
| 210 } | 210 } |
| 211 if (selectors == null) { | 211 if (selectors == null) { |
| 212 selectors = callSelectorsAsNamed(); | 212 selectors = callSelectorsAsNamed(); |
| 213 if (selectors == null) return; | 213 if (selectors == null) return; |
| 214 } else { | 214 } else { |
| 215 Set<Selector> callSelectors = callSelectorsAsNamed(); | 215 Set<Selector> callSelectors = callSelectorsAsNamed(); |
| 216 if (callSelectors != null) { | 216 if (callSelectors != null) { |
| 217 selectors = selectors.union(callSelectors); | 217 selectors = selectors.union(callSelectors); |
| 218 } | 218 } |
| 219 } | 219 } |
| 220 Set<Selector> untypedSelectors = new Set<Selector>(); | 220 Set<Selector> untypedSelectors = new Set<Selector>(); |
| 221 if (selectors != null) { | 221 if (selectors != null) { |
| 222 for (Selector selector in selectors) { | 222 for (Selector selector in selectors) { |
| 223 if (!selector.appliesUnnamed(member, compiler)) continue; | 223 if (!selector.appliesUnnamed(member, compiler)) continue; |
| 224 if (untypedSelectors.add(selector.asUntyped)) { | 224 if (untypedSelectors.add(selector.asUntyped)) { |
| 225 // TODO(ahe): Is the last argument to [addParameterStub] needed? | 225 // TODO(ahe): Is the last argument to [addParameterStub] needed? |
| 226 addParameterStub(member, selector, defineStub, new Set<String>()); | 226 addParameterStub(member, selector, defineStub, new Set<String>()); |
| 227 } | 227 } |
| 228 } | 228 } |
| 229 } | 229 } |
| 230 if (canTearOff) { | 230 if (canTearOff) { |
| 231 selectors = compiler.codegenWorld.invokedNames[ | 231 selectors = compiler.codegenWorld.invokedNames[ |
| 232 namer.closureInvocationSelectorName]; | 232 namer.closureInvocationSelectorName]; |
| 233 if (selectors != null) { | 233 if (selectors != null) { |
| 234 for (Selector selector in selectors) { | 234 for (Selector selector in selectors) { |
| 235 selector = new Selector.call( | 235 selector = new Selector.call( |
| 236 member.name, member.getLibrary(), | 236 member.name, member.library, |
| 237 selector.argumentCount, selector.namedArguments); | 237 selector.argumentCount, selector.namedArguments); |
| 238 if (!selector.appliesUnnamed(member, compiler)) continue; | 238 if (!selector.appliesUnnamed(member, compiler)) continue; |
| 239 if (untypedSelectors.add(selector)) { | 239 if (untypedSelectors.add(selector)) { |
| 240 // TODO(ahe): Is the last argument to [addParameterStub] needed? | 240 // TODO(ahe): Is the last argument to [addParameterStub] needed? |
| 241 addParameterStub(member, selector, defineStub, new Set<String>()); | 241 addParameterStub(member, selector, defineStub, new Set<String>()); |
| 242 } | 242 } |
| 243 } | 243 } |
| 244 } | 244 } |
| 245 } | 245 } |
| 246 } | 246 } |
| 247 | 247 |
| 248 /** | 248 /** |
| 249 * Documentation wanted -- johnniwinther | 249 * Documentation wanted -- johnniwinther |
| 250 * | 250 * |
| 251 * Invariant: [member] must be a declaration element. | 251 * Invariant: [member] must be a declaration element. |
| 252 */ | 252 */ |
| 253 void emitCallStubForGetter(Element member, | 253 void emitCallStubForGetter(Element member, |
| 254 Set<Selector> selectors, | 254 Set<Selector> selectors, |
| 255 AddPropertyFunction addProperty) { | 255 AddPropertyFunction addProperty) { |
| 256 assert(invariant(member, member.isDeclaration)); | 256 assert(invariant(member, member.isDeclaration)); |
| 257 LibraryElement memberLibrary = member.getLibrary(); | 257 LibraryElement memberLibrary = member.library; |
| 258 // If the method is intercepted, the stub gets the | 258 // If the method is intercepted, the stub gets the |
| 259 // receiver explicitely and we need to pass it to the getter call. | 259 // receiver explicitely and we need to pass it to the getter call. |
| 260 bool isInterceptedMethod = backend.isInterceptedMethod(member); | 260 bool isInterceptedMethod = backend.isInterceptedMethod(member); |
| 261 bool isInterceptorClass = | 261 bool isInterceptorClass = |
| 262 backend.isInterceptorClass(member.getEnclosingClass()); | 262 backend.isInterceptorClass(member.enclosingClass); |
| 263 | 263 |
| 264 const String receiverArgumentName = r'$receiver'; | 264 const String receiverArgumentName = r'$receiver'; |
| 265 | 265 |
| 266 jsAst.Expression buildGetter() { | 266 jsAst.Expression buildGetter() { |
| 267 jsAst.Expression receiver = | 267 jsAst.Expression receiver = |
| 268 js(isInterceptorClass ? receiverArgumentName : 'this'); | 268 js(isInterceptorClass ? receiverArgumentName : 'this'); |
| 269 if (member.isGetter()) { | 269 if (member.isGetter) { |
| 270 String getterName = namer.getterName(member); | 270 String getterName = namer.getterName(member); |
| 271 if (isInterceptedMethod) { | 271 if (isInterceptedMethod) { |
| 272 return js('this.#(#)', [getterName, receiver]); | 272 return js('this.#(#)', [getterName, receiver]); |
| 273 } | 273 } |
| 274 return js('#.#()', [receiver, getterName]); | 274 return js('#.#()', [receiver, getterName]); |
| 275 } else { | 275 } else { |
| 276 String fieldName = namer.instanceFieldPropertyName(member); | 276 String fieldName = namer.instanceFieldPropertyName(member); |
| 277 return js('#.#', [receiver, fieldName]); | 277 return js('#.#', [receiver, fieldName]); |
| 278 } | 278 } |
| 279 } | 279 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 } | 313 } |
| 314 } | 314 } |
| 315 | 315 |
| 316 /** | 316 /** |
| 317 * Documentation wanted -- johnniwinther | 317 * Documentation wanted -- johnniwinther |
| 318 * | 318 * |
| 319 * Invariant: [member] must be a declaration element. | 319 * Invariant: [member] must be a declaration element. |
| 320 */ | 320 */ |
| 321 void emitExtraAccessors(Element member, ClassBuilder builder) { | 321 void emitExtraAccessors(Element member, ClassBuilder builder) { |
| 322 assert(invariant(member, member.isDeclaration)); | 322 assert(invariant(member, member.isDeclaration)); |
| 323 if (member.isGetter() || member.isField()) { | 323 if (member.isGetter || member.isField) { |
| 324 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; | 324 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
| 325 if (selectors != null && !selectors.isEmpty) { | 325 if (selectors != null && !selectors.isEmpty) { |
| 326 emitCallStubForGetter(member, selectors, builder.addProperty); | 326 emitCallStubForGetter(member, selectors, builder.addProperty); |
| 327 } | 327 } |
| 328 } | 328 } |
| 329 } | 329 } |
| 330 | 330 |
| 331 void addMember(Element member, ClassBuilder builder) { | 331 void addMember(Element member, ClassBuilder builder) { |
| 332 assert(invariant(member, member.isDeclaration)); | 332 assert(invariant(member, member.isDeclaration)); |
| 333 | 333 |
| 334 if (member.isField()) { | 334 if (member.isField) { |
| 335 addMemberField(member, builder); | 335 addMemberField(member, builder); |
| 336 } else if (member.isFunction() || | 336 } else if (member.isFunction || |
| 337 member.isGenerativeConstructorBody() || | 337 member.isGenerativeConstructorBody || |
| 338 member.isGenerativeConstructor() || | 338 member.isGenerativeConstructor || |
| 339 member.isAccessor()) { | 339 member.isAccessor) { |
| 340 addMemberMethod(member, builder); | 340 addMemberMethod(member, builder); |
| 341 } else { | 341 } else { |
| 342 compiler.internalError(member, | 342 compiler.internalError(member, |
| 343 'Unexpected kind: "${member.kind}".'); | 343 'Unexpected kind: "${member.kind}".'); |
| 344 } | 344 } |
| 345 if (member.isInstanceMember()) emitExtraAccessors(member, builder); | 345 if (member.isInstanceMember) emitExtraAccessors(member, builder); |
| 346 } | 346 } |
| 347 | 347 |
| 348 void addMemberMethod(FunctionElement member, ClassBuilder builder) { | 348 void addMemberMethod(FunctionElement member, ClassBuilder builder) { |
| 349 if (member.isAbstract) return; | 349 if (member.isAbstract) return; |
| 350 jsAst.Expression code = backend.generatedCode[member]; | 350 jsAst.Expression code = backend.generatedCode[member]; |
| 351 if (code == null) return; | 351 if (code == null) return; |
| 352 String name = namer.getNameOfMember(member); | 352 String name = namer.getNameOfMember(member); |
| 353 task.interceptorEmitter.recordMangledNameOfMemberMethod(member, name); | 353 task.interceptorEmitter.recordMangledNameOfMemberMethod(member, name); |
| 354 FunctionSignature parameters = member.functionSignature; | 354 FunctionSignature parameters = member.functionSignature; |
| 355 bool needsStubs = !parameters.optionalParameters.isEmpty; | 355 bool needsStubs = !parameters.optionalParameters.isEmpty; |
| 356 bool canTearOff = false; | 356 bool canTearOff = false; |
| 357 bool isClosure = false; | 357 bool isClosure = false; |
| 358 bool isNotApplyTarget = !member.isFunction() || | 358 bool isNotApplyTarget = !member.isFunction || |
| 359 member.isConstructor() || | 359 member.isConstructor || |
| 360 member.isAccessor(); | 360 member.isAccessor; |
| 361 String tearOffName; | 361 String tearOffName; |
| 362 if (isNotApplyTarget) { | 362 if (isNotApplyTarget) { |
| 363 canTearOff = false; | 363 canTearOff = false; |
| 364 } else if (member.isInstanceMember()) { | 364 } else if (member.isInstanceMember) { |
| 365 if (member.getEnclosingClass().isClosure()) { | 365 if (member.enclosingClass.isClosure) { |
| 366 canTearOff = false; | 366 canTearOff = false; |
| 367 isClosure = true; | 367 isClosure = true; |
| 368 } else { | 368 } else { |
| 369 // Careful with operators. | 369 // Careful with operators. |
| 370 canTearOff = compiler.codegenWorld.hasInvokedGetter(member, compiler); | 370 canTearOff = compiler.codegenWorld.hasInvokedGetter(member, compiler); |
| 371 assert(!needsSuperGetter(member) || canTearOff); | 371 assert(!needsSuperGetter(member) || canTearOff); |
| 372 tearOffName = namer.getterName(member); | 372 tearOffName = namer.getterName(member); |
| 373 } | 373 } |
| 374 } else { | 374 } else { |
| 375 canTearOff = | 375 canTearOff = |
| (...skipping 12 matching lines...) Expand all Loading... |
| 388 addParameterStubs( | 388 addParameterStubs( |
| 389 member, | 389 member, |
| 390 (Selector selector, jsAst.Fun function) { | 390 (Selector selector, jsAst.Fun function) { |
| 391 builder.addProperty(namer.invocationName(selector), function); | 391 builder.addProperty(namer.invocationName(selector), function); |
| 392 }); | 392 }); |
| 393 } | 393 } |
| 394 return; | 394 return; |
| 395 } | 395 } |
| 396 | 396 |
| 397 if (canTearOff) { | 397 if (canTearOff) { |
| 398 assert(invariant(member, !member.isGenerativeConstructor())); | 398 assert(invariant(member, !member.isGenerativeConstructor)); |
| 399 assert(invariant(member, !member.isGenerativeConstructorBody())); | 399 assert(invariant(member, !member.isGenerativeConstructorBody)); |
| 400 assert(invariant(member, !member.isConstructor())); | 400 assert(invariant(member, !member.isConstructor)); |
| 401 } | 401 } |
| 402 | 402 |
| 403 // This element is needed for reflection or needs additional stubs. So we | 403 // This element is needed for reflection or needs additional stubs. So we |
| 404 // need to retain additional information. | 404 // need to retain additional information. |
| 405 | 405 |
| 406 // The information is stored in an array with this format: | 406 // The information is stored in an array with this format: |
| 407 // | 407 // |
| 408 // 1. The JS function for this member. | 408 // 1. The JS function for this member. |
| 409 // 2. First stub. | 409 // 2. First stub. |
| 410 // 3. Name of first stub. | 410 // 3. Name of first stub. |
| 411 // ... | 411 // ... |
| 412 // M. Call name of this member. | 412 // M. Call name of this member. |
| 413 // M+1. Call name of first stub. | 413 // M+1. Call name of first stub. |
| 414 // ... | 414 // ... |
| 415 // N. Getter name for tearOff. | 415 // N. Getter name for tearOff. |
| 416 // N+1. (Required parameter count << 1) + (member.isAccessor() ? 1 : 0). | 416 // N+1. (Required parameter count << 1) + (member.isAccessor ? 1 : 0). |
| 417 // N+2. (Optional parameter count << 1) + | 417 // N+2. (Optional parameter count << 1) + |
| 418 // (parameters.optionalParametersAreNamed ? 1 : 0). | 418 // (parameters.optionalParametersAreNamed ? 1 : 0). |
| 419 // N+3. Index to function type in constant pool. | 419 // N+3. Index to function type in constant pool. |
| 420 // N+4. First default argument. | 420 // N+4. First default argument. |
| 421 // ... | 421 // ... |
| 422 // O. First parameter name (if needed for reflection or Function.apply). | 422 // O. First parameter name (if needed for reflection or Function.apply). |
| 423 // ... | 423 // ... |
| 424 // P. Unmangled name (if reflectable). | 424 // P. Unmangled name (if reflectable). |
| 425 // P+1. First metadata (if reflectable). | 425 // P+1. First metadata (if reflectable). |
| 426 // ... | 426 // ... |
| 427 // TODO(ahe): Consider one of the parameter counts can be replaced by the | 427 // TODO(ahe): Consider one of the parameter counts can be replaced by the |
| 428 // length property of the JavaScript function object. | 428 // length property of the JavaScript function object. |
| 429 | 429 |
| 430 List<jsAst.Expression> expressions = <jsAst.Expression>[]; | 430 List<jsAst.Expression> expressions = <jsAst.Expression>[]; |
| 431 | 431 |
| 432 String callSelectorString = 'null'; | 432 String callSelectorString = 'null'; |
| 433 if (member.isFunction()) { | 433 if (member.isFunction) { |
| 434 Selector callSelector = | 434 Selector callSelector = |
| 435 new Selector.fromElement(member, compiler).toCallSelector(); | 435 new Selector.fromElement(member, compiler).toCallSelector(); |
| 436 callSelectorString = '"${namer.invocationName(callSelector)}"'; | 436 callSelectorString = '"${namer.invocationName(callSelector)}"'; |
| 437 } | 437 } |
| 438 | 438 |
| 439 // On [requiredParameterCount], the lower bit is set if this method can be | 439 // On [requiredParameterCount], the lower bit is set if this method can be |
| 440 // called reflectively. | 440 // called reflectively. |
| 441 int requiredParameterCount = parameters.requiredParameterCount << 1; | 441 int requiredParameterCount = parameters.requiredParameterCount << 1; |
| 442 if (member.isAccessor()) requiredParameterCount++; | 442 if (member.isAccessor) requiredParameterCount++; |
| 443 | 443 |
| 444 int optionalParameterCount = parameters.optionalParameterCount << 1; | 444 int optionalParameterCount = parameters.optionalParameterCount << 1; |
| 445 if (parameters.optionalParametersAreNamed) optionalParameterCount++; | 445 if (parameters.optionalParametersAreNamed) optionalParameterCount++; |
| 446 | 446 |
| 447 expressions.add(code); | 447 expressions.add(code); |
| 448 | 448 |
| 449 // TODO(sra): Don't use LiteralString for non-strings. | 449 // TODO(sra): Don't use LiteralString for non-strings. |
| 450 List tearOffInfo = [new jsAst.LiteralString(callSelectorString)]; | 450 List tearOffInfo = [new jsAst.LiteralString(callSelectorString)]; |
| 451 | 451 |
| 452 if (needsStubs || canTearOff) { | 452 if (needsStubs || canTearOff) { |
| 453 addParameterStubs(member, (Selector selector, jsAst.Fun function) { | 453 addParameterStubs(member, (Selector selector, jsAst.Fun function) { |
| 454 expressions.add(function); | 454 expressions.add(function); |
| 455 if (member.isInstanceMember()) { | 455 if (member.isInstanceMember) { |
| 456 Set invokedSelectors = | 456 Set invokedSelectors = |
| 457 compiler.codegenWorld.invokedNames[member.name]; | 457 compiler.codegenWorld.invokedNames[member.name]; |
| 458 expressions.add(js.string(namer.invocationName(selector))); | 458 expressions.add(js.string(namer.invocationName(selector))); |
| 459 } else { | 459 } else { |
| 460 expressions.add(js('null')); | 460 expressions.add(js('null')); |
| 461 // TOOD(ahe): Since we know when reading static data versus instance | 461 // TOOD(ahe): Since we know when reading static data versus instance |
| 462 // data, we can eliminate this element. | 462 // data, we can eliminate this element. |
| 463 } | 463 } |
| 464 Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[ | 464 Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[ |
| 465 namer.closureInvocationSelectorName]; | 465 namer.closureInvocationSelectorName]; |
| 466 Selector callSelector = selector.toCallSelector(); | 466 Selector callSelector = selector.toCallSelector(); |
| 467 String callSelectorString = 'null'; | 467 String callSelectorString = 'null'; |
| 468 if (canTearOff && callSelectors != null && | 468 if (canTearOff && callSelectors != null && |
| 469 callSelectors.contains(callSelector)) { | 469 callSelectors.contains(callSelector)) { |
| 470 callSelectorString = '"${namer.invocationName(callSelector)}"'; | 470 callSelectorString = '"${namer.invocationName(callSelector)}"'; |
| 471 } | 471 } |
| 472 tearOffInfo.add(new jsAst.LiteralString(callSelectorString)); | 472 tearOffInfo.add(new jsAst.LiteralString(callSelectorString)); |
| 473 }, canTearOff); | 473 }, canTearOff); |
| 474 } | 474 } |
| 475 | 475 |
| 476 jsAst.Expression memberTypeExpression; | 476 jsAst.Expression memberTypeExpression; |
| 477 if (canTearOff || canBeReflected) { | 477 if (canTearOff || canBeReflected) { |
| 478 DartType memberType; | 478 DartType memberType; |
| 479 if (member.isGenerativeConstructorBody()) { | 479 if (member.isGenerativeConstructorBody) { |
| 480 var body = member; | 480 var body = member; |
| 481 memberType = body.constructor.type; | 481 memberType = body.constructor.type; |
| 482 } else { | 482 } else { |
| 483 memberType = member.type; | 483 memberType = member.type; |
| 484 } | 484 } |
| 485 if (memberType.containsTypeVariables) { | 485 if (memberType.containsTypeVariables) { |
| 486 jsAst.Expression thisAccess = js(r'this.$receiver'); | 486 jsAst.Expression thisAccess = js(r'this.$receiver'); |
| 487 memberTypeExpression = | 487 memberTypeExpression = |
| 488 backend.rti.getSignatureEncoding(memberType, thisAccess); | 488 backend.rti.getSignatureEncoding(memberType, thisAccess); |
| 489 } else { | 489 } else { |
| 490 memberTypeExpression = | 490 memberTypeExpression = |
| 491 js.number(task.metadataEmitter.reifyType(memberType)); | 491 js.number(task.metadataEmitter.reifyType(memberType)); |
| 492 } | 492 } |
| 493 } else { | 493 } else { |
| 494 memberTypeExpression = js('null'); | 494 memberTypeExpression = js('null'); |
| 495 } | 495 } |
| 496 | 496 |
| 497 expressions | 497 expressions |
| 498 ..addAll(tearOffInfo) | 498 ..addAll(tearOffInfo) |
| 499 ..add((tearOffName == null || member.isAccessor()) | 499 ..add((tearOffName == null || member.isAccessor) |
| 500 ? js("null") : js.string(tearOffName)) | 500 ? js("null") : js.string(tearOffName)) |
| 501 ..add(js.number(requiredParameterCount)) | 501 ..add(js.number(requiredParameterCount)) |
| 502 ..add(js.number(optionalParameterCount)) | 502 ..add(js.number(optionalParameterCount)) |
| 503 ..add(memberTypeExpression) | 503 ..add(memberTypeExpression) |
| 504 ..addAll( | 504 ..addAll( |
| 505 task.metadataEmitter.reifyDefaultArguments(member).map(js.number)); | 505 task.metadataEmitter.reifyDefaultArguments(member).map(js.number)); |
| 506 | 506 |
| 507 if (canBeReflected || canBeApplied) { | 507 if (canBeReflected || canBeApplied) { |
| 508 parameters.forEachParameter((Element parameter) { | 508 parameters.forEachParameter((Element parameter) { |
| 509 expressions.add( | 509 expressions.add( |
| 510 js.number(task.metadataEmitter.reifyName(parameter.name))); | 510 js.number(task.metadataEmitter.reifyName(parameter.name))); |
| 511 if (backend.mustRetainMetadata) { | 511 if (backend.mustRetainMetadata) { |
| 512 List<MetadataAnnotation> annotations = parameter.metadata.toList(); | 512 List<MetadataAnnotation> annotations = parameter.metadata.toList(); |
| 513 Iterable<int> metadataIndices = | 513 Iterable<int> metadataIndices = |
| 514 annotations.map((MetadataAnnotation annotation) { | 514 annotations.map((MetadataAnnotation annotation) { |
| 515 Constant constant = | 515 Constant constant = |
| 516 backend.constants.getConstantForMetadata(annotation); | 516 backend.constants.getConstantForMetadata(annotation); |
| 517 backend.constants.addCompileTimeConstantForEmission(constant); | 517 backend.constants.addCompileTimeConstantForEmission(constant); |
| 518 return task.metadataEmitter.reifyMetadata(annotation); | 518 return task.metadataEmitter.reifyMetadata(annotation); |
| 519 }); | 519 }); |
| 520 expressions.add( | 520 expressions.add( |
| 521 new jsAst.ArrayInitializer.from(metadataIndices.map(js.number))); | 521 new jsAst.ArrayInitializer.from(metadataIndices.map(js.number))); |
| 522 } | 522 } |
| 523 }); | 523 }); |
| 524 } | 524 } |
| 525 if (canBeReflected) { | 525 if (canBeReflected) { |
| 526 jsAst.LiteralString reflectionName; | 526 jsAst.LiteralString reflectionName; |
| 527 if (member.isConstructor()) { | 527 if (member.isConstructor) { |
| 528 String reflectionNameString = task.getReflectionName(member, name); | 528 String reflectionNameString = task.getReflectionName(member, name); |
| 529 reflectionName = | 529 reflectionName = |
| 530 new jsAst.LiteralString( | 530 new jsAst.LiteralString( |
| 531 '"new ${Elements.reconstructConstructorName(member)}"'); | 531 '"new ${Elements.reconstructConstructorName(member)}"'); |
| 532 } else { | 532 } else { |
| 533 reflectionName = js.string(member.name); | 533 reflectionName = js.string(member.name); |
| 534 } | 534 } |
| 535 expressions | 535 expressions |
| 536 ..add(reflectionName) | 536 ..add(reflectionName) |
| 537 ..addAll(task.metadataEmitter.computeMetadata(member).map(js.number)); | 537 ..addAll(task.metadataEmitter.computeMetadata(member).map(js.number)); |
| 538 } else if (isClosure && canBeApplied) { | 538 } else if (isClosure && canBeApplied) { |
| 539 expressions.add(js.string(member.name)); | 539 expressions.add(js.string(member.name)); |
| 540 } | 540 } |
| 541 builder.addProperty(name, new jsAst.ArrayInitializer.from(expressions)); | 541 builder.addProperty(name, new jsAst.ArrayInitializer.from(expressions)); |
| 542 } | 542 } |
| 543 | 543 |
| 544 void addMemberField(VariableElement member, ClassBuilder builder) { | 544 void addMemberField(VariableElement member, ClassBuilder builder) { |
| 545 // For now, do nothing. | 545 // For now, do nothing. |
| 546 } | 546 } |
| 547 } | 547 } |
| OLD | NEW |