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,23 @@ |
* 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; |
ahe
2012/11/27 14:29:45
What is the key?
ngeoffray
2012/11/27 15:50:54
It's in the comment above: the name of the special
|
+ |
+ /** |
+ * Set of classes whose instances are intercepted. |
+ */ |
+ final Set<ClassElement> interceptedClasses; |
+ |
List<CompilerTask> get tasks { |
return <CompilerTask>[builder, optimizer, generator, emitter]; |
} |
@@ -695,6 +702,9 @@ |
usedInterceptors = new Set<Selector>(), |
interceptedElements = new Map<SourceString, Set<Element>>(), |
rti = new RuntimeTypeInformation(compiler), |
+ specializedGetInterceptors = |
+ new Map<String, Collection<ClassElement>>(), |
+ interceptedClasses = new Set<ClassElement>(), |
super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) { |
emitter = disableEval |
? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap) |
@@ -714,14 +724,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.contains(element); |
} |
void addInterceptedSelector(Selector selector) { |
@@ -746,6 +749,12 @@ |
return result; |
} |
+ List<ClassElement> getListOfInterceptedClasses() { |
+ return <ClassElement>[jsStringClass, jsArrayClass, jsIntClass, |
ahe
2012/11/27 14:29:45
I suggest you create this list in initializeInterc
ngeoffray
2012/11/27 15:50:54
Done.
|
+ jsDoubleClass, jsNumberClass, jsNullClass, |
+ jsFunctionClass, jsBoolClass]; |
+ } |
+ |
void initializeInterceptorElements() { |
objectInterceptorClass = |
compiler.findInterceptor(const SourceString('ObjectInterceptor')); |
@@ -774,22 +783,7 @@ |
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')); |
+ interceptedClasses.addAll(getListOfInterceptedClasses()); |
} |
void addInterceptors(ClassElement cls) { |
@@ -802,24 +796,34 @@ |
includeSuperMembers: true); |
} |
+ String registerSpecializedGetInterceptor( |
+ Set<ClassElement> interceptedClasses) { |
+ compiler.enqueuer.codegen.registerInstantiatedClass(objectInterceptorClass); |
+ if (interceptedClasses.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, () { |
ahe
2012/11/27 14:29:45
I don't understand why you do this. Why shouldn't
ngeoffray
2012/11/27 15:50:54
Because I did not want to call getListOfIntercepte
|
+ // 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 getListOfInterceptedClasses(); |
+ }); |
+ return namer.isolateAccess(getInterceptorMethod); |
+ } else { |
+ String name = namer.getSpecializedName(getInterceptorMethod, |
+ interceptedClasses); |
+ specializedGetInterceptors[name] = interceptedClasses; |
+ 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 +831,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; |