Chromium Code Reviews| Index: lib/compiler/implementation/compiler.dart |
| diff --git a/lib/compiler/implementation/compiler.dart b/lib/compiler/implementation/compiler.dart |
| index ca6ca2ba8cb60374a28e6029a5089e9d50e33292..50f0f658cfc52f4dece791e7dbe0496f5e42de51 100644 |
| --- a/lib/compiler/implementation/compiler.dart |
| +++ b/lib/compiler/implementation/compiler.dart |
| @@ -51,6 +51,23 @@ class Backend { |
| abstract List<CompilerTask> get tasks(); |
| } |
| +class InvocationInfo { |
|
ahe
2012/08/07 11:23:26
I don't think this class belongs in this file.
Søren Gjesse
2012/08/08 10:36:02
I agree. I will move this and the JavaScriptBacken
ahe
2012/08/08 13:00:27
SGTM
|
| + InvocationInfo(List<HType> types) |
| + : parameterCount = types != null ? types.length : -1, |
| + providedTypes = types, |
| + compiledFunctions = new List<Element>(); |
| + |
| + addCompiledFunction(FunctionElement function) => |
| + compiledFunctions.add(function); |
| + |
| + void clearTypeInformation() => providedTypes = null; |
| + bool get hasTypeInformation() => providedTypes != null; |
| + |
| + int parameterCount; |
|
ahe
2012/08/07 11:23:26
Please follow this sequence of members:
fields,
c
Søren Gjesse
2012/08/08 10:36:02
Done.
|
| + List<HType> providedTypes; |
| + List<Element> compiledFunctions; |
| +} |
| + |
| class JavaScriptBackend extends Backend { |
| SsaBuilderTask builder; |
| SsaOptimizerTask optimizer; |
| @@ -60,6 +77,8 @@ class JavaScriptBackend extends Backend { |
| final Map<Element, Map<Element, HType>> fieldConstructorSetters; |
| final Map<Element, Map<Element, HType>> fieldSettersType; |
| + final Map<SourceString, Map<Selector, InvocationInfo>> invocationInfo; |
| + |
| List<CompilerTask> get tasks() { |
| return <CompilerTask>[builder, optimizer, generator, emitter]; |
| } |
| @@ -69,6 +88,7 @@ class JavaScriptBackend extends Backend { |
| fieldInitializers = new Map<Element, Map<Element, HType>>(), |
| fieldConstructorSetters = new Map<Element, Map<Element, HType>>(), |
| fieldSettersType = new Map<Element, Map<Element, HType>>(), |
| + invocationInfo = new Map<SourceString, Map<Selector, InvocationInfo>>(), |
| super(compiler) { |
| builder = new SsaBuilderTask(this); |
| optimizer = new SsaOptimizerTask(this); |
| @@ -204,6 +224,91 @@ class JavaScriptBackend extends Backend { |
| if (!fields.containsKey(field)) return HType.CONFLICTING; |
| return fields[field]; |
| } |
| + |
| + // Register a dynamic invocation and collects the provided types for the |
|
ahe
2012/08/07 11:23:26
collects -> collect.
ahe
2012/08/07 11:23:26
This should be a documentation comment, that is, u
Søren Gjesse
2012/08/08 10:36:02
Done.
Søren Gjesse
2012/08/08 10:36:02
Done.
|
| + // named selector. |
| + void registerDynamicInvocation(HInvokeDynamicMethod node, Selector selector) { |
|
ahe
2012/08/07 11:23:26
It would be great if you could move this out of co
Søren Gjesse
2012/08/08 10:36:02
Will do.
|
| + Map<Selector, InvocationInfo> invocationInfos = |
| + invocationInfo.putIfAbsent(node.name, |
| + () => new Map<Selector, InvocationInfo>()); |
| + InvocationInfo info = invocationInfos[selector]; |
| + if (info != null) { |
| + // If we don't know anything useful about the types adding more |
| + // information will not help. |
| + if (!info.hasTypeInformation) return; |
| + |
| + // Update the type information with the provided types. |
| + bool typesChanged = false; |
| + List<HType> types = info.providedTypes; |
| + bool allUnknown = true; |
| + for (int i = 0; i < types.length; i++) { |
| + HType newType = types[i].union(node.inputs[i + 1].propagatedType); |
| + if (newType != types[i]) { |
| + typesChanged = true; |
| + types[i] = newType; |
| + } |
| + if (types[i] != HType.UNKNOWN) allUnknown = false; |
| + } |
| + // If the provided types change we need to recompile all functions which |
| + // have been compiled under the now invalidated assumptions. |
| + if (typesChanged && info.compiledFunctions.length != 0) { |
| + if (compiler.phase == Compiler.PHASE_COMPILING) { |
| + info.compiledFunctions.forEach( |
|
ahe
2012/08/07 11:23:26
info.compiledFunctions.forEach(compiler.enqueuer.c
Søren Gjesse
2012/08/08 10:36:02
Done.
|
| + (e) => compiler.enqueuer.codegen.eagerRecompile(e) |
| + ); |
| + info.compiledFunctions.clear(); |
| + } |
| + } |
| + // If all information is lost no need to keep it around. |
| + if (allUnknown) info.clearTypeInformation(); |
| + } else { |
| + // Gather the type information provided. If the types contains no useful |
| + // information there is no need to actually store them. |
| + bool allUnknown = true; |
| + for (int i = 1; i < node.inputs.length; i++) { |
| + if (node.inputs[i].propagatedType != HType.UNKNOWN) { |
| + allUnknown = false; |
| + break; |
| + } |
| + } |
| + List<HType> types; |
| + if (allUnknown) { |
| + types == null; |
|
ahe
2012/08/07 11:23:26
This is a no-op.
Søren Gjesse
2012/08/08 10:36:02
Fixed.
|
| + } else { |
| + types = new List<HType>(node.inputs.length - 1); |
| + for (int i = 0; i < types.length; i++) { |
| + types[i] = node.inputs[i + 1].propagatedType; |
| + } |
| + } |
| + InvocationInfo info = new InvocationInfo(types); |
| + invocationInfos[selector] = info; |
| + } |
| + } |
| + |
| + List<HType> optimisticParameterTypesWithRecompilationOnTypeChange( |
|
ahe
2012/08/07 11:23:26
Please document this method.
Søren Gjesse
2012/08/08 10:36:02
Done.
|
| + FunctionElement element) { |
| + Map<Selector, InvocationInfo> invocationInfos = |
| + invocationInfo[element.name]; |
| + if (invocationInfos == null) return null; |
| + |
| + int foundCount = 0; |
| + InvocationInfo found = null; |
| + invocationInfos.forEach((Selector selector, InvocationInfo info) { |
| + if (selector.applies(element, compiler)) { |
| + found = info; |
| + foundCount++; |
| + } |
| + }); |
| + |
| + if (foundCount == 1 && found.hasTypeInformation) { |
| + FunctionSignature signature = element.computeSignature(compiler); |
| + if (signature.parameterCount == found.parameterCount) { |
| + found.addCompiledFunction(element); |
| + return found.providedTypes; |
| + } |
| + } |
| + return null; |
| + } |
| } |
| class Compiler implements DiagnosticListener { |