Index: pkg/compiler/lib/src/ssa/optimize.dart |
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart |
index 1186d9cf35b22faae3af62a67888beba6ffde3fa..f08b3fdcce87d7bb7ee833859e63cc0c6f39dce7 100644 |
--- a/pkg/compiler/lib/src/ssa/optimize.dart |
+++ b/pkg/compiler/lib/src/ssa/optimize.dart |
@@ -3,6 +3,7 @@ |
// BSD-style license that can be found in the LICENSE file. |
import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
+import '../common/names.dart' show Selectors; |
import '../common/tasks.dart' show CompilerTask; |
import '../compiler.dart' show Compiler; |
import '../constants/constant_system.dart'; |
@@ -1013,22 +1014,51 @@ class SsaInstructionSimplifier extends HBaseVisitor |
HInstruction visitStringify(HStringify node) { |
HInstruction input = node.inputs[0]; |
if (input.isString(compiler)) return input; |
- if (input.isConstant()) { |
+ |
+ HInstruction tryConstant() { |
+ if (!input.isConstant()) return null; |
HConstant constant = input; |
- if (!constant.constant.isPrimitive) return node; |
+ if (!constant.constant.isPrimitive) return null; |
if (constant.constant.isInt) { |
// Only constant-fold int.toString() when Dart and JS results the same. |
// TODO(18103): We should be able to remove this work-around when issue |
// 18103 is resolved by providing the correct string. |
IntConstantValue intConstant = constant.constant; |
// Very conservative range. |
- if (!intConstant.isUInt32()) return node; |
+ if (!intConstant.isUInt32()) return null; |
} |
PrimitiveConstantValue primitive = constant.constant; |
return graph.addConstant( |
constantSystem.createString(primitive.toDartString()), compiler); |
} |
- return node; |
+ |
+ HInstruction tryToString() { |
Harry Terkelsen
2016/09/23 17:49:25
Will this only be called in the kernel->ssa case?
sra1
2016/09/23 18:15:39
There are a few in the old builder case.
There are
|
+ // If the `toString` method is guaranteed to return a string we can call |
+ // it directly. Keep the stringifier for primitives (since they have fast |
+ // path code in the stringifier) and for classes requiring interceptors |
+ // (since SsaInstructionSimplifier runs after SsaSimplifyInterceptors). |
+ if (input.canBePrimitive(compiler)) return null; |
+ if (input.canBeNull()) return null; |
+ Selector selector = Selectors.toString_; |
+ TypeMask toStringType = TypeMaskFactory.inferredTypeForSelector( |
+ selector, input.instructionType, compiler); |
+ ClassWorld classWorld = compiler.closedWorld; |
+ if (!toStringType.containsOnlyString(classWorld)) return null; |
+ // All intercepted classes extend `Interceptor`, so if the receiver can't |
+ // be a class extending `Interceptor` then it can be called directly. |
+ if (new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, classWorld) |
+ .isDisjoint(input.instructionType, classWorld)) { |
+ HInstruction result = new HInvokeDynamicMethod( |
+ selector, |
+ input.instructionType, // receiver mask. |
+ <HInstruction>[input, input], // [interceptor, receiver]. |
+ toStringType)..sourceInformation = node.sourceInformation; |
+ return result; |
+ } |
+ return null; |
+ } |
+ |
+ return tryConstant() ?? tryToString() ?? node; |
} |
HInstruction visitOneShotInterceptor(HOneShotInterceptor node) { |