Chromium Code Reviews| Index: pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart |
| diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart |
| index 06f080341a464cbce307e5454dfd4bb68e003f8e..59bb22dac3f4f3e93bfeacc612131d82617d3909 100644 |
| --- a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart |
| +++ b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart |
| @@ -43,9 +43,11 @@ class OldEmitter implements Emitter { |
| => task.outputClassLists; |
| Map<OutputUnit, List<ConstantValue>> get outputConstantLists |
| => task.outputConstantLists; |
| - final Map<String, String> mangledFieldNames = <String, String>{}; |
| - final Map<String, String> mangledGlobalFieldNames = <String, String>{}; |
| - final Set<String> recordedMangledNames = new Set<String>(); |
| + final Map<jsAst.Name, String> mangledFieldNames = |
| + new HashMap<jsAst.Name, String>(); |
| + final Map<jsAst.Name, String> mangledGlobalFieldNames = |
| + new HashMap<jsAst.Name, String>(); |
| + final Set<jsAst.Name> recordedMangledNames = new Set<jsAst.Name>(); |
| List<TypedefElement> get typedefsNeededForReflection => |
| task.typedefsNeededForReflection; |
| @@ -93,7 +95,7 @@ class OldEmitter implements Emitter { |
| cachedClassBuilders = compiler.cacheStrategy.newMap(), |
| cachedElements = compiler.cacheStrategy.newSet() { |
| constantEmitter = new ConstantEmitter( |
| - compiler, namer, this.constantReference, makeConstantListTemplate); |
| + compiler, namer, this.constantReference, constantListGenerator); |
| containerBuilder.emitter = this; |
| classEmitter.emitter = this; |
| nsmEmitter.emitter = this; |
| @@ -152,7 +154,9 @@ class OldEmitter implements Emitter { |
| if (r != 0) return r; |
| // Resolve collisions in the long name by using the constant name (i.e. JS |
| // name) which is unique. |
| - return namer.constantName(a).compareTo(namer.constantName(b)); |
| + // TODO(herhut): Find a better way to resolve collisions. |
| + return namer.constantName(a).hashCode.compareTo( |
| + namer.constantName(b).hashCode); |
| } |
| @override |
| @@ -187,7 +191,8 @@ class OldEmitter implements Emitter { |
| => '${namer.isolateName}.${lazyInitializerProperty}'; |
| String get initName => 'init'; |
| - String get makeConstListProperty => namer.internalGlobal('makeConstantList'); |
| + jsAst.Name get makeConstListProperty |
| + => namer.internalGlobal('makeConstantList'); |
| /// The name of the property that contains all field names. |
| /// |
| @@ -199,7 +204,7 @@ class OldEmitter implements Emitter { |
| /// Contains the global state that is needed to initialize and load a |
| /// deferred library. |
| - String get globalsHolder => namer.internalGlobal("globalsHolder"); |
| + jsAst.Name get globalsHolder => namer.internalGlobal("globalsHolder"); |
| @override |
| jsAst.Expression generateEmbeddedGlobalAccess(String global) { |
| @@ -212,8 +217,8 @@ class OldEmitter implements Emitter { |
| } |
| jsAst.PropertyAccess globalPropertyAccess(Element element) { |
| - String name = namer.globalPropertyName(element); |
| - jsAst.PropertyAccess pa = new jsAst.PropertyAccess.field( |
| + jsAst.Name name = namer.globalPropertyName(element); |
| + jsAst.PropertyAccess pa = new jsAst.PropertyAccess( |
| new jsAst.VariableUse(namer.globalObjectFor(element)), |
| name); |
| return pa; |
| @@ -293,23 +298,8 @@ class OldEmitter implements Emitter { |
| return jsAst.js.expressionTemplateFor( |
| "('$isPrefix' + #) in #.prototype"); |
| - case JsBuiltin.isFunctionTypeRti: |
| - String functionClassName = |
| - backend.namer.runtimeTypeName(compiler.functionClass); |
| - return jsAst.js.expressionTemplateFor( |
| - '#.$typeNameProperty === "$functionClassName"'); |
| - |
| - case JsBuiltin.isDartObjectTypeRti: |
| - String objectClassName = |
| - backend.namer.runtimeTypeName(compiler.objectClass); |
| - return jsAst.js.expressionTemplateFor( |
| - '#.$typeNameProperty === "$objectClassName"'); |
| - |
| - case JsBuiltin.isNullTypeRti: |
| - String nullClassName = |
| - backend.namer.runtimeTypeName(compiler.nullClass); |
| - return jsAst.js.expressionTemplateFor( |
| - '#.$typeNameProperty === "$nullClassName"'); |
| + case JsBuiltin.isGivenTypeRti: |
| + return jsAst.js.expressionTemplateFor('#.$typeNameProperty === #'); |
| case JsBuiltin.getMetadata: |
| String metadataAccess = |
| @@ -371,7 +361,7 @@ class OldEmitter implements Emitter { |
| /// The reflection name of class 'C' is 'C'. |
| /// An anonymous mixin application has no reflection name. |
| /// This is used by js_mirrors.dart. |
| - String getReflectionName(elementOrSelector, String mangledName) { |
| + String getReflectionName(elementOrSelector, jsAst.Name mangledName) { |
| String name = elementOrSelector.name; |
| if (backend.shouldRetainName(name) || |
| elementOrSelector is Element && |
| @@ -390,13 +380,15 @@ class OldEmitter implements Emitter { |
| return null; |
| } |
| - String getReflectionNameInternal(elementOrSelector, String mangledName) { |
| + String getReflectionNameInternal(elementOrSelector, |
| + jsAst.Name mangledName) { |
| String name = namer.privateName(elementOrSelector.memberName); |
| if (elementOrSelector.isGetter) return name; |
| if (elementOrSelector.isSetter) { |
| - if (!mangledName.startsWith(namer.setterPrefix)) return '$name='; |
| - String base = mangledName.substring(namer.setterPrefix.length); |
| - String getter = '${namer.getterPrefix}$base'; |
| + if (mangledName is! SetterName) return '$name='; |
| + SetterName setterName = mangledName; |
| + jsAst.Name base = setterName.base; |
| + jsAst.Name getter = namer.deriveGetterName(base); |
| mangledFieldNames.putIfAbsent(getter, () => name); |
| assert(mangledFieldNames[getter] == name); |
| recordedMangledNames.add(getter); |
| @@ -409,7 +401,7 @@ class OldEmitter implements Emitter { |
| // Closures are synthesized and their name might conflict with existing |
| // globals. Assign an illegal name, and make sure they don't clash |
| // with each other. |
| - return " $mangledName"; |
| + return " $name"; |
| } |
| if (elementOrSelector is Selector |
| || elementOrSelector.isFunction |
| @@ -501,7 +493,8 @@ class OldEmitter implements Emitter { |
| if (compiler.hasIncrementalSupport) { |
| ClassBuilder cachedBuilder = |
| cachedClassBuilders.putIfAbsent(classElement, () { |
| - ClassBuilder builder = new ClassBuilder(classElement, namer); |
| + ClassBuilder builder = |
| + new ClassBuilder.forClass(classElement, namer); |
| classEmitter.emitClass(cls, builder, fragment); |
| return builder; |
| }); |
| @@ -525,7 +518,7 @@ class OldEmitter implements Emitter { |
| // We need to filter out null-elements for the interceptors. |
| // TODO(floitsch): use the precomputed interceptors here. |
| if (element == null) continue; |
| - ClassBuilder builder = new ClassBuilder(element, namer); |
| + ClassBuilder builder = new ClassBuilder.forStatics(element, namer); |
| containerBuilder.addMemberMethod(method, builder); |
| getElementDescriptor(element, fragment).properties |
| .addAll(builder.properties); |
| @@ -625,12 +618,12 @@ class OldEmitter implements Emitter { |
| // before code generation. |
| if (code == null) continue; |
| if (compiler.enableMinification) { |
| - laziesInfo.addAll([js.string(namer.globalPropertyName(element)), |
| - js.string(namer.lazyInitializerName(element)), |
| + laziesInfo.addAll([js.quoteName(namer.globalPropertyName(element)), |
| + js.quoteName(namer.lazyInitializerName(element)), |
| code]); |
| } else { |
| - laziesInfo.addAll([js.string(namer.globalPropertyName(element)), |
| - js.string(namer.lazyInitializerName(element)), |
| + laziesInfo.addAll([js.quoteName(namer.globalPropertyName(element)), |
| + js.quoteName(namer.lazyInitializerName(element)), |
| code, |
| js.string(element.name)]); |
| } |
| @@ -655,8 +648,8 @@ class OldEmitter implements Emitter { |
| // in new lazy values. |
| return js('#(#,#,#,#,#)', |
| [js(lazyInitializerName), |
| - js.string(namer.globalPropertyName(element)), |
| - js.string(namer.lazyInitializerName(element)), |
| + js.quoteName(namer.globalPropertyName(element)), |
| + js.quoteName(namer.lazyInitializerName(element)), |
| code, |
| js.string(element.name), |
| isolateProperties]); |
| @@ -665,14 +658,14 @@ class OldEmitter implements Emitter { |
| if (compiler.enableMinification) { |
| return js('#(#,#,#)', |
| [js(lazyInitializerName), |
| - js.string(namer.globalPropertyName(element)), |
| - js.string(namer.lazyInitializerName(element)), |
| + js.quoteName(namer.globalPropertyName(element)), |
| + js.quoteName(namer.lazyInitializerName(element)), |
| code]); |
| } else { |
| return js('#(#,#,#,#)', |
| [js(lazyInitializerName), |
| - js.string(namer.globalPropertyName(element)), |
| - js.string(namer.lazyInitializerName(element)), |
| + js.quoteName(namer.globalPropertyName(element)), |
| + js.quoteName(namer.lazyInitializerName(element)), |
| code, |
| js.string(element.name)]); |
| } |
| @@ -720,16 +713,15 @@ class OldEmitter implements Emitter { |
| } |
| jsAst.Statement buildConstantInitializer(ConstantValue constant) { |
| - String name = namer.constantName(constant); |
| + jsAst.Name name = namer.constantName(constant); |
| return js.statement('#.# = #', |
| [namer.globalObjectForConstant(constant), name, |
| constantInitializerExpression(constant)]); |
| } |
| - jsAst.Template get makeConstantListTemplate { |
| + jsAst.Expression constantListGenerator(jsAst.Expression array) { |
| // TODO(floitsch): there is no harm in caching the template. |
| - return jsAst.js.uncachedExpressionTemplate( |
| - '${namer.isolateName}.$makeConstListProperty(#)'); |
| + return js('${namer.isolateName}.#(#)', [makeConstListProperty, array]); |
| } |
| jsAst.Statement buildMakeConstantList() { |
| @@ -1024,12 +1016,11 @@ class OldEmitter implements Emitter { |
| } |
| void assemblePrecompiledConstructor(OutputUnit outputUnit, |
| - String constructorName, |
| + jsAst.Name constructorName, |
| jsAst.Expression constructorAst, |
| List<String> fields) { |
| cspPrecompiledFunctionFor(outputUnit).add( |
| - new jsAst.FunctionDeclaration( |
| - new jsAst.VariableDeclaration(constructorName), constructorAst)); |
| + new jsAst.FunctionDeclaration(constructorName, constructorAst)); |
| String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME; |
| bool hasIsolateSupport = compiler.hasIsolateSupport; |
| @@ -1051,7 +1042,7 @@ class OldEmitter implements Emitter { |
| }''', |
| {"constructorName": constructorName, |
| "typeNameProperty": typeNameProperty, |
| - "constructorNameString": js.string(constructorName), |
| + "constructorNameString": js.quoteName(constructorName), |
| "hasIsolateSupport": hasIsolateSupport, |
| "fieldNamesArray": fieldNamesArray})); |
| @@ -1073,9 +1064,9 @@ class OldEmitter implements Emitter { |
| // typedefs is supported. |
| jsAst.Expression typeIndex = |
| task.metadataCollector.reifyType(type, ignoreTypeVariables: true); |
| - ClassBuilder builder = new ClassBuilder(typedef, namer); |
| - builder.addProperty(embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME, typeIndex); |
| - builder.addProperty(embeddedNames.TYPEDEF_PREDICATE_PROPERTY_NAME, |
| + ClassBuilder builder = new ClassBuilder.forStatics(typedef, namer); |
| + builder.addPropertyByName(embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME, typeIndex); |
|
floitsch
2015/06/22 17:43:44
long line.
herhut
2015/06/23 13:26:31
Done.
|
| + builder.addPropertyByName(embeddedNames.TYPEDEF_PREDICATE_PROPERTY_NAME, |
| js.boolean(true)); |
| // We can be pretty sure that the objectClass is initialized, since |
| @@ -1084,13 +1075,13 @@ class OldEmitter implements Emitter { |
| assert(compiler.objectClass != null); |
| builder.superName = namer.className(compiler.objectClass); |
| jsAst.Node declaration = builder.toObjectInitializer(); |
| - String mangledName = namer.globalPropertyName(typedef); |
| + jsAst.Name mangledName = namer.globalPropertyName(typedef); |
| String reflectionName = getReflectionName(typedef, mangledName); |
| getElementDescriptor(library, mainFragment) |
| ..addProperty(mangledName, declaration) |
| - ..addProperty("+$reflectionName", js.string('')); |
| + ..addPropertyByName("+$reflectionName", js.string('')); |
| // Also emit a trivial constructor for CSP mode. |
| - String constructorName = mangledName; |
| + jsAst.Name constructorName = mangledName; |
| jsAst.Expression constructorAst = js('function() {}'); |
| List<String> fieldNames = []; |
| assemblePrecompiledConstructor(mainOutputUnit, |
| @@ -1190,12 +1181,11 @@ class OldEmitter implements Emitter { |
| List<jsAst.Statement> parts = <jsAst.Statement>[]; |
| if (!mangledFieldNames.isEmpty) { |
| - var keys = mangledFieldNames.keys.toList(); |
| - keys.sort(); |
| + List<jsAst.Name> keys = mangledFieldNames.keys.toList()..sort(); |
| var properties = []; |
| - for (String key in keys) { |
| - var value = js.string('${mangledFieldNames[key]}'); |
| - properties.add(new jsAst.Property(js.string(key), value)); |
| + for (jsAst.Name key in keys) { |
| + var value = js.string(mangledFieldNames[key]); |
| + properties.add(new jsAst.Property(key, value)); |
| } |
| jsAst.Expression mangledNamesAccess = |
| @@ -1205,12 +1195,11 @@ class OldEmitter implements Emitter { |
| } |
| if (!mangledGlobalFieldNames.isEmpty) { |
| - var keys = mangledGlobalFieldNames.keys.toList(); |
| - keys.sort(); |
| + var keys = mangledGlobalFieldNames.keys.toList()..sort(); |
|
floitsch
2015/06/22 17:43:44
I prefer it in a separate line.
Otherwise it's har
floitsch
2015/06/22 17:43:44
Please add types in this function.
herhut
2015/06/23 13:26:31
Done.
herhut
2015/06/23 13:26:31
Done.
|
| var properties = []; |
| - for (String key in keys) { |
| - var value = js.string('${mangledGlobalFieldNames[key]}'); |
| - properties.add(new jsAst.Property(js.string(key), value)); |
| + for (jsAst.Name key in keys) { |
| + var value = js.string(mangledGlobalFieldNames[key]); |
| + properties.add(new jsAst.Property(js.quoteName(key), value)); |
| } |
| jsAst.Expression mangledGlobalNamesAccess = |
| generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); |
| @@ -1717,6 +1706,7 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) { |
| ClassBuilder getElementDescriptor(Element element, Fragment fragment) { |
| Element owner = element.library; |
| + bool isClass = false; |
| if (!element.isLibrary && !element.isTopLevel && !element.isNative) { |
| // For static (not top level) elements, record their code in a buffer |
| // specific to the class. For now, not supported for native classes and |
| @@ -1735,7 +1725,9 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) { |
| } |
| return elementDescriptors |
| .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>()) |
| - .putIfAbsent(owner, () => new ClassBuilder(owner, namer)); |
| + .putIfAbsent(owner, () { |
| + return new ClassBuilder(owner, namer, owner.isClass); |
| + }); |
| } |
| /// Emits support-code for deferred loading into [output]. |
| @@ -1757,11 +1749,12 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) { |
| // Function for initializing a loaded hunk, given its hash. |
| #initializeLoadedHunk = function(hunkHash) { |
| $deferredInitializers[hunkHash]( |
| - $globalsHolder, ${namer.currentIsolate}); |
| + #globalsHolder, ${namer.currentIsolate}); |
| #deferredInitialized[hunkHash] = true; |
| }; |
| } |
| - ''', {"isHunkLoaded": generateEmbeddedGlobalAccess( |
| + ''', {"globalsHolder": globalsHolder, |
| + "isHunkLoaded": generateEmbeddedGlobalAccess( |
| embeddedNames.IS_HUNK_LOADED), |
| "isHunkInitialized": generateEmbeddedGlobalAccess( |
| embeddedNames.IS_HUNK_INITIALIZED), |
| @@ -1834,14 +1827,18 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) { |
| body.add(js.comment("/* ::norenaming:: ")); |
| for (String globalObject in Namer.reservedGlobalObjectNames) { |
| - body.add(js.statement('var #object = ${globalsHolder}.#object;', |
| - {'object': globalObject})); |
| + body.add(js.statement('var #object = #globalsHolder.#object;', |
| + {'globalsHolder': globalsHolder, |
| + 'object': globalObject})); |
| } |
| - body..add(js.statement('var init = ${globalsHolder}.init;')) |
| + body..add(js.statement('var init = #globalsHolder.init;', |
| + {'globalsHolder': globalsHolder})) |
| ..add(js.statement('var $setupProgramName = ' |
| - '$globalsHolder.$setupProgramName;')) |
| + '#globalsHolder.$setupProgramName;', |
| + {'globalsHolder': globalsHolder})) |
| ..add(js.statement('var ${namer.isolateName} = ' |
| - '${globalsHolder}.${namer.isolateName};')); |
| + '#globalsHolder.${namer.isolateName};', |
| + {'globalsHolder': globalsHolder})); |
| String typesAccess = |
| generateEmbeddedGlobalAccessString(embeddedNames.TYPES); |
| if (libraryDescriptor != null) { |
| @@ -1874,10 +1871,10 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) { |
| statements |
| ..add(buildGeneratedBy()) |
| ..add(js.statement('${deferredInitializers}.current = ' |
| - """function (${globalsHolder}) { |
| + """function (#) { |
| # |
| } |
| - """, [body])); |
| + """, [globalsHolder, body])); |
| result[outputUnit] = new jsAst.Program(statements); |
| } |