Index: sdk/lib/_internal/compiler/implementation/js_backend/backend.dart |
=================================================================== |
--- sdk/lib/_internal/compiler/implementation/js_backend/backend.dart (revision 15379) |
+++ sdk/lib/_internal/compiler/implementation/js_backend/backend.dart (working copy) |
@@ -101,6 +101,13 @@ |
HTypeMap types) { |
HTypeList result; |
int argumentsCount = node.inputs.length - 1; |
+ int startInvokeIndex = HInvoke.ARGUMENTS_OFFSET; |
+ |
+ if (node.isInterceptorCall) { |
+ argumentsCount--; |
+ startInvokeIndex++; |
+ } |
+ |
if (selector.namedArgumentCount > 0) { |
result = |
new HTypeList.withNamedArguments( |
@@ -108,8 +115,9 @@ |
} else { |
result = new HTypeList(argumentsCount); |
} |
+ |
for (int i = 0; i < result.types.length; i++) { |
- result.types[i] = types[node.inputs[i + 1]]; |
+ result.types[i] = types[node.inputs[i + startInvokeIndex]]; |
} |
return result; |
} |
@@ -142,38 +150,6 @@ |
return onlyUnknown ? HTypeList.ALL_UNKNOWN : result; |
} |
- /** |
- * Create the union of this [HTypeList] object with the types used by |
- * the [node]. If the union results in exactly the same types the receiver |
- * is returned. Otherwise a different [HTypeList] object is returned |
- * with the type union information. |
- */ |
- HTypeList unionWithInvoke(HInvoke node, HTypeMap types, Compiler compiler) { |
- // Union an all unknown list with something stays all unknown. |
- if (allUnknown) return this; |
- |
- bool allUnknown = true; |
- if (length != node.inputs.length - 1) { |
- return HTypeList.ALL_UNKNOWN; |
- } |
- |
- bool onlyUnknown = true; |
- HTypeList result = this; |
- for (int i = 0; i < length; i++) { |
- HType newType = this[i].union(types[node.inputs[i + 1]], compiler); |
- if (result == this && newType != this[i]) { |
- // Create a new argument types object with the matching types copied. |
- result = new HTypeList(length); |
- result.types.setRange(0, i, this.types); |
- } |
- if (result != this) { |
- result.types[i] = newType; |
- } |
- if (result[i] != HType.UNKNOWN) onlyUnknown = false; |
- } |
- return onlyUnknown ? HTypeList.ALL_UNKNOWN : result; |
- } |
- |
HTypeList unionWithOptionalParameters( |
Selector selector, |
FunctionSignature signature, |
@@ -473,18 +449,22 @@ |
Compiler get compiler => backend.compiler; |
+ bool updateTypes(HTypeList oldTypes, HTypeList newTypes, var key, var map) { |
+ if (oldTypes.allUnknown) return false; |
+ newTypes = oldTypes.union(newTypes, backend.compiler); |
+ if (identical(newTypes, oldTypes)) return false; |
+ map[key] = newTypes; |
+ return true; |
+ } |
+ |
void registerStaticInvocation(HInvokeStatic node, HTypeMap types) { |
Element element = node.element; |
assert(invariant(node, element.isDeclaration)); |
HTypeList oldTypes = staticTypeMap[element]; |
+ HTypeList newTypes = new HTypeList.fromStaticInvocation(node, types); |
if (oldTypes == null) { |
- staticTypeMap[element] = new HTypeList.fromStaticInvocation(node, types); |
- } else { |
- if (oldTypes.allUnknown) return; |
- HTypeList newTypes = |
- oldTypes.unionWithInvoke(node, types, backend.compiler); |
- if (identical(newTypes, oldTypes)) return; |
staticTypeMap[element] = newTypes; |
+ } else if (updateTypes(oldTypes, newTypes, element, staticTypeMap)) { |
if (optimizedStaticFunctions.contains(element)) { |
backend.scheduleForRecompilation(element); |
} |
@@ -524,10 +504,7 @@ |
selectorTypeMap[selector] = providedTypes; |
} else { |
HTypeList oldTypes = selectorTypeMap[selector]; |
- HTypeList newTypes = |
- oldTypes.unionWithInvoke(node, types, backend.compiler); |
- if (identical(newTypes, oldTypes)) return; |
- selectorTypeMap[selector] = newTypes; |
+ updateTypes(oldTypes, providedTypes, selector, selectorTypeMap); |
} |
// If we're not compiling, we don't have to do anything. |
@@ -658,6 +635,14 @@ |
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; |
@@ -788,6 +773,23 @@ |
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')); |
} |
void addInterceptors(ClassElement cls) { |