Chromium Code Reviews| 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), |
|
kasperl
2012/03/02 13:11:33
Does this mean that you're re-evaluating the nativ
ngeoffray
2012/03/05 08:28:00
There are three cases:
1) Normal:
classNam
| |
| 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 | |
| 203 // fields. | |
| 204 if ((member.modifiers === null || !member.modifiers.isFinal()) && | 202 if ((member.modifiers === null || !member.modifiers.isFinal()) && |
| 205 compiler.universe.invokedSetters.contains(member.name)) { | 203 compiler.universe.invokedSetters.contains(member.name)) { |
| 206 String setterName = namer.setterName(member.name); | 204 String setterName = namer.setterName(member.name); |
| 207 buffer.add('$prototype.$setterName = function(v){\n' + | 205 String name = |
|
kasperl
2012/03/02 13:11:33
The name computation seems to be duplicated. Is th
ngeoffray
2012/03/05 08:28:00
I could share it, but that means it would be compu
| |
| 208 ' this.${namer.getName(member)} = v;\n};\n'); | 206 isNative ? member.name.slowToString() : namer.getName(member); |
| 207 buffer.add('${attachTo(setterName)} = function(v){\n'); | |
| 208 buffer.add(' this.$name = v;\n};\n'); | |
| 209 } | 209 } |
| 210 if (compiler.universe.invokedGetters.contains(member.name)) { | 210 if (compiler.universe.invokedGetters.contains(member.name)) { |
| 211 String getterName = namer.getterName(member.name); | 211 String getterName = namer.getterName(member.name); |
| 212 buffer.add('$prototype.$getterName = function(){\n' + | 212 String name = |
| 213 ' return this.${namer.getName(member)};\n};\n'); | 213 isNative ? member.name.slowToString() : namer.getName(member); |
| 214 buffer.add('${attachTo(getterName)} = function(){\n'); | |
| 215 buffer.add(' return this.$name;\n};\n'); | |
| 214 } | 216 } |
| 215 } else { | 217 } else { |
| 216 compiler.internalError('unexpected kind: "${member.kind}"', | 218 compiler.internalError('unexpected kind: "${member.kind}"', |
| 217 element: member); | 219 element: member); |
| 218 } | 220 } |
| 219 | 221 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 } | 222 } |
| 231 | 223 |
| 232 bool generateFieldInits(ClassElement classElement, | 224 bool generateFieldInits(ClassElement classElement, |
| 233 StringBuffer argumentsBuffer, | 225 StringBuffer argumentsBuffer, |
| 234 StringBuffer bodyBuffer) { | 226 StringBuffer bodyBuffer) { |
| 235 bool isFirst = true; | 227 bool isFirst = true; |
| 236 do { | 228 do { |
| 237 // TODO(floitsch): make sure there are no name clashes. | 229 // TODO(floitsch): make sure there are no name clashes. |
| 238 String className = namer.getName(classElement); | 230 String className = namer.getName(classElement); |
| 239 | 231 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 generateFieldInits(classElement, buffer, bodyBuffer); | 274 generateFieldInits(classElement, buffer, bodyBuffer); |
| 283 } | 275 } |
| 284 buffer.add(') {\n'); | 276 buffer.add(') {\n'); |
| 285 buffer.add(bodyBuffer); | 277 buffer.add(bodyBuffer); |
| 286 buffer.add('};\n'); | 278 buffer.add('};\n'); |
| 287 if (superclass !== null) { | 279 if (superclass !== null) { |
| 288 addInheritFunctionIfNecessary(buffer); | 280 addInheritFunctionIfNecessary(buffer); |
| 289 String superName = namer.isolatePropertyAccess(superclass); | 281 String superName = namer.isolatePropertyAccess(superclass); |
| 290 buffer.add('${inheritsName}($className, $superName);\n'); | 282 buffer.add('${inheritsName}($className, $superName);\n'); |
| 291 } | 283 } |
| 292 String prototype = '$className.prototype'; | |
| 293 | 284 |
| 285 String attachTo(String name) => '$className.prototype.$name'; | |
| 294 for (Element member in classElement.members) { | 286 for (Element member in classElement.members) { |
| 295 if (member.isInstanceMember()) { | 287 if (member.isInstanceMember()) { |
| 296 addInstanceMember(member, prototype, buffer); | 288 addInstanceMember(member, attachTo, buffer); |
| 297 } | 289 } |
| 298 } | 290 } |
| 299 for (Element member in classElement.backendMembers) { | 291 for (Element member in classElement.backendMembers) { |
| 300 if (member.isInstanceMember()) { | 292 if (member.isInstanceMember()) { |
| 301 addInstanceMember(member, prototype, buffer); | 293 addInstanceMember(member, attachTo, buffer); |
| 302 } | 294 } |
| 303 } | 295 } |
| 304 generateTypeTests(classElement, (Element other) { | 296 generateTypeTests(classElement, (Element other) { |
| 305 buffer.add('$prototype.${namer.operatorIs(other)} = true;\n'); | 297 buffer.add('${attachTo(namer.operatorIs(other))} = true;\n'); |
| 306 }); | 298 }); |
| 307 | 299 |
| 308 if (superclass === null) { | 300 if (superclass === null) { |
| 309 // Emit the noSuchMethods on the Object prototype now, so that | 301 // Emit the noSuchMethods on the Object prototype now, so that |
| 310 // the code in the dynamicMethod can find them. Note that the | 302 // the code in the dynamicMethod can find them. Note that the |
| 311 // code in dynamicMethod is invoked before analyzing the full JS | 303 // code in dynamicMethod is invoked before analyzing the full JS |
| 312 // script. | 304 // script. |
| 313 emitNoSuchMethodCalls(buffer); | 305 emitNoSuchMethodCalls(buffer); |
| 314 } | 306 } |
| 315 } | 307 } |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 521 constants.getStaticFinalFieldsForEmission(); | 513 constants.getStaticFinalFieldsForEmission(); |
| 522 for (VariableElement element in staticFinalFields) { | 514 for (VariableElement element in staticFinalFields) { |
| 523 buffer.add('${namer.isolatePropertyAccess(element)} = '); | 515 buffer.add('${namer.isolatePropertyAccess(element)} = '); |
| 524 compiler.withCurrentElement(element, () { | 516 compiler.withCurrentElement(element, () { |
| 525 constants.writeJsCodeForVariable(buffer, element); | 517 constants.writeJsCodeForVariable(buffer, element); |
| 526 }); | 518 }); |
| 527 buffer.add(';\n'); | 519 buffer.add(';\n'); |
| 528 } | 520 } |
| 529 } | 521 } |
| 530 | 522 |
| 523 void emitExtraAccessors(Element member, | |
| 524 String attachTo(String name), | |
| 525 StringBuffer buffer) { | |
| 526 if (member.kind == ElementKind.GETTER || member.kind == ElementKind.FIELD) { | |
| 527 Set<Selector> selectors = compiler.universe.invokedNames[member.name]; | |
| 528 if (selectors !== null && !selectors.isEmpty()) { | |
| 529 compiler.emitter.emitCallStubForGetter( | |
| 530 buffer, attachTo, member, selectors); | |
| 531 } | |
| 532 } else if (member.kind == ElementKind.FUNCTION) { | |
| 533 if (compiler.universe.invokedGetters.contains(member.name)) { | |
| 534 compiler.emitter.emitDynamicFunctionGetter( | |
| 535 buffer, attachTo, member); | |
| 536 } | |
| 537 } | |
| 538 } | |
| 539 | |
| 531 void emitNoSuchMethodCalls(StringBuffer buffer) { | 540 void emitNoSuchMethodCalls(StringBuffer buffer) { |
| 532 // Do not generate no such method calls if there is no class. | 541 // Do not generate no such method calls if there is no class. |
| 533 if (compiler.universe.instantiatedClasses.isEmpty()) return; | 542 if (compiler.universe.instantiatedClasses.isEmpty()) return; |
| 534 | 543 |
| 535 // TODO(ngeoffray): We don't need to generate these methods if | 544 // TODO(ngeoffray): We don't need to generate these methods if |
| 536 // nobody overwrites noSuchMethod. | 545 // nobody overwrites noSuchMethod. |
| 537 | 546 |
| 538 ClassElement objectClass = | 547 ClassElement objectClass = |
| 539 compiler.coreLibrary.find(const SourceString('Object')); | 548 compiler.coreLibrary.find(const SourceString('Object')); |
| 540 String className = namer.isolatePropertyAccess(objectClass); | 549 String className = namer.isolatePropertyAccess(objectClass); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 599 emitStaticFinalFieldInitializations(buffer); | 608 emitStaticFinalFieldInitializations(buffer); |
| 600 nativeEmitter.emitDynamicDispatchMetadata(buffer); | 609 nativeEmitter.emitDynamicDispatchMetadata(buffer); |
| 601 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); | 610 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); |
| 602 Element main = compiler.mainApp.find(Compiler.MAIN); | 611 Element main = compiler.mainApp.find(Compiler.MAIN); |
| 603 buffer.add('${namer.isolateAccess(main)}();\n'); | 612 buffer.add('${namer.isolateAccess(main)}();\n'); |
| 604 compiler.assembledCode = buffer.toString(); | 613 compiler.assembledCode = buffer.toString(); |
| 605 }); | 614 }); |
| 606 return compiler.assembledCode; | 615 return compiler.assembledCode; |
| 607 } | 616 } |
| 608 } | 617 } |
| OLD | NEW |