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

Unified Diff: sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart

Issue 11598006: Concept of how dart:mirrors LibraryMirror, ClassMirror can be implemented in dart2js. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Added enough closure support to get tests/lib/mirrors/mirrors_test.dart pass. Created 7 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: sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 58debdba0858b1686abc9702ca6cd7ce12610569..3a7f5ee8cb7db248b0ad276b40084d9335d64f3f 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -48,6 +48,9 @@ class CodeEmitterTask extends CompilerTask {
// TODO(ngeoffray): remove this field.
Set<ClassElement> instantiatedClasses;
+ List<js.Expression> libraryMirrorsParametersList;
+ Map<String, int> libraryMirrorsIndices;
+
String get _ => compiler.enableMinification ? "" : " ";
String get n => compiler.enableMinification ? "" : "\n";
String get N => compiler.enableMinification ? "\n" : ";\n";
@@ -1030,6 +1033,16 @@ $lazyInitializerLogic
});
}
+ void emitClassLibraryGetter(ClassElement classElement, CodeBuffer buffer) {
+ var name = classElement.getLibrary().getLibraryOrScriptName();
+ // Some builtin classes come from js_helper libraries, which are
+ // not in libraryMirrorsIndices collection. At this point we
+ // will ignore them.
+ if (libraryMirrorsIndices.containsKey(name)) {
+ buffer.add(",$n$_${_}builtin\$library:$_${libraryMirrorsIndices[name]}");
+ }
+ }
+
/**
* Documentation wanted -- johnniwinther
*
@@ -1065,6 +1078,9 @@ $lazyInitializerLogic
// syntax.
emitClassGettersSetters(classElement, buffer, true);
emitInstanceMembers(classElement, buffer, true);
+ if (compiler.hasMirrorsSupport()) {
+ emitClassLibraryGetter(classElement, buffer);
+ }
buffer.add('$n}$N$n');
}
@@ -2107,9 +2123,194 @@ if (typeof document !== 'undefined' && document.readyState !== 'complete') {
}
}
+ Collection<js.Expression> extract(listElements, filterToApply) {
+ return new js.ArrayInitializer.from(
+ listElements
+ .filter(filterToApply)
+ .map((member) => js.string(namer.getName(member))));
+ }
+
+ Collection extractClasses(listElements) {
+ var classDescriptions = [];
+ var classes = listElements.filter((e) => Elements.isClass(e));
+ for (Element classElement in classes) {
+ var classMembers = [];
+ for (var classMember in classElement.localMembers) {
+ var prefixType;
+ var name;
+ if (classMember.isGetter()) {
+ prefixType = 'G';
+ name = qualifiedFunctionName(classMember);
+ } else if (classMember.isSetter()) {
+ prefixType = 'S';
+ name = qualifiedFunctionName(classMember);
+ } else if (classMember.isField()) {
+ prefixType = 'V';
+ name = qualifiedVariableName(classMember);
+ } else if (classMember.isConstructor()) {
+ prefixType = 'C';
+ name = namer.getName(classMember);
+ } else if (classMember.isTypeVariable()) {
+ prefixType = 'T';
+ name = namer.getName(classMember);
+ } else if (classMember.isParameter()) {
+ prefixType = 'A';
+ name = namer.getName(classMember);
+ } else {
+ prefixType = 'M';
+ name = qualifiedFunctionName(classMember);
+ }
+ var originalName = classMember.name.slowToString();
+ if (name != originalName) {
+ name = "$name[$originalName]";
+ }
+ classMembers.add(js.string("$prefixType:$name"));
+ }
+ classDescriptions.add(
+ new js.ArrayInitializer.from(
+ [js.string(namer.getName(classElement)),
+ new js.ArrayInitializer.from(classMembers)]));
+ }
+ return new js.ArrayInitializer.from(classDescriptions);
+ }
+
+ String qualifiedFunctionName(Element functionElement) {
+ String prefixType;
+ if (functionElement.modifiers.isStatic()) {
+ prefixType = 'S';
+ } else {
+ prefixType = 'I';
+ }
+ var typeName = "";
+ var libraryID = "";
+ assert(functionElement.type != null);
+ DartType dt = functionElement.type;
+ // Ignore types that weren't computed.
+ if (dt != null) {
+ if (dt.kind == TypeKind.FUNCTION) {
+ typeName = dt.returnType.name.slowToString();
+ if (typeName == 'void' || typeName == 'dynamic') {
+ libraryID = "";
+ } else {
+ var library = dt.returnType.element.getLibrary();
+ var libraryName = library.getLibraryOrScriptName();
+ libraryID = libraryMirrorsIndices[libraryName];
+ }
+ }
+ }
+ return "$prefixType:$libraryID:$typeName:${namer.getName(functionElement)}";
+ }
+
+ Collection extractMethods(listElements, filterToApply) {
+ var methodsDescription =
+ listElements
+ .filter(filterToApply)
+ .map((e) => js.string(qualifiedFunctionName(e)));
+ return new js.ArrayInitializer.from(methodsDescription);
+ }
+
+ String qualifiedVariableName(Element fieldElement) {
+ String prefixType;
+ if (fieldElement.modifiers.isStatic()) {
+ prefixType = 'S';
+ } else {
+ prefixType = 'I';
+ }
+ // Use case to indicate whether field is final or not.
+ // Is it too fancy?
+ if (fieldElement.modifiers.isFinal()) {
+ prefixType = prefixType.toLowerCase();
+ }
+ var name = namer.getName(fieldElement);
+ var originalName = fieldElement.name.slowToString();
+ if (name != originalName) {
+ name = "$name[$originalName]";
+ }
+ return "$prefixType:$name";
+ }
+
+ Collection extractVariables(listElements) {
+ var fieldsDescription =
+ listElements
+ .filter((e) => e.isField())
+ .map((e) => js.string(qualifiedVariableName(e)));
+ return new js.ArrayInitializer.from(fieldsDescription);
+ }
+
+ Collection extractClosures(Collection<ClosureClassMap> listClosures) {
+ var closuresDescriptions =
+ listClosures.map(
+ (map) => js.string(
+ "${namer.getName(map.closureClassElement)}:"
+ "${namer.getName(map.callElement)}:"
+ "${map.callElement.functionSignature.requiredParameterCount}:"
+ "${map.callElement.functionSignature.optionalParameterCount}:"));
+ return new js.ArrayInitializer.from(closuresDescriptions);
+ }
+
+ void computeLibraryMirrors() {
+ int index = 0;
+ libraryMirrorsParametersList = new List<js.Expression>();
+ libraryMirrorsIndices = new Map<String, int>();
+ for (LibraryElement libraryElement in compiler.libraries.values) {
+ //
+ // [lib1,
+ // [[class1, classConstructor, [member1,...]]
+ // ...],
+ // [function1...],
+ // [getter1...]
+ // [setter1...]
+ // [variable1...]
+ // [closure1...]
+ // ]...
+ //
+ var elements =
+ new List<Element>.from(libraryElement.localMembers);
+ var libraryName = libraryElement.getLibraryOrScriptName();
+ libraryMirrorsParametersList.add(
+ new js.ArrayInitializer.from(
+ <js.Expression>[
+ js.string(libraryName),
+ extractClasses(elements),
+ extractMethods(elements, (e) => e.isFunction()),
+ extractMethods(elements, (e) => e.isGetter()),
+ extractMethods(elements, (e) => e.isSetter()),
+ extractVariables(elements),
+ extractClosures(
+ new List<ClassElement>.from(
+ compiler.closureToClassMapper
+ .closureMappingCache.values
+ .filter((map) => map.closureElement != null
+ && map.closureElement.getLibrary()
+ == libraryElement)))
+ ]));
+ libraryMirrorsIndices[libraryName] = index++;
+ }
+ }
+
+ void emitMirrorsSupport(CodeBuffer buffer) {
+ Element createMirrorSystem =
+ compiler.mirrorsLibrary.find(Compiler.CREATE_MIRROR_SYSTEM);
+ String isolateCreateMirrorSystem =
+ namer.isolateAccess(createMirrorSystem);
+
+ // createMirrorSystem([library1, library2, ...])
+ var createMirrorSystemCall =
+ new js.ExpressionStatement(
+ js.call(
+ js.use(isolateCreateMirrorSystem),
+ [new js.ArrayInitializer.from(libraryMirrorsParametersList)]));
+ mainBuffer.add(js.prettyPrint(createMirrorSystemCall, compiler));
+ }
+
String assembleProgram() {
measure(() {
computeNeededClasses();
+ if (compiler.hasMirrorsSupport()) {
+ // Create library mirror structure up front so that we can refer to
+ // library elements during class construction by array index.
+ computeLibraryMirrors();
+ }
mainBuffer.add(GENERATED_BY);
if (!compiler.enableMinification) mainBuffer.add(HOOKS_API_USAGE);
@@ -2139,6 +2340,10 @@ if (typeof document !== 'undefined' && document.readyState !== 'complete') {
emitGetInterceptorMethods(mainBuffer);
emitLazilyInitializedStaticFields(mainBuffer);
+ if (compiler.hasMirrorsSupport()) {
+ emitMirrorsSupport(mainBuffer);
+ }
+
isolateProperties = isolatePropertiesName;
// The following code should not use the short-hand for the
// initialStatics.
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/enqueue.dart ('k') | sdk/lib/_internal/compiler/implementation/lib/js_helper.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698