Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Unified Diff: pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart

Issue 819993003: dart2js OldEmitter: inline FinishClasses. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Small fixes. Created 5 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart
index c9d20172b85a655466848c40fac4efa65b3edab2..89404d6882f75d2b816108ca675212a1fa3ef1c0 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart
@@ -14,9 +14,8 @@ const DEFAULT_ARGUMENTS_INDEX = 5;
const bool VALIDATE_DATA = false;
-// TODO(ahe): This code should be integrated in CodeEmitterTask.finishClasses.
-jsAst.Expression getReflectionDataParser(String classesCollector,
- JavaScriptBackend backend) {
+jsAst.Expression getReflectionDataParser(OldEmitter oldEmitter,
+ JavaScriptBackend backend) {
Namer namer = backend.namer;
Compiler compiler = backend.compiler;
CodeEmitterTask emitter = backend.emitter;
@@ -48,6 +47,8 @@ jsAst.Expression getReflectionDataParser(String classesCollector,
emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES);
jsAst.Expression librariesAccess =
emitter.generateEmbeddedGlobalAccess(embeddedNames.LIBRARIES);
+ jsAst.Expression metadataAccess =
+ emitter.generateEmbeddedGlobalAccess(embeddedNames.METADATA);
jsAst.Statement header = js.statement('''
// [map] returns an object literal that V8 shouldn not try to optimize with a
@@ -58,8 +59,89 @@ jsAst.Expression getReflectionDataParser(String classesCollector,
function map(x){x=Object.create(null);x.x=0;delete x.x;return x}
''');
+ jsAst.Statement processClassData = js.statement('''{
+ function processClassData(cls, descriptor, processedClasses) {
+ var newDesc = {};
+ var previousProperty;
+ for (var property in descriptor) {
+ if (!hasOwnProperty.call(descriptor, property)) continue;
+ var firstChar = property.substring(0, 1);
+ if (property === "static") {
+ processStatics(#embeddedStatics[cls] = descriptor[property],
+ processedClasses);
+ } else if (firstChar === "+") {
+ mangledNames[previousProperty] = property.substring(1);
+ var flag = descriptor[property];
+ if (flag > 0)
+ descriptor[previousProperty].$reflectableField = flag;
+ } else if (firstChar === "@" && property !== "@") {
+ newDesc[property.substring(1)][$metadataField] = descriptor[property];
+ } else if (firstChar === "*") {
+ newDesc[previousProperty].$defaultValuesField = descriptor[property];
+ var optionalMethods = newDesc.$methodsWithOptionalArgumentsField;
+ if (!optionalMethods) {
+ newDesc.$methodsWithOptionalArgumentsField = optionalMethods={}
+ }
+ optionalMethods[property] = previousProperty;
+ } else {
+ var elem = descriptor[property];
+ if (property !== "${namer.classDescriptorProperty}" &&
+ elem != null &&
+ elem.constructor === Array &&
+ property !== "<>") {
+ addStubs(newDesc, elem, property, false, descriptor, []);
+ } else {
+ newDesc[previousProperty = property] = elem;
+ }
+ }
+ }
+
+ /* The 'fields' are either a constructor function or a
+ * string encoding fields, constructor and superclass. Gets the
+ * superclass and fields in the format
+ * 'Super;field1,field2'
+ * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor.
+ */
+ var classData = newDesc["${namer.classDescriptorProperty}"],
+ split, supr, fields = classData;
+
+ if (#hasRetainedMetadata)
+ if (typeof classData == "object" &&
+ classData instanceof Array) {
+ classData = fields = classData[0];
+ }
+ // ${ClassBuilder.fieldEncodingDescription}.
+ var s = fields.split(";");
+ fields = s[1] == "" ? [] : s[1].split(",");
+ supr = s[0];
+ // ${ClassBuilder.functionTypeEncodingDescription}.
+ split = supr.split(":");
+ if (split.length == 2) {
+ supr = split[0];
+ var functionSignature = split[1];
+ if (functionSignature)
+ newDesc.${namer.operatorSignature} = function(s) {
+ return function() {
+ return #metadata[s];
+ };
+ }(functionSignature);
+ }
+
+ if (supr) processedClasses.pending[cls] = supr;
+ if (#notInCspMode) {
+ processedClasses.combinedConstructorFunction += defineClass(cls, fields);
+ processedClasses.constructorsList.push(cls);
+ }
+ processedClasses.collected[cls] = [globalObject, newDesc];
+ classes.push(cls);
+ }
+}''', {'embeddedStatics': staticsAccess,
+ 'hasRetainedMetadata': backend.hasRetainedMetadata,
+ 'metadata': metadataAccess,
+ 'notInCspMode': !compiler.useContentSecurityPolicy});
+
jsAst.Statement processStatics = js.statement('''
- function processStatics(descriptor) {
+ function processStatics(descriptor, processedClasses) {
for (var property in descriptor) {
if (!hasOwnProperty.call(descriptor, property)) continue;
if (property === "${namer.classDescriptorProperty}") continue;
@@ -72,7 +154,7 @@ jsAst.Expression getReflectionDataParser(String classesCollector,
if (flag > 0)
descriptor[previousProperty].$reflectableField = flag;
if (element && element.length)
- #[previousProperty] = element; // embedded typeInformation.
+ #typeInformation[previousProperty] = element;
} else if (firstChar === "@") {
property = property.substring(1);
${namer.currentIsolate}[property][$metadataField] = element;
@@ -86,51 +168,22 @@ jsAst.Expression getReflectionDataParser(String classesCollector,
} else if (typeof element === "function") {
globalObject[previousProperty = property] = element;
functions.push(property);
- #[property] = element; // embedded globalFunctions.
+ #globalFunctions[property] = element;
} else if (element.constructor === Array) {
addStubs(globalObject, element, property,
true, descriptor, functions);
} else {
- previousProperty = property;
- var newDesc = {};
- var previousProp;
- for (var prop in element) {
- if (!hasOwnProperty.call(element, prop)) continue;
- firstChar = prop.substring(0, 1);
- if (prop === "static") {
- processStatics(#[property] = element[prop]); // embedded statics.
- } else if (firstChar === "+") {
- mangledNames[previousProp] = prop.substring(1);
- var flag = element[prop];
- if (flag > 0)
- element[previousProp].$reflectableField = flag;
- } else if (firstChar === "@" && prop !== "@") {
- newDesc[prop.substring(1)][$metadataField] = element[prop];
- } else if (firstChar === "*") {
- newDesc[previousProp].$defaultValuesField = element[prop];
- var optionalMethods = newDesc.$methodsWithOptionalArgumentsField;
- if (!optionalMethods) {
- newDesc.$methodsWithOptionalArgumentsField = optionalMethods={}
- }
- optionalMethods[prop] = previousProp;
- } else {
- var elem = element[prop];
- if (prop !== "${namer.classDescriptorProperty}" &&
- elem != null &&
- elem.constructor === Array &&
- prop !== "<>") {
- addStubs(newDesc, elem, prop, false, element, []);
- } else {
- newDesc[previousProp = prop] = elem;
- }
- }
+ // We will not enter this case if no classes are defined.
+ if (#hasClasses) {
+ previousProperty = property;
+ processClassData(property, element, processedClasses);
}
- $classesCollector[property] = [globalObject, newDesc];
- classes.push(property);
}
}
}
-''', [typeInformationAccess, globalFunctionsAccess, staticsAccess]);
+''', {'typeInformation': typeInformationAccess,
+ 'globalFunctions': globalFunctionsAccess,
+ 'hasClasses': oldEmitter.needsClassSupport});
/**
@@ -226,18 +279,29 @@ jsAst.Expression getReflectionDataParser(String classesCollector,
jsAst.Statement init = js.statement('''{
var functionCounter = 0;
- if (!#) # = []; // embedded libraries.
- if (!#) # = map(); // embedded mangledNames.
- if (!#) # = map(); // embedded mangledGlobalNames.
- if (!#) # = map(); // embedded statics.
- if (!#) # = map(); // embedded typeInformation.
- if (!#) # = map(); // embedded globalFunctions.
- if (!#) # = map(); // embedded interceptedNames.
- var libraries = #; // embeded libraries.
- var mangledNames = #; // embedded mangledNames.
- var mangledGlobalNames = #; // embedded mangledGlobalNames.
+ if (!#libraries) #libraries = [];
+ if (!#mangledNames) #mangledNames = map();
+ if (!#mangledGlobalNames) #mangledGlobalNames = map();
+ if (!#statics) #statics = map();
+ if (!#typeInformation) #typeInformation = map();
+ if (!#globalFunctions) #globalFunctions = map();
+ if (!#interceptedNames) #interceptedNames = map();
+ var libraries = #libraries;
+ var mangledNames = #mangledNames;
+ var mangledGlobalNames = #mangledGlobalNames;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var length = reflectionData.length;
+ var processedClasses = Object.create(null);
+ processedClasses.collected = Object.create(null);
+ processedClasses.pending = Object.create(null);
+ if (#notInCspMode) {
+ processedClasses.constructorsList = [];
+ // For every class processed [processedClasses.combinedConstructorFunction]
+ // will be updated with the corresponding constructor function.
+ processedClasses.combinedConstructorFunction =
+ "function \$reflectable(fn){fn.$reflectableField=1;return fn};\\n"+
+ "var \$desc;\\n";
+ }
for (var i = 0; i < length; i++) {
var data = reflectionData[i];
@@ -262,20 +326,90 @@ jsAst.Expression getReflectionDataParser(String classesCollector,
if (fields instanceof Array) fields = fields[0];
var classes = [];
var functions = [];
- processStatics(descriptor);
+ processStatics(descriptor, processedClasses);
libraries.push([name, uri, classes, functions, metadata, fields, isRoot,
globalObject]);
}
-}''', [librariesAccess, librariesAccess,
- mangledNamesAccess, mangledNamesAccess,
- mangledGlobalNamesAccess, mangledGlobalNamesAccess,
- staticsAccess, staticsAccess,
- typeInformationAccess, typeInformationAccess,
- globalFunctionsAccess, globalFunctionsAccess,
- interceptedNamesAccess, interceptedNamesAccess,
- librariesAccess,
- mangledNamesAccess,
- mangledGlobalNamesAccess]);
+ if (#needsClassSupport) finishClasses(processedClasses);
+}''', {'libraries': librariesAccess,
+ 'mangledNames': mangledNamesAccess,
+ 'mangledGlobalNames': mangledGlobalNamesAccess,
+ 'statics': staticsAccess,
+ 'typeInformation': typeInformationAccess,
+ 'globalFunctions': globalFunctionsAccess,
+ 'interceptedNames': interceptedNamesAccess,
+ 'notInCspMode': !compiler.useContentSecurityPolicy,
+ 'needsClassSupport': oldEmitter.needsClassSupport});
+
+ jsAst.Expression allClassesAccess =
+ emitter.generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
+
+ String specProperty = '"${namer.nativeSpecProperty}"'; // "%"
+
+ // Class descriptions are collected in a JS object.
+ // 'finishClasses' takes all collected descriptions and sets up
+ // the prototype.
+ // Once set up, the constructors prototype field satisfy:
+ // - it contains all (local) members.
+ // - its internal prototype (__proto__) points to the superclass'
+ // prototype field.
+ // - the prototype's constructor field points to the JavaScript
+ // constructor.
+ // For engines where we have access to the '__proto__' we can manipulate
+ // the object literal directly. For other engines we have to create a new
+ // object and copy over the members.
+ jsAst.Statement finishClasses = js.statement('''{
+ function finishClasses(processedClasses) {
+ if (#debugFastObjects)
+ print("Number of classes: " +
+ Object.getOwnPropertyNames(processedClasses.collected).length);
+
+ var allClasses = #allClasses;
+
+ if (#inCspMode) {
+ constructors = dart_precompiled(processedClasses.collected);
+ }
+
+ if (#notInCspMode) {
+ processedClasses.combinedConstructorFunction +=
+ "return [\\n" + processedClasses.constructorsList.join(",\\n ") +
+ "\\n]";
+ var constructors =
+ new Function("\$collectedClasses",
+ processedClasses.combinedConstructorFunction)
+ (processedClasses.collected);
+ processedClasses.combinedConstructorFunction = null;
+ }
+
+ for (var i = 0; i < constructors.length; i++) {
+ var constructor = constructors[i];
+ var cls = constructor.name;
+ var desc = processedClasses.collected[cls];
+ var globalObject = \$;
+ if (desc instanceof Array) {
+ globalObject = desc[0] || \$;
+ desc = desc[1];
+ }
+ if (#isTreeShakingDisabled)
+ constructor["${namer.metadataField}"] = desc;
+ allClasses[cls] = constructor;
+ globalObject[cls] = constructor;
+ }
+ constructors = null;
+
+ #finishClassFunction;
+
+ #trivialNsmHandlers;
+
+ for (var cls in processedClasses.pending) finishClass(cls);
+ }
+}''', {'allClasses': allClassesAccess,
+ 'debugFastObjects': DEBUG_FAST_OBJECTS,
+ 'isTreeShakingDisabled': backend.isTreeShakingDisabled,
+ 'finishClassFunction': oldEmitter.buildFinishClass(),
+ 'trivialNsmHandlers': oldEmitter.buildTrivialNsmHandlers(),
+ 'inCspMode': compiler.useContentSecurityPolicy,
+ 'notInCspMode': !compiler.useContentSecurityPolicy});
List<jsAst.Statement> incrementalSupport = <jsAst.Statement>[];
if (compiler.hasIncrementalSupport) {
@@ -288,6 +422,12 @@ jsAst.Expression getReflectionDataParser(String classesCollector,
(function (reflectionData) {
"use strict";
#header;
+ if (#needsClassSupport) {
+ #defineClass;
+ #inheritFrom;
+ #finishClasses;
+ #processClassData;
+ }
#processStatics;
#addStubs;
#tearOffCode;
@@ -295,11 +435,16 @@ jsAst.Expression getReflectionDataParser(String classesCollector,
#init;
})''', {
'header': header,
+ 'defineClass': oldEmitter.defineClassFunction,
+ 'inheritFrom': oldEmitter.buildInheritFrom(),
+ 'processClassData': processClassData,
'processStatics': processStatics,
'incrementalSupport': incrementalSupport,
'addStubs': addStubs,
'tearOffCode': tearOffCode,
- 'init': init});
+ 'init': init,
+ 'finishClasses': finishClasses,
+ 'needsClassSupport': oldEmitter.needsClassSupport});
}
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart ('k') | pkg/dart2js_incremental/lib/caching_compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698