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

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

Issue 15987007: Revert r23380, some browser tests fail. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 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
===================================================================
--- sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart (revision 23381)
+++ sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart (working copy)
@@ -58,6 +58,7 @@
bool needsInheritFunction = false;
bool needsDefineClass = false;
bool needsMixinSupport = false;
+ bool needsClosureClass = false;
bool needsLazyInitializer = false;
final Namer namer;
ConstantEmitter constantEmitter;
@@ -93,6 +94,13 @@
final Map<int, String> boundClosureCache;
/**
+ * A cache of closures that are used to closurize instance methods
+ * of interceptors. These closures are dynamically bound to the
+ * interceptor instance, and the actual receiver of the method.
+ */
+ final Map<int, String> interceptorClosureCache;
+
+ /**
* Raw ClassElement symbols occuring in is-checks and type assertions. If the
* program contains parameterized checks `x is Set<int>` and
* `x is Set<String>` then the ClassElement `Set` will occur once in
@@ -125,6 +133,7 @@
: mainBuffer = new CodeBuffer(),
this.namer = namer,
boundClosureCache = new Map<int, String>(),
+ interceptorClosureCache = new Map<int, String>(),
constantEmitter = new ConstantEmitter(compiler, namer),
super(compiler) {
nativeEmitter = new NativeEmitter(this);
@@ -1747,6 +1756,19 @@
return (ClassElement cls) => !unneededClasses.contains(cls);
}
+ void emitClosureClassIfNeeded(CodeBuffer buffer) {
+ // The closure class could have become necessary because of the generation
+ // of stubs.
+ ClassElement closureClass = compiler.closureClass;
+ if (needsClosureClass && !instantiatedClasses.contains(closureClass)) {
+ ClassElement objectClass = compiler.objectClass;
+ if (!instantiatedClasses.contains(objectClass)) {
+ generateClass(objectClass, bufferForElement(objectClass, buffer));
+ }
+ generateClass(closureClass, bufferForElement(closureClass, buffer));
+ }
+ }
+
void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) {
if (needsDefineClass) {
buffer.write('$finishClassesName($classesCollector,'
@@ -1830,10 +1852,10 @@
compiler.codegenWorld.staticFunctionsNeedingGetter;
for (FunctionElement element in
Elements.sortedByPosition(functionsNeedingGetter)) {
- assert(instantiatedClasses.contains(compiler.closureClass));
String staticName = namer.getName(element);
String superName = namer.getName(compiler.closureClass);
String name = 'Closure\$${element.name.slowToString()}';
+ needsClosureClass = true;
ClassElement closureClassElement = new ClosureClassElement(
null, new SourceString(name), compiler, element,
@@ -1892,7 +1914,6 @@
*/
void emitDynamicFunctionGetter(FunctionElement member,
DefineStubFunction defineStub) {
- assert(instantiatedClasses.contains(compiler.boundClosureClass));
assert(invariant(member, member.isDeclaration));
// For every method that has the same name as a property-get we create a
// getter that returns a bound closure. Say we have a class 'A' with method
@@ -1903,9 +1924,10 @@
// foo(x, y, z) { ... } // Original function.
// get foo { return new BoundClosure499(this, "foo"); }
// }
- // class BoundClosure499 extends BoundClosure {
- // BoundClosure499(this.self, this.target);
- // $call3(x, y, z) { return self[target](x, y, z); }
+ // class BoundClosure499 extends Closure {
+ // var self;
+ // BoundClosure499(this.self, this.name);
+ // $call3(x, y, z) { return self[name](x, y, z); }
// }
// TODO(floitsch): share the closure classes with other classes
@@ -1917,14 +1939,22 @@
bool hasOptionalParameters = member.optionalParameterCount(compiler) != 0;
int parameterCount = member.parameterCount(compiler);
- Map<int, String> cache = boundClosureCache;
+ Map<int, String> cache;
+ String extraArg = null;
// Intercepted methods take an extra parameter, which is the
// receiver of the call.
bool inInterceptor = backend.isInterceptedMethod(member);
- List<String> fieldNames = <String>[];
- compiler.boundClosureClass.forEachInstanceField((_, field) {
- fieldNames.add(namer.getName(field));
- });
+ if (inInterceptor) {
+ cache = interceptorClosureCache;
+ extraArg = 'receiver';
+ } else {
+ cache = boundClosureCache;
+ }
+ List<String> fieldNames = compiler.enableMinification
+ ? inInterceptor ? const ['a', 'b', 'c']
+ : const ['a', 'b']
+ : inInterceptor ? const ['self', 'target', 'receiver']
+ : const ['self', 'target'];
Iterable<Element> typedefChecks =
getTypedefChecksOn(member.computeType(compiler));
@@ -1938,7 +1968,11 @@
// Create a new closure class.
String name;
if (canBeShared) {
- name = 'BoundClosure\$${parameterCount}';
+ if (inInterceptor) {
+ name = 'BoundClosure\$i${parameterCount}';
+ } else {
+ name = 'BoundClosure\$${parameterCount}';
+ }
} else {
name = 'Bound_${member.name.slowToString()}'
'_${member.enclosingElement.name.slowToString()}';
@@ -1949,6 +1983,7 @@
member.getCompilationUnit());
String mangledName = namer.getName(closureClassElement);
String superName = namer.getName(closureClassElement.superclass);
+ needsClosureClass = true;
// Define the constructor with a name so that Object.toString can
// find the class name of the closure class.
@@ -2009,8 +2044,8 @@
arguments.add(js('this'));
arguments.add(js.string(targetName));
if (inInterceptor) {
- parameters.add('receiver');
- arguments.add(js('receiver'));
+ parameters.add(extraArg);
+ arguments.add(js(extraArg));
}
jsAst.Expression getterFunction = js.fun(
@@ -2962,6 +2997,7 @@
}
emitStaticFunctionClosures();
+ emitClosureClassIfNeeded(mainBuffer);
addComment('Bound closures', mainBuffer);
// Now that we have emitted all classes, we know all the bound

Powered by Google App Engine
This is Rietveld 408576698