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

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

Issue 11795002: Revert "Retry "Emit more stuff via ASTs"" (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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/native_emitter.dart
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
index f51edba43a1a1d099484f37b7f686a6edce5b67c..84e57f1402a2c844a2f8a37cdea20866df370c59 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -125,25 +125,45 @@ function(cls, desc) {
}
void generateNativeClass(ClassElement classElement) {
- assert(classElement.backendMembers.isEmpty);
nativeClasses.add(classElement);
- ClassBuilder builder = new ClassBuilder();
- emitter.emitClassFields(classElement, builder, classIsNative: true);
- emitter.emitClassGettersSetters(classElement, builder);
- emitter.emitInstanceMembers(classElement, builder);
+ assert(classElement.backendMembers.isEmpty);
+ String quotedName = classElement.nativeTagInfo.slowToString();
- // An empty native class may be omitted since the superclass methods can be
- // located via the dispatch metadata.
- if (builder.properties.isEmpty) return;
+ CodeBuffer fieldBuffer = new CodeBuffer();
+ CodeBuffer getterSetterBuffer = new CodeBuffer();
+ CodeBuffer methodBuffer = new CodeBuffer();
- String nativeTag = toNativeTag(classElement);
- js.Expression definition =
- js.call(js.use(defineNativeClassName),
- [js.string(nativeTag), builder.toObjectInitializer()]);
+ emitter.emitClassFields(classElement, fieldBuffer, false,
+ classIsNative: true);
+ emitter.emitClassGettersSetters(classElement, getterSetterBuffer, false);
+ emitter.emitInstanceMembers(classElement, methodBuffer, false);
+
+ if (methodBuffer.isEmpty
+ && fieldBuffer.isEmpty
+ && getterSetterBuffer.isEmpty) {
+ return;
+ }
- nativeBuffer.add(js.prettyPrint(definition, compiler));
- nativeBuffer.add('$N$n');
+ String nativeTag = toNativeTag(classElement);
+ nativeBuffer.add("$defineNativeClassName('$nativeTag',$_");
+ nativeBuffer.add('{');
+ bool firstInMap = true;
+ if (!fieldBuffer.isEmpty) {
+ firstInMap = false;
+ nativeBuffer.add(fieldBuffer);
+ }
+ if (!getterSetterBuffer.isEmpty) {
+ if (!firstInMap) nativeBuffer.add(",");
+ firstInMap = false;
+ nativeBuffer.add("\n$_");
+ nativeBuffer.add(getterSetterBuffer);
+ }
+ if (!methodBuffer.isEmpty) {
+ if (!firstInMap) nativeBuffer.add(",");
+ nativeBuffer.add(methodBuffer);
+ }
+ nativeBuffer.add('$n})$N$n');
classesWithDynamicDispatch.add(classElement);
}
@@ -176,10 +196,11 @@ function(cls, desc) {
statements.add(
new js.ExpressionStatement(
- js.assign(
- js.use(name),
- js.use(closureConverter).callWith(
- [js.use(name), new js.LiteralNumber('$arity')]))));
+ new js.Assignment(
+ new js.VariableUse(name),
+ new js.VariableUse(closureConverter)
+ .callWith([new js.VariableUse(name),
+ new js.LiteralNumber('$arity')]))));
break;
}
}
@@ -203,6 +224,7 @@ function(cls, desc) {
// foo(null, y).
ClassElement classElement = member.enclosingElement;
+ //String nativeTagInfo = classElement.nativeName.slowToString();
String nativeTagInfo = classElement.nativeTagInfo.slowToString();
List<js.Statement> statements = <js.Statement>[];
@@ -246,16 +268,23 @@ function(cls, desc) {
String methodName,
js.Statement body,
List<js.Parameter> parameters) {
- return js.if_(
- js.use('Object').dot('getPrototypeOf')
- .callWith([js.use('this')])
- .dot('hasOwnProperty').callWith([js.string(methodName)]),
+ return new js.If(
+ new js.VariableUse('Object')
+ .dot('getPrototypeOf')
+ .callWith([new js.VariableUse('this')])
+ .dot('hasOwnProperty')
+ .callWith([new js.LiteralString("'$methodName'")]),
body,
- js.return_(
- js.use('Object').dot('prototype').dot(methodName).dot('call')
- .callWith(
- <js.Expression>[js.use('this')]..addAll(
- parameters.map((param) => js.use(param.name))))));
+ new js.Block(
+ <js.Statement>[
+ new js.Return(
+ new js.VariableUse('Object')
+ .dot('prototype').dot(methodName).dot('call')
+ .callWith(
+ <js.Expression>[new js.VariableUse('this')]
+ ..addAll(parameters.map((param) =>
+ new js.VariableUse(param.name)))))
+ ]));
}
js.Block generateMethodBodyWithPrototypeCheckForElement(
@@ -271,7 +300,7 @@ function(cls, desc) {
} else if (element.kind == ElementKind.SETTER) {
methodName = namer.setterName(element.getLibrary(), element.name);
} else {
- compiler.internalError("unexpected kind: '${element.kind}'",
+ compiler.internalError('unexpected kind: "${element.kind}"',
element: element);
}
@@ -371,14 +400,17 @@ function(cls, desc) {
walk(classElement);
if (!subtags.isEmpty) {
- expressions.add(js.string(Strings.join(subtags, '|')));
+ expressions.add(
+ new js.LiteralString("'${Strings.join(subtags, '|')}'"));
}
js.Expression expression;
if (expressions.length == 1) {
expression = expressions[0];
} else {
js.Expression array = new js.ArrayInitializer.from(expressions);
- expression = js.call(array.dot('join'), [js.string('|')]);
+ expression = new js.Call(
+ new js.PropertyAccess.field(array, 'join'),
+ [new js.LiteralString("'|'")]);
}
return expression;
}
@@ -413,7 +445,7 @@ function(cls, desc) {
new js.ArrayInitializer.from(
preorderDispatchClasses.map((cls) =>
new js.ArrayInitializer.from([
- js.string(toNativeTag(cls)),
+ new js.LiteralString("'${toNativeTag(cls)}'"),
tagDefns[cls]])));
// $.dynamicSetMetadata(table);
@@ -459,86 +491,67 @@ function(cls, desc) {
return isSupertypeOfNativeClass(element);
}
+ void emitIsChecks(Map<String, String> objectProperties) {
+ for (Element element in emitter.checkedClasses) {
+ if (!requiresNativeIsCheck(element)) continue;
+ if (element.isObject(compiler)) continue;
+ String name = backend.namer.operatorIs(element);
+ objectProperties[name] = 'function()$_{${_}return false;$_}';
+ }
+ }
+
void assembleCode(CodeBuffer targetBuffer) {
if (nativeClasses.isEmpty) return;
emitDynamicDispatchMetadata();
targetBuffer.add('$defineNativeClassName = '
'$defineNativeClassFunction$N$n');
- List<js.Property> objectProperties = <js.Property>[];
-
- void addProperty(String name, js.Expression value) {
- objectProperties.add(new js.Property(js.string(name), value));
- }
-
// Because of native classes, we have to generate some is checks
// by calling a method, instead of accessing a property. So we
// attach to the JS Object prototype these methods that return
// false, and will be overridden by subclasses when they have to
// return true.
- void emitIsChecks() {
- for (Element element in
- Elements.sortedByPosition(emitter.checkedClasses)) {
- if (!requiresNativeIsCheck(element)) continue;
- if (element.isObject(compiler)) continue;
- String name = backend.namer.operatorIs(element);
- addProperty(name,
- js.fun([], js.block1(js.return_(new js.LiteralBool(false)))));
- }
- }
- emitIsChecks();
-
- js.Expression makeCallOnThis(String functionName) =>
- js.fun([],
- js.block1(
- js.return_(
- js.call(js.use(functionName), [js.use('this')]))));
+ Map<String, String> objectProperties = new Map<String, String>();
+ emitIsChecks(objectProperties);
// In order to have the toString method on every native class,
// we must patch the JS Object prototype with a helper method.
String toStringName = backend.namer.publicInstanceMethodNameByArity(
const SourceString('toString'), 0);
- addProperty(toStringName, makeCallOnThis(toStringHelperName));
+ objectProperties[toStringName] =
+ 'function() { return $toStringHelperName(this); }';
// Same as above, but for hashCode.
String hashCodeName =
backend.namer.publicGetterName(const SourceString('hashCode'));
- addProperty(hashCodeName, makeCallOnThis(hashCodeHelperName));
+ objectProperties[hashCodeName] =
+ 'function() { return $hashCodeHelperName(this); }';
// If the native emitter has been asked to take care of the
// noSuchMethod handlers, we do that now.
if (handleNoSuchMethod) {
- emitter.emitNoSuchMethodHandlers(addProperty);
+ emitter.emitNoSuchMethodHandlers((String name, CodeBuffer buffer) {
+ objectProperties[name] = buffer.toString();
+ });
}
// If we have any properties to add to Object.prototype, we run
// through them and add them using defineProperty.
if (!objectProperties.isEmpty) {
- js.Expression init =
- js.call(
- js.fun(['table'],
- js.block1(
- new js.ForIn(
- new js.VariableDeclarationList(
- [new js.VariableInitialization(
- new js.VariableDeclaration('key'),
- null)]),
- js.use('table'),
- new js.ExpressionStatement(
- js.call(
- js.use(defPropName),
- [js.use('Object').dot('prototype'),
- js.use('key'),
- new js.PropertyAccess(js.use('table'),
- js.use('key'))]))))),
- [new js.ObjectInitializer(objectProperties)]);
-
- if (emitter.compiler.enableMinification) targetBuffer.add(';');
- targetBuffer.add(js.prettyPrint(
- new js.ExpressionStatement(init), compiler));
- targetBuffer.add('\n');
+ if (emitter.compiler.enableMinification) targetBuffer.add(";");
+ targetBuffer.add("(function(table) {\n"
+ " for (var key in table) {\n"
+ " $defPropName(Object.prototype, key, table[key]);\n"
+ " }\n"
+ "})({\n");
+ bool first = true;
+ objectProperties.forEach((String name, String function) {
+ if (!first) targetBuffer.add(",\n");
+ targetBuffer.add("$_$name:$_$function");
+ first = false;
+ });
+ targetBuffer.add("\n})$N$n");
}
-
targetBuffer.add(nativeBuffer);
targetBuffer.add('\n');
}

Powered by Google App Engine
This is Rietveld 408576698