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

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

Issue 11413184: Create specialized versions of getInterceptor. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month 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/backend.dart
===================================================================
--- sdk/lib/_internal/compiler/implementation/js_backend/backend.dart (revision 15381)
+++ sdk/lib/_internal/compiler/implementation/js_backend/backend.dart (working copy)
@@ -635,14 +635,6 @@
Element jsArrayLength;
Element jsStringLength;
Element getInterceptorMethod;
- Element arrayInterceptor;
- Element boolInterceptor;
- Element doubleInterceptor;
- Element functionInterceptor;
- Element intInterceptor;
- Element nullInterceptor;
- Element numberInterceptor;
- Element stringInterceptor;
bool _interceptorsAreInitialized = false;
final Namer namer;
@@ -679,8 +671,25 @@
* name to the list of members that have that name. This map is used
* by the codegen to know whether a send must be intercepted or not.
*/
- final Map<SourceString, Set<Element>> interceptedElements;
+ final Map<SourceString, Set<Element>> interceptedElements;
+ /**
+ * A map of specialized versions of the [getInterceptorMethod].
+ * Since [getInterceptorMethod] is a hot method at runtime, we're
+ * always specializing it based on the incoming type. The keys in
+ * the map are the names of these specialized versions. Note that
+ * the generic version that contains all possible type checks is
+ * also stored in this map.
+ */
+ final Map<String, Collection<ClassElement>> specializedGetInterceptors;
+
+ /**
+ * Set of classes whose instances are intercepted. Implemented as a
+ * [LinkedHashMap] to preserve the insertion order.
+ * TODO(ngeoffray): Use a BitSet instead.
+ */
+ final Map<ClassElement, ClassElement> interceptedClasses;
+
List<CompilerTask> get tasks {
return <CompilerTask>[builder, optimizer, generator, emitter];
}
@@ -695,6 +704,9 @@
usedInterceptors = new Set<Selector>(),
interceptedElements = new Map<SourceString, Set<Element>>(),
rti = new RuntimeTypeInformation(compiler),
+ specializedGetInterceptors =
+ new Map<String, Collection<ClassElement>>(),
+ interceptedClasses = new LinkedHashMap<ClassElement, ClassElement>(),
super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) {
emitter = disableEval
? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap)
@@ -714,14 +726,7 @@
bool isInterceptorClass(Element element) {
if (element == null) return false;
- return element == jsStringClass
- || element == jsArrayClass
- || element == jsIntClass
- || element == jsDoubleClass
- || element == jsNullClass
- || element == jsFunctionClass
- || element == jsBoolClass
- || element == jsNumberClass;
+ return interceptedClasses.containsKey(element);
}
void addInterceptedSelector(Selector selector) {
@@ -746,50 +751,39 @@
return result;
}
+ List<ClassElement> getListOfInterceptedClasses() {
+ return <ClassElement>[jsStringClass, jsArrayClass, jsIntClass,
+ jsDoubleClass, jsNumberClass, jsNullClass,
+ jsFunctionClass, jsBoolClass];
+ }
+
void initializeInterceptorElements() {
objectInterceptorClass =
compiler.findInterceptor(const SourceString('ObjectInterceptor'));
getInterceptorMethod =
compiler.findInterceptor(const SourceString('getInterceptor'));
- jsStringClass =
- compiler.findInterceptor(const SourceString('JSString'));
- jsArrayClass =
- compiler.findInterceptor(const SourceString('JSArray'));
- jsNumberClass =
- compiler.findInterceptor(const SourceString('JSNumber'));
- jsIntClass =
- compiler.findInterceptor(const SourceString('JSInt'));
- jsDoubleClass =
- compiler.findInterceptor(const SourceString('JSDouble'));
- jsNullClass =
- compiler.findInterceptor(const SourceString('JSNull'));
- jsFunctionClass =
- compiler.findInterceptor(const SourceString('JSFunction'));
- jsBoolClass =
- compiler.findInterceptor(const SourceString('JSBool'));
+ List<ClassElement> classes = [
+ jsStringClass = compiler.findInterceptor(const SourceString('JSString')),
+ jsArrayClass = compiler.findInterceptor(const SourceString('JSArray')),
+ jsNumberClass = compiler.findInterceptor(const SourceString('JSNumber')),
+ jsIntClass = compiler.findInterceptor(const SourceString('JSInt')),
+ jsDoubleClass = compiler.findInterceptor(const SourceString('JSDouble')),
+ jsNullClass = compiler.findInterceptor(const SourceString('JSNull')),
+ jsFunctionClass =
+ compiler.findInterceptor(const SourceString('JSFunction')),
+ jsBoolClass = compiler.findInterceptor(const SourceString('JSBool'))];
+
jsArrayClass.ensureResolved(compiler);
jsArrayLength =
jsArrayClass.lookupLocalMember(const SourceString('length'));
+
jsStringClass.ensureResolved(compiler);
jsStringLength =
jsStringClass.lookupLocalMember(const SourceString('length'));
- arrayInterceptor =
- compiler.findInterceptor(const SourceString('arrayInterceptor'));
- boolInterceptor =
- compiler.findInterceptor(const SourceString('boolInterceptor'));
- doubleInterceptor =
- compiler.findInterceptor(const SourceString('doubleInterceptor'));
- functionInterceptor =
- compiler.findInterceptor(const SourceString('functionInterceptor'));
- intInterceptor =
- compiler.findInterceptor(const SourceString('intInterceptor'));
- nullInterceptor =
- compiler.findInterceptor(const SourceString('nullInterceptor'));
- stringInterceptor =
- compiler.findInterceptor(const SourceString('stringInterceptor'));
- numberInterceptor =
- compiler.findInterceptor(const SourceString('numberInterceptor'));
+ for (ClassElement cls in classes) {
+ interceptedClasses[cls] = null;
+ }
}
void addInterceptors(ClassElement cls) {
@@ -802,24 +796,32 @@
includeSuperMembers: true);
}
+ String registerSpecializedGetInterceptor(Set<ClassElement> classes) {
+ compiler.enqueuer.codegen.registerInstantiatedClass(objectInterceptorClass);
+ if (classes.contains(compiler.objectClass)) {
+ // We can't use a specialized [getInterceptorMethod], so we make
+ // sure we emit the one with all checks.
+ String name = namer.getName(getInterceptorMethod);
+ specializedGetInterceptors.putIfAbsent(name, () {
+ // It is important to take the order provided by this list,
+ // because we want the int type check to happen before the
+ // double type check: the double type check covers the int
+ // type check.
+ return interceptedClasses.keys;
+ });
+ return namer.isolateAccess(getInterceptorMethod);
+ } else {
+ String name = namer.getSpecializedName(getInterceptorMethod, classes);
+ specializedGetInterceptors[name] = classes;
+ return '${namer.CURRENT_ISOLATE}.$name';
+ }
+ }
+
void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) {
ClassElement result = null;
if (!_interceptorsAreInitialized) {
initializeInterceptorElements();
_interceptorsAreInitialized = true;
- // The null interceptor and the function interceptor are
- // currently always instantiated if a new class is instantiated.
- // TODO(ngeoffray): do this elsewhere for the function
- // interceptor?
- if (jsNullClass != null) {
- addInterceptors(jsNullClass);
- enqueuer.registerInstantiatedClass(jsNullClass);
- }
- if (jsFunctionClass != null) {
- addInterceptors(jsFunctionClass);
- enqueuer.registerInstantiatedClass(jsFunctionClass);
- }
- enqueuer.addToWorkList(getInterceptorMethod);
}
if (cls == compiler.stringClass) {
result = jsStringClass;
@@ -827,12 +829,16 @@
result = jsArrayClass;
} else if (cls == compiler.intClass) {
result = jsIntClass;
+ enqueuer.registerInstantiatedClass(jsNumberClass);
} else if (cls == compiler.doubleClass) {
result = jsDoubleClass;
+ enqueuer.registerInstantiatedClass(jsNumberClass);
} else if (cls == compiler.functionClass) {
result = jsFunctionClass;
} else if (cls == compiler.boolClass) {
result = jsBoolClass;
+ } else if (cls == compiler.nullClass) {
+ result = jsNullClass;
}
if (result == null) return;

Powered by Google App Engine
This is Rietveld 408576698