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

Unified Diff: pkg/compiler/lib/src/ssa/interceptor_simplifier.dart

Issue 1031633003: Almost-constant interceptors (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 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
« no previous file with comments | « pkg/compiler/lib/src/ssa/codegen.dart ('k') | pkg/compiler/lib/src/ssa/nodes.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index d8213e2ca289cebe0d47db8d2d71574239ae4c80..a22b94d05834802705cdd553967bc85b7c4284fc 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -110,30 +110,50 @@ class SsaSimplifyInterceptors extends HBaseVisitor
return graph.thisInstruction;
}
- ClassElement constantInterceptor;
+ ClassElement constantInterceptor = tryComputeConstantInterceptorFromType(
+ input.instructionType, interceptedClasses);
+
+ if (constantInterceptor == null) return null;
+
+ // If we just happen to be in an instance method of the constant
+ // interceptor, `this` is a shorter alias.
+ if (constantInterceptor == work.element.enclosingClass &&
+ graph.thisInstruction != null) {
+ return graph.thisInstruction;
+ }
+
+ ConstantValue constant =
+ new InterceptorConstantValue(constantInterceptor.thisType);
+ return graph.addConstant(constant, compiler);
+ }
+
+ ClassElement tryComputeConstantInterceptorFromType(
+ TypeMask type,
+ Set<ClassElement> interceptedClasses) {
+
ClassWorld classWorld = compiler.world;
JavaScriptBackend backend = compiler.backend;
- if (input.canBeNull()) {
- if (input.isNull()) {
- constantInterceptor = backend.jsNullClass;
+ if (type.isNullable) {
+ if (type.isEmpty) {
+ return backend.jsNullClass;
}
- } else if (input.isInteger(compiler)) {
- constantInterceptor = backend.jsIntClass;
- } else if (input.isDouble(compiler)) {
- constantInterceptor = backend.jsDoubleClass;
- } else if (input.isBoolean(compiler)) {
- constantInterceptor = backend.jsBoolClass;
- } else if (input.isString(compiler)) {
- constantInterceptor = backend.jsStringClass;
- } else if (input.isArray(compiler)) {
- constantInterceptor = backend.jsArrayClass;
- } else if (input.isNumber(compiler) &&
+ } else if (type.containsOnlyInt(classWorld)) {
+ return backend.jsIntClass;
+ } else if (type.containsOnlyDouble(classWorld)) {
+ return backend.jsDoubleClass;
+ } else if (type.containsOnlyBool(classWorld)) {
+ return backend.jsBoolClass;
+ } else if (type.containsOnlyString(classWorld)) {
+ return backend.jsStringClass;
+ } else if (type.satisfies(backend.jsArrayClass, classWorld)) {
+ return backend.jsArrayClass;
+ } else if (type.containsOnlyNum(classWorld) &&
!interceptedClasses.contains(backend.jsIntClass) &&
!interceptedClasses.contains(backend.jsDoubleClass)) {
// If the method being intercepted is not defined in [int] or [double] we
// can safely use the number interceptor. This is because none of the
// [int] or [double] methods are called from a method defined on [num].
- constantInterceptor = backend.jsNumberClass;
+ return backend.jsNumberClass;
} else {
// Try to find constant interceptor for a native class. If the receiver
// is constrained to a leaf native class, we can use the class's
@@ -146,24 +166,13 @@ class SsaSimplifyInterceptors extends HBaseVisitor
// for a subclass or call methods defined on a subclass. Provided the
// code is completely insensitive to the specific instance subclasses, we
// can use the non-leaf class directly.
- ClassElement element = input.instructionType.singleClass(classWorld);
+ ClassElement element = type.singleClass(classWorld);
if (element != null && element.isNative) {
- constantInterceptor = element;
+ return element;
}
}
- if (constantInterceptor == null) return null;
-
- // If we just happen to be in an instance method of the constant
- // interceptor, `this` is a shorter alias.
- if (constantInterceptor == work.element.enclosingClass &&
- graph.thisInstruction != null) {
- return graph.thisInstruction;
- }
-
- ConstantValue constant =
- new InterceptorConstantValue(constantInterceptor.thisType);
- return graph.addConstant(constant, compiler);
+ return null;
}
HInstruction findDominator(Iterable<HInstruction> instructions) {
@@ -276,6 +285,32 @@ class SsaSimplifyInterceptors extends HBaseVisitor
return false;
}
+ // Do we have an 'almost constant' interceptor? The receiver could be
+ // `null` but not any other JavaScript falsy value, `null` values cause
+ // `NoSuchMethodError`s, and if the receiver was not null we would have a
+ // constant interceptor `C`. Then we can use `(receiver && C)` for the
+ // interceptor.
+ if (receiver.canBeNull() && !node.isConditionalConstantInterceptor) {
+ if (!interceptedClasses.contains(backend.jsNullClass)) {
+ // Can use `(receiver && C)` only if receiver is either null or truthy.
+ if (!(receiver.canBePrimitiveNumber(compiler) ||
+ receiver.canBePrimitiveBoolean(compiler) ||
+ receiver.canBePrimitiveString(compiler))) {
+ ClassElement interceptorClass = tryComputeConstantInterceptorFromType(
+ receiver.instructionType.nonNullable(), interceptedClasses);
+ if (interceptorClass != null) {
+ HInstruction constantInstruction =
+ graph.addConstant(
+ new InterceptorConstantValue(interceptorClass.thisType),
+ compiler);
+ node.conditionalConstantInterceptor = constantInstruction;
+ constantInstruction.usedBy.add(node);
+ return false;
+ }
+ }
+ }
+ }
+
// Try creating a one-shot interceptor or optimized is-check
if (compiler.hasIncrementalSupport) return false;
if (node.usedBy.length != 1) return false;
« no previous file with comments | « pkg/compiler/lib/src/ssa/codegen.dart ('k') | pkg/compiler/lib/src/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698