Chromium Code Reviews| Index: lib/compiler/implementation/emitter.dart |
| diff --git a/lib/compiler/implementation/emitter.dart b/lib/compiler/implementation/emitter.dart |
| index 422e3e9a80c78b08d0d3b139ba4e0dcdd5035d74..09884e0c0854cd97d154650e3ff20e5c0f2d7817 100644 |
| --- a/lib/compiler/implementation/emitter.dart |
| +++ b/lib/compiler/implementation/emitter.dart |
| @@ -50,12 +50,6 @@ function(child, parent) { |
| String get inheritsName() => '${namer.ISOLATE}.\$inherits'; |
| - String get objectClassName() { |
| - ClassElement objectClass = |
| - compiler.coreLibrary.find(const SourceString('Object')); |
| - return namer.isolatePropertyAccess(objectClass); |
| - } |
| - |
| void addInheritFunctionIfNecessary() { |
| if (addedInheritFunction) return; |
| addedInheritFunction = true; |
| @@ -185,6 +179,7 @@ function(child, parent) { |
| void addInstanceMember(Element member, |
| String attachTo(String name), |
| StringBuffer buffer, |
| + String isolatePrototype, |
| [bool isNative = false]) { |
| // TODO(floitsch): we don't need to deal with members of |
| // uninstantiated classes, that have been overwritten by subclasses. |
| @@ -229,7 +224,7 @@ function(child, parent) { |
| compiler.internalError('unexpected kind: "${member.kind}"', |
| element: member); |
| } |
| - emitExtraAccessors(member, attachTo, buffer); |
| + emitExtraAccessors(member, attachTo, buffer, isolatePrototype); |
| } |
| bool generateFieldInits(ClassElement classElement, |
| @@ -252,25 +247,32 @@ function(child, parent) { |
| includeSuperMembers: true); |
| } |
| - void emitInherits(ClassElement cls, StringBuffer buffer) { |
| + void emitInherits(ClassElement cls, |
| + StringBuffer buffer, |
| + String isolatePrototype) { |
| ClassElement superclass = cls.superclass; |
| if (superclass !== null) { |
| addInheritFunctionIfNecessary(); |
| - String className = namer.isolatePropertyAccess(cls); |
| - String superName = namer.isolatePropertyAccess(superclass); |
| - buffer.add('${inheritsName}($className, $superName);\n'); |
| + String className = namer.getName(cls); |
| + String superName = namer.getName(superclass); |
| + buffer.add('${inheritsName}($isolatePrototype.$className, '); |
| + buffer.add('$isolatePrototype.$superName);\n'); |
| } |
| } |
| - void ensureGenerated(ClassElement classElement, StringBuffer buffer) { |
| + void ensureGenerated(ClassElement classElement, |
| + StringBuffer buffer, |
| + String isolatePrototype) { |
| if (classElement == null) return; |
| if (generatedClasses.contains(classElement)) return; |
| generatedClasses.add(classElement); |
| - generateClass(classElement, buffer); |
| + generateClass(classElement, buffer, isolatePrototype); |
| } |
| - void generateClass(ClassElement classElement, StringBuffer buffer) { |
| - ensureGenerated(classElement.superclass, buffer); |
| + void generateClass(ClassElement classElement, |
| + StringBuffer buffer, |
| + String isolatePrototype) { |
| + ensureGenerated(classElement.superclass, buffer, isolatePrototype); |
| if (classElement.isNative()) { |
| nativeEmitter.generateNativeClass(classElement); |
| @@ -282,7 +284,7 @@ function(child, parent) { |
| buffer = mainBuffer; |
| } |
| - String className = namer.isolatePropertyAccess(classElement); |
| + String className = '${isolatePrototype}.${namer.getName(classElement)}'; |
| String constructorName = namer.safeName(classElement.name.slowToString()); |
| buffer.add('$className = function $constructorName('); |
| StringBuffer bodyBuffer = new StringBuffer(); |
| @@ -295,14 +297,14 @@ function(child, parent) { |
| buffer.add(bodyBuffer); |
| buffer.add('};\n'); |
| - emitInherits(classElement, buffer); |
| + emitInherits(classElement, buffer, isolatePrototype); |
| String attachTo(String name) => '$className.prototype.$name'; |
| classElement.forEachMember(includeBackendMembers: true, |
| f: (ClassElement enclosing, Element member) { |
| if (member.isInstanceMember()) { |
| - addInstanceMember(member, attachTo, buffer); |
| + addInstanceMember(member, attachTo, buffer, isolatePrototype); |
| } |
| }); |
| @@ -321,7 +323,7 @@ function(child, parent) { |
| // the code in the dynamicMethod can find them. Note that the |
| // code in dynamicMethod is invoked before analyzing the full JS |
| // script. |
| - emitNoSuchMethodCalls(buffer); |
| + emitNoSuchMethodCalls(buffer, isolatePrototype); |
| } |
| } |
| @@ -347,34 +349,38 @@ function(child, parent) { |
| } |
| } |
| - void emitClasses(StringBuffer buffer) { |
| + void emitClasses(StringBuffer buffer, String isolatePrototype) { |
| for (ClassElement element in compiler.universe.instantiatedClasses) { |
| - ensureGenerated(element, buffer); |
| + ensureGenerated(element, buffer, isolatePrototype); |
| } |
| } |
| void emitStaticFunctionsWithNamer(StringBuffer buffer, |
| + String isolatePrototype, |
| Map<Element, String> generatedCode, |
| String functionNamer(Element element)) { |
| generatedCode.forEach((Element element, String codeBlock) { |
| if (!element.isInstanceMember()) { |
| - buffer.add('${functionNamer(element)} = '); |
| + buffer.add(isolatePrototype); |
| + buffer.add('.${functionNamer(element)} = '); |
| buffer.add(codeBlock); |
| buffer.add(';\n\n'); |
| } |
| }); |
| } |
| - void emitStaticFunctions(StringBuffer buffer) { |
| + void emitStaticFunctions(StringBuffer buffer, String isolatePrototype) { |
| emitStaticFunctionsWithNamer(buffer, |
| + isolatePrototype, |
| compiler.universe.generatedCode, |
| - namer.isolatePropertyAccess); |
| + namer.getName); |
| emitStaticFunctionsWithNamer(buffer, |
| + isolatePrototype, |
| compiler.universe.generatedBailoutCode, |
| - namer.isolateBailoutPropertyAccess); |
| + namer.getBailoutName); |
| } |
| - void emitStaticFunctionGetters(StringBuffer buffer) { |
| + void emitStaticFunctionGetters(StringBuffer buffer, String isolatePrototype) { |
| Set<FunctionElement> functionsNeedingGetter = |
| compiler.universe.staticFunctionsNeedingGetter; |
| for (FunctionElement element in functionsNeedingGetter) { |
| @@ -384,17 +390,23 @@ function(child, parent) { |
| // Note: the callElement will not have any enclosingElement. |
| FunctionElement callElement = |
| new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element); |
| - String staticName = namer.isolatePropertyAccess(element); |
| + String staticName = namer.getName(element); |
| int parameterCount = element.parameterCount(compiler); |
| String invocationName = |
| namer.instanceMethodName(element.getLibrary(), callElement.name, |
| parameterCount); |
| - buffer.add("$staticName.$invocationName = $staticName;\n"); |
| - addParameterStubs(callElement, (name) => '$staticName.$name', buffer); |
| + buffer.add(isolatePrototype); |
| + buffer.add(".$staticName.$invocationName = "); |
| + buffer.add(isolatePrototype); |
| + buffer.add(".$staticName;\n"); |
| + addParameterStubs(callElement, |
| + (name) => '$isolatePrototype.$staticName.$name', |
| + buffer); |
| } |
| } |
| void emitDynamicFunctionGetter(StringBuffer buffer, |
| + String isolatePrototype, |
| String attachTo(String invocationName), |
| FunctionElement member) { |
| // For every method that has the same name as a property-get we create a |
| @@ -419,16 +431,17 @@ function(child, parent) { |
| SourceString name = const SourceString("BoundClosure"); |
| ClassElement closureClassElement = |
| new ClosureClassElement(compiler, member.getCompilationUnit()); |
| - String isolateAccess = namer.isolatePropertyAccess(closureClassElement); |
| - ensureGenerated(closureClassElement.superclass, buffer); |
| + String mangledName = namer.getName(closureClassElement); |
| + ensureGenerated(closureClassElement.superclass, buffer, isolatePrototype); |
| // Define the constructor with a name so that Object.toString can |
| // find the class name of the closure class. |
| - buffer.add("$isolateAccess = function $name(self) "); |
| + buffer.add(isolatePrototype); |
|
Lasse Reichstein Nielsen
2012/04/12 09:45:32
We should add an "<<" operator to StringBuffer :)
floitsch
2012/04/12 11:26:56
hehe.
|
| + buffer.add(".$mangledName = function $name(self) "); |
| buffer.add("{ this.self = self; };\n"); |
| - emitInherits(closureClassElement, buffer); |
| + emitInherits(closureClassElement, buffer, isolatePrototype); |
| - String prototype = "$isolateAccess.prototype"; |
| + String prototype = "$isolatePrototype.$mangledName.prototype"; |
| // Now add the methods on the closure class. The instance method does not |
| // have the correct name. Since [addParameterStubs] use the name to create |
| @@ -452,7 +465,7 @@ function(child, parent) { |
| buffer.add(" return this.self.$targetName($joinedArgs);\n"); |
| buffer.add("};\n"); |
| addParameterStubs(callElement, |
| - (invocationName) => '$prototype.$invocationName', |
| + (stubName) => '$prototype.$stubName', |
| buffer); |
| // And finally the getter. |
| @@ -513,25 +526,24 @@ function(child, parent) { |
| } |
| } |
| - void emitCompileTimeConstants(StringBuffer buffer) { |
| + void emitCompileTimeConstants(StringBuffer buffer, String isolatePrototype) { |
| ConstantHandler handler = compiler.constantHandler; |
| List<Constant> constants = handler.getConstantsForEmission(); |
| - String prototype = "${namer.ISOLATE}.prototype"; |
| bool addedMakeConstantList = false; |
| for (Constant constant in constants) { |
| if (!addedMakeConstantList && constant.isList()) { |
| addedMakeConstantList = true; |
| - emitMakeConstantList(prototype, buffer); |
| + emitMakeConstantList(buffer, isolatePrototype); |
| } |
| String name = handler.getNameForConstant(constant); |
| - buffer.add('$prototype.$name = '); |
| + buffer.add('$isolatePrototype.$name = '); |
| handler.writeJsCode(buffer, constant); |
| buffer.add(';\n'); |
| } |
| } |
| - void emitMakeConstantList(String prototype, StringBuffer buffer) { |
| - buffer.add(prototype); |
| + void emitMakeConstantList(StringBuffer buffer, String isolatePrototype) { |
| + buffer.add(isolatePrototype); |
| buffer.add(@'''.makeConstantList = function(list) { |
| list.immutable$list = true; |
| list.fixed$length = true; |
| @@ -540,12 +552,14 @@ function(child, parent) { |
| '''); |
| } |
| - void emitStaticFinalFieldInitializations(StringBuffer buffer) { |
| + void emitStaticFinalFieldInitializations(StringBuffer buffer, |
| + String isolatePrototype) { |
| ConstantHandler handler = compiler.constantHandler; |
| List<VariableElement> staticFinalFields = |
| handler.getStaticFinalFieldsForEmission(); |
| for (VariableElement element in staticFinalFields) { |
| - buffer.add('${namer.isolatePropertyAccess(element)} = '); |
| + buffer.add(isolatePrototype); |
| + buffer.add('.${namer.getName(element)} = '); |
| compiler.withCurrentElement(element, () { |
| handler.writeJsCodeForVariable(buffer, element); |
| }); |
| @@ -555,7 +569,8 @@ function(child, parent) { |
| void emitExtraAccessors(Element member, |
| String attachTo(String name), |
| - StringBuffer buffer) { |
| + StringBuffer buffer, |
| + String isolatePrototype) { |
| if (member.kind == ElementKind.GETTER || member.kind == ElementKind.FIELD) { |
| Set<Selector> selectors = compiler.universe.invokedNames[member.name]; |
| if (selectors !== null && !selectors.isEmpty()) { |
| @@ -565,19 +580,21 @@ function(child, parent) { |
| } else if (member.kind == ElementKind.FUNCTION) { |
| if (compiler.universe.invokedGetters.contains(member.name)) { |
| compiler.emitter.emitDynamicFunctionGetter( |
| - buffer, attachTo, member); |
| + buffer, isolatePrototype, attachTo, member); |
| } |
| } |
| } |
| - void emitNoSuchMethodCalls(StringBuffer buffer) { |
| + void emitNoSuchMethodCalls(StringBuffer buffer, String isolatePrototype) { |
|
Lasse Reichstein Nielsen
2012/04/12 09:45:32
Instead of passing isolatePrototype everywhere, co
floitsch
2012/04/12 11:26:56
Done.
|
| // Do not generate no such method calls if there is no class. |
| if (compiler.universe.instantiatedClasses.isEmpty()) return; |
| ClassElement objectClass = |
| compiler.coreLibrary.find(const SourceString('Object')); |
| - String className = namer.isolatePropertyAccess(objectClass); |
| - String prototype = '$className.prototype'; |
| + String className = namer.getName(objectClass); |
| + String prototype = '$isolatePrototype.$className.prototype'; |
| + String runtimeObjectPrototype = |
| + '${namer.isolateAccess(objectClass)}.prototype'; |
| String noSuchMethodName = |
| namer.instanceMethodName(null, Compiler.NO_SUCH_METHOD, 2); |
| Collection<LibraryElement> libraries = |
| @@ -597,7 +614,7 @@ function(child, parent) { |
| buffer.add(' ($args) {\n'); |
| buffer.add(' return this.$noSuchMethodName\n'); |
| buffer.add(" ? this.$noSuchMethodName('$methodName', [$args])\n"); |
| - buffer.add(" : $objectClassName.prototype.$noSuchMethodName.call("); |
| + buffer.add(" : $runtimeObjectPrototype.$noSuchMethodName.call("); |
| buffer.add("this, '$methodName', [$args])\n"); |
| buffer.add('}\n'); |
| } |
| @@ -713,15 +730,19 @@ if (typeof window != 'undefined' && typeof document != 'undefined' && |
| measure(() { |
| mainBuffer.add('function ${namer.ISOLATE}() {'); |
| emitStaticNonFinalFieldInitializations(mainBuffer); |
| - mainBuffer.add('}\n\n'); |
| - emitClasses(mainBuffer); |
| - emitStaticFunctions(mainBuffer); |
| - emitStaticFunctionGetters(mainBuffer); |
| - emitCompileTimeConstants(mainBuffer); |
| - emitStaticFinalFieldInitializations(mainBuffer); |
| - nativeEmitter.emitDynamicDispatchMetadata(); |
| + mainBuffer.add('};\n\n'); |
| + // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. |
| + String isolatePrototype = namer.CURRENT_ISOLATE; |
| + mainBuffer.add('var $isolatePrototype = ${namer.ISOLATE}.prototype;\n'); |
| + emitClasses(mainBuffer, isolatePrototype); |
| + emitStaticFunctions(mainBuffer, isolatePrototype); |
| + emitStaticFunctionGetters(mainBuffer, isolatePrototype); |
| + emitCompileTimeConstants(mainBuffer, isolatePrototype); |
| + emitStaticFinalFieldInitializations(mainBuffer, isolatePrototype); |
| + |
| mainBuffer.add( |
| 'var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); |
| + nativeEmitter.emitDynamicDispatchMetadata(); |
| nativeEmitter.assembleCode(mainBuffer); |
| emitMain(mainBuffer); |
| compiler.assembledCode = mainBuffer.toString(); |