| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
| 6 * A function element that represents a closure call. The signature is copied | 6 * A function element that represents a closure call. The signature is copied |
| 7 * from the given element. | 7 * from the given element. |
| 8 */ | 8 */ |
| 9 class ClosureInvocationElement extends FunctionElement { | 9 class ClosureInvocationElement extends FunctionElement { |
| 10 ClosureInvocationElement(SourceString name, | 10 ClosureInvocationElement(SourceString name, |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 [bool isNative = false]) { | 167 [bool isNative = false]) { |
| 168 Set<Selector> selectors = compiler.universe.invokedNames[member.name]; | 168 Set<Selector> selectors = compiler.universe.invokedNames[member.name]; |
| 169 if (selectors == null) return; | 169 if (selectors == null) return; |
| 170 for (Selector selector in selectors) { | 170 for (Selector selector in selectors) { |
| 171 if (!selector.applies(compiler, member)) continue; | 171 if (!selector.applies(compiler, member)) continue; |
| 172 addParameterStub(member, attachTo, buffer, selector, isNative); | 172 addParameterStub(member, attachTo, buffer, selector, isNative); |
| 173 } | 173 } |
| 174 } | 174 } |
| 175 | 175 |
| 176 void addInstanceMember(Element member, | 176 void addInstanceMember(Element member, |
| 177 String prototype, | 177 String attachTo(String name), |
| 178 StringBuffer buffer) { | 178 StringBuffer buffer, |
| 179 [bool isNative = false]) { |
| 179 // TODO(floitsch): we don't need to deal with members of | 180 // TODO(floitsch): we don't need to deal with members of |
| 180 // uninstantiated classes, that have been overwritten by subclasses. | 181 // uninstantiated classes, that have been overwritten by subclasses. |
| 181 String attachTo(String name) => '$prototype.$name'; | |
| 182 | 182 |
| 183 assert(member.isInstanceMember()); | |
| 184 if (member.kind === ElementKind.FUNCTION | 183 if (member.kind === ElementKind.FUNCTION |
| 185 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY | 184 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY |
| 186 || member.kind === ElementKind.GETTER | 185 || member.kind === ElementKind.GETTER |
| 187 || member.kind === ElementKind.SETTER) { | 186 || member.kind === ElementKind.SETTER) { |
| 188 if (member.modifiers !== null && member.modifiers.isAbstract()) return; | 187 if (member.modifiers !== null && member.modifiers.isAbstract()) return; |
| 189 String codeBlock = compiler.universe.generatedCode[member]; | 188 String codeBlock = compiler.universe.generatedCode[member]; |
| 190 if (codeBlock == null) return; | 189 if (codeBlock == null) return; |
| 191 buffer.add('$prototype.${namer.getName(member)} = $codeBlock;\n'); | 190 buffer.add('${attachTo(namer.getName(member))} = $codeBlock;\n'); |
| 192 codeBlock = compiler.universe.generatedBailoutCode[member]; | 191 codeBlock = compiler.universe.generatedBailoutCode[member]; |
| 193 if (codeBlock !== null) { | 192 if (codeBlock !== null) { |
| 194 String name = namer.getBailoutName(member); | 193 String name = compiler.namer.getBailoutName(member); |
| 195 buffer.add('$prototype.$name = $codeBlock;\n'); | 194 buffer.add('${attachTo(name)} = $codeBlock;\n'); |
| 196 } | 195 } |
| 197 FunctionElement function = member; | 196 FunctionElement function = member; |
| 198 if (!function.computeParameters(compiler).optionalParameters.isEmpty()) { | 197 FunctionParameters parameters = function.computeParameters(compiler); |
| 199 addParameterStubs(member, attachTo, buffer); | 198 if (!parameters.optionalParameters.isEmpty()) { |
| 199 addParameterStubs(member, attachTo, buffer, isNative: isNative); |
| 200 } | 200 } |
| 201 } else if (member.kind === ElementKind.FIELD) { | 201 } else if (member.kind === ElementKind.FIELD) { |
| 202 // TODO(ngeoffray): Have another class generate the code for the | 202 // TODO(ngeoffray): Have another class generate the code for the |
| 203 // fields. | 203 // fields. |
| 204 if ((member.modifiers === null || !member.modifiers.isFinal()) && | 204 if ((member.modifiers === null || !member.modifiers.isFinal()) && |
| 205 compiler.universe.invokedSetters.contains(member.name)) { | 205 compiler.universe.invokedSetters.contains(member.name)) { |
| 206 String setterName = namer.setterName(member.name); | 206 String setterName = namer.setterName(member.name); |
| 207 buffer.add('$prototype.$setterName = function(v){\n' + | 207 String name = |
| 208 ' this.${namer.getName(member)} = v;\n};\n'); | 208 isNative ? member.name.slowToString() : namer.getName(member); |
| 209 buffer.add('${attachTo(setterName)} = function(v){\n'); |
| 210 buffer.add(' this.$name = v;\n};\n'); |
| 209 } | 211 } |
| 210 if (compiler.universe.invokedGetters.contains(member.name)) { | 212 if (compiler.universe.invokedGetters.contains(member.name)) { |
| 211 String getterName = namer.getterName(member.name); | 213 String getterName = namer.getterName(member.name); |
| 212 buffer.add('$prototype.$getterName = function(){\n' + | 214 String name = |
| 213 ' return this.${namer.getName(member)};\n};\n'); | 215 isNative ? member.name.slowToString() : namer.getName(member); |
| 216 buffer.add('${attachTo(getterName)} = function(){\n'); |
| 217 buffer.add(' return this.$name;\n};\n'); |
| 214 } | 218 } |
| 215 } else { | 219 } else { |
| 216 compiler.internalError('unexpected kind: "${member.kind}"', | 220 compiler.internalError('unexpected kind: "${member.kind}"', |
| 217 element: member); | 221 element: member); |
| 218 } | 222 } |
| 219 | 223 emitExtraAccessors(member, attachTo, buffer); |
| 220 if (member.kind == ElementKind.GETTER || member.kind == ElementKind.FIELD) { | |
| 221 Set<Selector> selectors = compiler.universe.invokedNames[member.name]; | |
| 222 if (selectors !== null && !selectors.isEmpty()) { | |
| 223 emitCallStubForGetter(buffer, attachTo, member, selectors); | |
| 224 } | |
| 225 } else if (member.kind == ElementKind.FUNCTION) { | |
| 226 if (compiler.universe.invokedGetters.contains(member.name)) { | |
| 227 emitDynamicFunctionGetter(buffer, attachTo, member); | |
| 228 } | |
| 229 } | |
| 230 } | 224 } |
| 231 | 225 |
| 232 bool generateFieldInits(ClassElement classElement, | 226 bool generateFieldInits(ClassElement classElement, |
| 233 StringBuffer argumentsBuffer, | 227 StringBuffer argumentsBuffer, |
| 234 StringBuffer bodyBuffer) { | 228 StringBuffer bodyBuffer) { |
| 235 bool isFirst = true; | 229 bool isFirst = true; |
| 236 do { | 230 do { |
| 237 // TODO(floitsch): make sure there are no name clashes. | 231 // TODO(floitsch): make sure there are no name clashes. |
| 238 String className = namer.getName(classElement); | 232 String className = namer.getName(classElement); |
| 239 | 233 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 generateFieldInits(classElement, buffer, bodyBuffer); | 276 generateFieldInits(classElement, buffer, bodyBuffer); |
| 283 } | 277 } |
| 284 buffer.add(') {\n'); | 278 buffer.add(') {\n'); |
| 285 buffer.add(bodyBuffer); | 279 buffer.add(bodyBuffer); |
| 286 buffer.add('};\n'); | 280 buffer.add('};\n'); |
| 287 if (superclass !== null) { | 281 if (superclass !== null) { |
| 288 addInheritFunctionIfNecessary(buffer); | 282 addInheritFunctionIfNecessary(buffer); |
| 289 String superName = namer.isolatePropertyAccess(superclass); | 283 String superName = namer.isolatePropertyAccess(superclass); |
| 290 buffer.add('${inheritsName}($className, $superName);\n'); | 284 buffer.add('${inheritsName}($className, $superName);\n'); |
| 291 } | 285 } |
| 292 String prototype = '$className.prototype'; | |
| 293 | 286 |
| 287 String attachTo(String name) => '$className.prototype.$name'; |
| 294 for (Element member in classElement.members) { | 288 for (Element member in classElement.members) { |
| 295 if (member.isInstanceMember()) { | 289 if (member.isInstanceMember()) { |
| 296 addInstanceMember(member, prototype, buffer); | 290 addInstanceMember(member, attachTo, buffer); |
| 297 } | 291 } |
| 298 } | 292 } |
| 299 for (Element member in classElement.backendMembers) { | 293 for (Element member in classElement.backendMembers) { |
| 300 if (member.isInstanceMember()) { | 294 if (member.isInstanceMember()) { |
| 301 addInstanceMember(member, prototype, buffer); | 295 addInstanceMember(member, attachTo, buffer); |
| 302 } | 296 } |
| 303 } | 297 } |
| 304 generateTypeTests(classElement, (Element other) { | 298 generateTypeTests(classElement, (Element other) { |
| 305 buffer.add('$prototype.${namer.operatorIs(other)} = true;\n'); | 299 buffer.add('${attachTo(namer.operatorIs(other))} = true;\n'); |
| 306 }); | 300 }); |
| 307 | 301 |
| 308 if (superclass === null) { | 302 if (superclass === null) { |
| 309 // Emit the noSuchMethods on the Object prototype now, so that | 303 // Emit the noSuchMethods on the Object prototype now, so that |
| 310 // the code in the dynamicMethod can find them. Note that the | 304 // the code in the dynamicMethod can find them. Note that the |
| 311 // code in dynamicMethod is invoked before analyzing the full JS | 305 // code in dynamicMethod is invoked before analyzing the full JS |
| 312 // script. | 306 // script. |
| 313 emitNoSuchMethodCalls(buffer); | 307 emitNoSuchMethodCalls(buffer); |
| 314 } | 308 } |
| 315 } | 309 } |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 constants.getStaticFinalFieldsForEmission(); | 515 constants.getStaticFinalFieldsForEmission(); |
| 522 for (VariableElement element in staticFinalFields) { | 516 for (VariableElement element in staticFinalFields) { |
| 523 buffer.add('${namer.isolatePropertyAccess(element)} = '); | 517 buffer.add('${namer.isolatePropertyAccess(element)} = '); |
| 524 compiler.withCurrentElement(element, () { | 518 compiler.withCurrentElement(element, () { |
| 525 constants.writeJsCodeForVariable(buffer, element); | 519 constants.writeJsCodeForVariable(buffer, element); |
| 526 }); | 520 }); |
| 527 buffer.add(';\n'); | 521 buffer.add(';\n'); |
| 528 } | 522 } |
| 529 } | 523 } |
| 530 | 524 |
| 525 void emitExtraAccessors(Element member, |
| 526 String attachTo(String name), |
| 527 StringBuffer buffer) { |
| 528 if (member.kind == ElementKind.GETTER || member.kind == ElementKind.FIELD) { |
| 529 Set<Selector> selectors = compiler.universe.invokedNames[member.name]; |
| 530 if (selectors !== null && !selectors.isEmpty()) { |
| 531 compiler.emitter.emitCallStubForGetter( |
| 532 buffer, attachTo, member, selectors); |
| 533 } |
| 534 } else if (member.kind == ElementKind.FUNCTION) { |
| 535 if (compiler.universe.invokedGetters.contains(member.name)) { |
| 536 compiler.emitter.emitDynamicFunctionGetter( |
| 537 buffer, attachTo, member); |
| 538 } |
| 539 } |
| 540 } |
| 541 |
| 531 void emitNoSuchMethodCalls(StringBuffer buffer) { | 542 void emitNoSuchMethodCalls(StringBuffer buffer) { |
| 532 // Do not generate no such method calls if there is no class. | 543 // Do not generate no such method calls if there is no class. |
| 533 if (compiler.universe.instantiatedClasses.isEmpty()) return; | 544 if (compiler.universe.instantiatedClasses.isEmpty()) return; |
| 534 | 545 |
| 535 // TODO(ngeoffray): We don't need to generate these methods if | 546 // TODO(ngeoffray): We don't need to generate these methods if |
| 536 // nobody overwrites noSuchMethod. | 547 // nobody overwrites noSuchMethod. |
| 537 | 548 |
| 538 ClassElement objectClass = | 549 ClassElement objectClass = |
| 539 compiler.coreLibrary.find(const SourceString('Object')); | 550 compiler.coreLibrary.find(const SourceString('Object')); |
| 540 String className = namer.isolatePropertyAccess(objectClass); | 551 String className = namer.isolatePropertyAccess(objectClass); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 emitStaticFinalFieldInitializations(buffer); | 610 emitStaticFinalFieldInitializations(buffer); |
| 600 nativeEmitter.emitDynamicDispatchMetadata(buffer); | 611 nativeEmitter.emitDynamicDispatchMetadata(buffer); |
| 601 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); | 612 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); |
| 602 Element main = compiler.mainApp.find(Compiler.MAIN); | 613 Element main = compiler.mainApp.find(Compiler.MAIN); |
| 603 buffer.add('${namer.isolateAccess(main)}();\n'); | 614 buffer.add('${namer.isolateAccess(main)}();\n'); |
| 604 compiler.assembledCode = buffer.toString(); | 615 compiler.assembledCode = buffer.toString(); |
| 605 }); | 616 }); |
| 606 return compiler.assembledCode; | 617 return compiler.assembledCode; |
| 607 } | 618 } |
| 608 } | 619 } |
| OLD | NEW |