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

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

Issue 10855170: Track types for arguments passed to calls to static functions (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 4 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: lib/compiler/implementation/js_backend/backend.dart
diff --git a/lib/compiler/implementation/js_backend/backend.dart b/lib/compiler/implementation/js_backend/backend.dart
index da7e00d1d2889c8f298c50acb1d6f7d6ce65d363..f4397d6456c1044e1001a50d38a2e793367a8a78 100644
--- a/lib/compiler/implementation/js_backend/backend.dart
+++ b/lib/compiler/implementation/js_backend/backend.dart
@@ -3,14 +3,59 @@
// BSD-style license that can be found in the LICENSE file.
class InvocationInfo {
- int parameterCount;
+ int parameterCount = -1;
List<HType> providedTypes;
List<Element> compiledFunctions;
- InvocationInfo(List<HType> types)
- : parameterCount = types != null ? types.length : -1,
- providedTypes = types,
- compiledFunctions = new List<Element>();
+ InvocationInfo(HInvoke node) : compiledFunctions = new List<Element>() {
floitsch 2012/08/15 09:11:59 nit: move the init into a separate line.
Søren Gjesse 2012/08/15 12:17:10 Done.
+ // If no node is provided this is an invocation info to indicate no type
+ // information.
+ if (node == null) return;
floitsch 2012/08/15 09:11:59 named constructor: InvocationInfo.withoutType() ?
Søren Gjesse 2012/08/15 12:17:10 Good point, done.
+ // 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;
+ }
+ }
+ if (!allUnknown) {
+ providedTypes = new List<HType>(node.inputs.length - 1);
+ for (int i = 0; i < providedTypes.length; i++) {
+ providedTypes[i] = node.inputs[i + 1].propagatedType;
+ }
+ parameterCount = providedTypes.length;
+ }
+ }
+
+ void update(HInvoke node, var recompile) {
+ // If we don't know anything useful about the types adding more
+ // information will not help.
+ if (!hasTypeInformation) return;
+
+ // Update the type information with the provided types.
+ bool typesChanged = false;
+ bool allUnknown = true;
+ for (int i = 0; i < providedTypes.length; i++) {
+ HType newType = providedTypes[i].union(node.inputs[i + 1].propagatedType);
+ if (newType != providedTypes[i]) {
+ typesChanged = true;
+ providedTypes[i] = newType;
+ }
+ if (providedTypes[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 && compiledFunctions.length != 0) {
+ if (recompile != null) {
+ compiledFunctions.forEach(recompile);
+ }
+ compiledFunctions.clear();
+ }
+ // If all information is lost no need to keep it around.
+ if (allUnknown) clearTypeInformation();
+ }
addCompiledFunction(FunctionElement function) =>
compiledFunctions.add(function);
@@ -29,6 +74,7 @@ class JavaScriptBackend extends Backend {
final Map<Element, Map<Element, HType>> fieldConstructorSetters;
final Map<Element, Map<Element, HType>> fieldSettersType;
+ final Map<Element, InvocationInfo> staticInvocationInfo;
final Map<SourceString, Map<Selector, InvocationInfo>> invocationInfo;
final List<Element> invalidateAfterCodegen;
@@ -43,6 +89,7 @@ class JavaScriptBackend extends Backend {
fieldConstructorSetters = new Map<Element, Map<Element, HType>>(),
fieldSettersType = new Map<Element, Map<Element, HType>>(),
invocationInfo = new Map<SourceString, Map<Selector, InvocationInfo>>(),
+ staticInvocationInfo = new Map<Element, InvocationInfo>(),
invalidateAfterCodegen = new List<Element>(),
super(compiler) {
builder = new SsaBuilderTask(this);
@@ -197,51 +244,52 @@ class JavaScriptBackend extends Backend {
() => 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) {
+ recompile(Element element) {
floitsch 2012/08/15 09:11:59 void recompile(Element element) {
Søren Gjesse 2012/08/15 12:17:10 Done.
if (compiler.phase == Compiler.PHASE_COMPILING) {
- info.compiledFunctions.forEach(invalidateAfterCodegen.add);
- info.compiledFunctions.clear();
+ invalidateAfterCodegen.add(element);
}
}
floitsch 2012/08/15 09:11:59 new line after function declarations.
Søren Gjesse 2012/08/15 12:17:10 Done.
- // If all information is lost no need to keep it around.
- if (allUnknown) info.clearTypeInformation();
+ info.update(node, recompile);
} 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;
+ invocationInfos[selector] = new InvocationInfo(node);
+ }
+ }
+
+ /**
+ * Register a static invocation and collect the provided types for the
+ * named selector.
+ */
+ void registerStaticInvocation(HInvokeStatic node) {
+ InvocationInfo info = staticInvocationInfo[node.element];
+ if (info != null) {
+ recompile(Element element) {
+ if (compiler.phase == Compiler.PHASE_COMPILING) {
+ invalidateAfterCodegen.add(element);
}
}
- List<HType> types = null;
- if (!allUnknown) {
- types = new List<HType>(node.inputs.length - 1);
- for (int i = 0; i < types.length; i++) {
- types[i] = node.inputs[i + 1].propagatedType;
+ info.update(node, recompile);
+ } else {
+ staticInvocationInfo[node.element] = new InvocationInfo(node);
+ }
+ }
+
+ /**
+ * Register that a static is used for something else than a call target.
+ */
+ void registerNonCallStaticUse(HStatic node) {
floitsch 2012/08/15 09:11:59 where is the same functionality for dynamic calls?
Søren Gjesse 2012/08/15 12:17:10 We don't have it, and its a bug. I have filed http
+ // When a static is used for anything else than a call target we cannot
+ // infer anything about its parameter types.
+ InvocationInfo info = staticInvocationInfo[node.element];
+ if (info == null) {
+ staticInvocationInfo[node.element] = new InvocationInfo(null);
+ } else {
+ info.clearTypeInformation();
+ if (info.compiledFunctions.length != 0) {
+ if (compiler.phase == Compiler.PHASE_COMPILING) {
+ info.compiledFunctions.forEach(invalidateAfterCodegen.add);
+ info.compiledFunctions.clear();
}
}
- InvocationInfo info = new InvocationInfo(types);
- invocationInfos[selector] = info;
}
}
@@ -255,26 +303,38 @@ class JavaScriptBackend extends Backend {
*/
List<HType> optimisticParameterTypesWithRecompilationOnTypeChange(
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 (Elements.isStaticOrTopLevelFunction(element)) {
+ InvocationInfo found = staticInvocationInfo[element];
+ if (found != null && found.hasTypeInformation) {
+ FunctionSignature signature = element.computeSignature(compiler);
+ if (signature.parameterCount == found.parameterCount) {
+ found.addCompiledFunction(element);
+ return found.providedTypes;
+ }
}
- });
+ return null;
+ } else {
+ Map<Selector, InvocationInfo> invocationInfos =
+ invocationInfo[element.name];
+ if (invocationInfos == null) return null;
- if (foundCount == 1 && found.hasTypeInformation) {
- FunctionSignature signature = element.computeSignature(compiler);
- if (signature.parameterCount == found.parameterCount) {
- found.addCompiledFunction(element);
- return found.providedTypes;
+ 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;
}
- return null;
}
}
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen.dart » ('j') | lib/compiler/implementation/ssa/codegen.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698