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

Unified Diff: pkg/compiler/lib/src/cps_ir/type_propagation.dart

Issue 1409803003: dart2js cps: More interceptor optimizations and fixes. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 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: pkg/compiler/lib/src/cps_ir/type_propagation.dart
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index 7fd2153184a842c4c8fcec1039c8b22f15ccc75e..3e8f483883404231b25638b08000fbb11f3e9a5d 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -666,6 +666,7 @@ class TransformingVisitor extends DeepRecursiveVisitor {
JavaScriptBackend get backend => compiler.backend;
TypeMaskSystem get typeSystem => lattice.typeSystem;
types.DartTypes get dartTypes => lattice.dartTypes;
+ World get classWorld => typeSystem.classWorld;
Map<Variable, ConstantValue> get values => analyzer.values;
final InternalErrorFunction internalError;
@@ -2195,39 +2196,80 @@ class TransformingVisitor extends DeepRecursiveVisitor {
Primitive visitInterceptor(Interceptor node) {
AbstractValue value = getValue(node.input.definition);
- // If the exact class of the input is known, replace with a constant
- // or the input itself.
- ClassElement singleClass;
- if (lattice.isDefinitelyInt(value)) {
- // Classes like JSUInt31 and JSUInt32 do not exist at runtime, so ensure
- // all the int classes get mapped tor their runtime class.
- singleClass = backend.jsIntClass;
- } else if (lattice.isDefinitelyNum(value)) {
- if (jsNumberClassSuffices(node)) {
- singleClass = backend.jsNumberClass;
- }
- } else if (lattice.isDefinitelyNativeList(value)) {
- // Ensure all the array subclasses get mapped to the array class.
- singleClass = backend.jsArrayClass;
+ TypeMask interceptedInputs =
+ value.type.intersection(typeSystem.interceptorType, classWorld);
+ bool catchNull =
sra1 2015/10/21 00:46:25 'include' might be a better name than 'catch'.
asgerf 2015/10/21 11:52:46 Changed to 'interceptNull'. Hope that's better.
+ node.interceptedClasses.contains(backend.jsNullClass) ||
+ node.interceptedClasses.contains(backend.jsInterceptorClass);
+
+ if (lattice.isDefinitelyInt(value, allowNull: !catchNull)) {
+ node.interceptedClasses.clear();
+ node.interceptedClasses.add(backend.jsIntClass);
sra1 2015/10/21 00:46:25 Maybe: node.interceptedClasses..clear()..add(back
asgerf 2015/10/21 11:52:46 Done.
+ } else if (lattice.isDefinitelyNum(value, allowNull: !catchNull) &&
+ jsNumberClassSuffices(node)) {
+ node.interceptedClasses.clear();
+ node.interceptedClasses.add(backend.jsNumberClass);
} else {
- singleClass = typeSystem.singleClass(value.type);
- }
- if (singleClass != null &&
- singleClass.isSubclassOf(backend.jsInterceptorClass)) {
- node.constantValue = new InterceptorConstantValue(singleClass.rawType);
+ // Filter out intercepted classes that do not match the input type.
+ node.interceptedClasses.retainWhere((ClassElement clazz) {
+ return !typeSystem.areDisjoint(
+ value.type,
+ typeSystem.getInterceptorSubtypes(clazz));
+ });
+
+ // The interceptor root class will usually not be filtered out because all
+ // intercepted values are subtypes of it. But it can be "shadowed" by a
+ // more specific interceptor classes if all possible intercepted values
+ // will hit one of the more specific classes.
+ // We only do this optimization if the resulting interceptor call is
+ // sufficiently specialized to be worth it (#classes <= 2).
+ // TODO(asgerf): Reconsider when TypeTest interceptors don't intercept
+ // ALL interceptor classes.
+ if (node.interceptedClasses.length > 1 &&
+ node.interceptedClasses.length < 4 &&
+ node.interceptedClasses.contains(backend.jsInterceptorClass)) {
+ TypeMask specificInterceptors = new TypeMask.unionOf(
+ node.interceptedClasses
+ .where((cl) => cl != backend.jsInterceptorClass)
+ .map(typeSystem.getInterceptorSubtypes),
+ classWorld);
+ if (specificInterceptors.containsMask(interceptedInputs, classWorld)) {
+ // All possible inputs are caught an Interceptor subclass (or are
+ // self-interceptors), so there is no need to have the check for
+ // the Interceptor root class (which is expensive).
+ node.interceptedClasses.remove(backend.jsInterceptorClass);
+ }
+ }
+
+ // Remove the interceptor call if it can only return its input.
+ if (node.interceptedClasses.isEmpty) {
+ node.input.definition.substituteFor(node);
+ return null;
+ }
}
- // Filter out intercepted classes that do not match the input type.
- node.interceptedClasses.retainWhere((ClassElement clazz) {
- if (clazz == typeSystem.jsNullClass) {
- return value.isNullable;
+
+ node.flags = Interceptor.ALL_FLAGS;
+
+ // If there is only one caught interceptor class, determine more precisely
+ // how this might resolve at runtime. Later optimizations depend on this,
+ // but do not have refined type information available.
+ if (node.interceptedClasses.length == 1) {
+ if (value.isDefinitelyNotNull) {
+ node.clearFlag(Interceptor.NULL);
+ } else if (catchNull) {
+ node.clearFlag(Interceptor.NULL_BYPASS);
} else {
- TypeMask classMask = typeSystem.nonNullSubclass(clazz);
- return !typeSystem.areDisjoint(value.type, classMask);
+ node.clearFlag(Interceptor.NULL_INTERCEPT);
+ }
+ if (typeSystem.isDefinitelyIntercepted(value.type, allowNull: true)) {
+ node.clearFlag(Interceptor.SELF_INTERCEPT);
+ }
+ TypeMask interceptedType =
+ typeSystem.getInterceptorSubtypes(node.interceptedClasses.single);
+ if (interceptedType.containsMask(interceptedInputs.nonNullable(),
+ classWorld)) {
+ node.clearFlag(Interceptor.NON_NULL_BYPASS);
}
- });
- // Remove the interceptor call if it can only return its input.
- if (node.interceptedClasses.isEmpty) {
- node.input.definition.substituteFor(node);
}
return null;
}
@@ -2899,7 +2941,6 @@ class TypePropagationVisitor implements Visitor {
void visitGetLazyStatic(GetLazyStatic node) {
setResult(node, nonConstant(typeSystem.getFieldType(node.element)));
}
-
void visitInterceptor(Interceptor node) {
push(node.input.definition);
AbstractValue value = getValue(node.input.definition);

Powered by Google App Engine
This is Rietveld 408576698