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 c5286677eddfc8d146f1d6588de4c43166f1274f..0703f1c44f3927a5d3d6835f6ab71060990b94de 100644 |
--- a/pkg/compiler/lib/src/ssa/optimize.dart |
+++ b/pkg/compiler/lib/src/ssa/optimize.dart |
@@ -8,7 +8,7 @@ import '../common/tasks.dart' show CompilerTask; |
import '../compiler.dart' show Compiler; |
import '../constants/constant_system.dart'; |
import '../constants/values.dart'; |
-import '../core_types.dart' show CoreClasses; |
+import '../core_types.dart' show CommonElements, CoreClasses; |
import '../dart_types.dart'; |
import '../elements/elements.dart'; |
import '../js/js.dart' as js; |
@@ -139,10 +139,10 @@ bool isFixedLength(mask, Compiler compiler) { |
return true; |
} |
// TODO(sra): Recognize any combination of fixed length indexables. |
- if (mask.containsOnly(backend.helpers.jsFixedArrayClass) || |
- mask.containsOnly(backend.helpers.jsUnmodifiableArrayClass) || |
+ if (mask.containsOnly(closedWorld.backendClasses.fixedListImplementation) || |
+ mask.containsOnly(closedWorld.backendClasses.constListImplementation) || |
mask.containsOnlyString(closedWorld) || |
- backend.isTypedArray(mask)) { |
+ closedWorld.commonMasks.isTypedArray(mask)) { |
return true; |
} |
return false; |
@@ -170,12 +170,15 @@ class SsaInstructionSimplifier extends HBaseVisitor |
SsaInstructionSimplifier( |
this.constantSystem, this.backend, this.optimizer, this.registry); |
- CoreClasses get coreClasses => compiler.coreClasses; |
- |
ClosedWorld get closedWorld => compiler.closedWorld; |
+ CommonElements get commonElements => closedWorld.commonElements; |
+ |
BackendHelpers get helpers => backend.helpers; |
+ GlobalTypeInferenceResults get globalInferenceResults => |
+ compiler.globalInference.results; |
+ |
void visitGraph(HGraph visitee) { |
graph = visitee; |
visitDominatorTree(visitee); |
@@ -447,9 +450,9 @@ class SsaInstructionSimplifier extends HBaseVisitor |
if (folded != node) return folded; |
} |
- TypeMask receiverType = node.getDartReceiver(compiler).instructionType; |
+ TypeMask receiverType = node.getDartReceiver(closedWorld).instructionType; |
Element element = |
- compiler.closedWorld.locateSingleElement(node.selector, receiverType); |
+ closedWorld.locateSingleElement(node.selector, receiverType); |
// TODO(ngeoffray): Also fold if it's a getter or variable. |
if (element != null && |
element.isFunction |
@@ -482,9 +485,10 @@ class SsaInstructionSimplifier extends HBaseVisitor |
element.isField && |
element.name == node.selector.name) { |
FieldElement field = element; |
- if (!backend.isNative(field) && !node.isCallOnInterceptor(compiler)) { |
- HInstruction receiver = node.getDartReceiver(compiler); |
- TypeMask type = TypeMaskFactory.inferredTypeForElement(field, compiler); |
+ if (!backend.isNative(field) && !node.isCallOnInterceptor(closedWorld)) { |
+ HInstruction receiver = node.getDartReceiver(closedWorld); |
+ TypeMask type = TypeMaskFactory.inferredTypeForElement( |
+ field, globalInferenceResults); |
HInstruction load = new HFieldGet(field, receiver, type); |
node.block.addBefore(node, load); |
Selector callSelector = new Selector.callClosureFrom(node.selector); |
@@ -554,7 +558,7 @@ class SsaInstructionSimplifier extends HBaseVisitor |
native.NativeBehavior nativeBehavior = |
backend.getNativeMethodBehavior(method); |
TypeMask returnType = |
- TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); |
+ TypeMaskFactory.fromNativeBehavior(nativeBehavior, closedWorld); |
HInvokeDynamicMethod result = |
new HInvokeDynamicMethod(node.selector, node.mask, inputs, returnType); |
result.element = method; |
@@ -732,7 +736,7 @@ class SsaInstructionSimplifier extends HBaseVisitor |
return node; |
} else if (type.isTypedef) { |
return node; |
- } else if (element == coreClasses.functionClass) { |
+ } else if (element == commonElements.functionClass) { |
return node; |
} |
@@ -742,11 +746,11 @@ class SsaInstructionSimplifier extends HBaseVisitor |
HInstruction expression = node.expression; |
if (expression.isInteger(closedWorld)) { |
- if (element == coreClasses.intClass || |
- element == coreClasses.numClass || |
- Elements.isNumberOrStringSupertype(element, compiler)) { |
+ if (element == commonElements.intClass || |
+ element == commonElements.numClass || |
+ Elements.isNumberOrStringSupertype(element, commonElements)) { |
return graph.addConstantBool(true, compiler); |
- } else if (element == coreClasses.doubleClass) { |
+ } else if (element == commonElements.doubleClass) { |
// We let the JS semantics decide for that check. Currently |
// the code we emit will always return true. |
return node; |
@@ -754,11 +758,11 @@ class SsaInstructionSimplifier extends HBaseVisitor |
return graph.addConstantBool(false, compiler); |
} |
} else if (expression.isDouble(closedWorld)) { |
- if (element == coreClasses.doubleClass || |
- element == coreClasses.numClass || |
- Elements.isNumberOrStringSupertype(element, compiler)) { |
+ if (element == commonElements.doubleClass || |
+ element == commonElements.numClass || |
+ Elements.isNumberOrStringSupertype(element, commonElements)) { |
return graph.addConstantBool(true, compiler); |
- } else if (element == coreClasses.intClass) { |
+ } else if (element == commonElements.intClass) { |
// We let the JS semantics decide for that check. Currently |
// the code we emit will return true for a double that can be |
// represented as a 31-bit integer and for -0.0. |
@@ -767,14 +771,14 @@ class SsaInstructionSimplifier extends HBaseVisitor |
return graph.addConstantBool(false, compiler); |
} |
} else if (expression.isNumber(closedWorld)) { |
- if (element == coreClasses.numClass) { |
+ if (element == commonElements.numClass) { |
return graph.addConstantBool(true, compiler); |
} else { |
// We cannot just return false, because the expression may be of |
// type int or double. |
} |
} else if (expression.canBePrimitiveNumber(closedWorld) && |
- element == coreClasses.intClass) { |
+ element == commonElements.intClass) { |
// We let the JS semantics decide for that check. |
return node; |
// We need the [:hasTypeArguments:] check because we don't have |
@@ -784,7 +788,7 @@ class SsaInstructionSimplifier extends HBaseVisitor |
} else if (!RuntimeTypes.hasTypeArguments(type)) { |
TypeMask expressionMask = expression.instructionType; |
assert(TypeMask.assertIsNormalized(expressionMask, closedWorld)); |
- TypeMask typeMask = (element == coreClasses.nullClass) |
+ TypeMask typeMask = (element == commonElements.nullClass) |
? new TypeMask.subtype(element, closedWorld) |
: new TypeMask.nonNullSubtype(element, closedWorld); |
if (expressionMask.union(typeMask, closedWorld) == typeMask) { |
@@ -845,7 +849,7 @@ class SsaInstructionSimplifier extends HBaseVisitor |
FieldElement findConcreteFieldForDynamicAccess( |
HInstruction receiver, Selector selector) { |
TypeMask receiverType = receiver.instructionType; |
- return compiler.closedWorld.locateSingleField(selector, receiverType); |
+ return closedWorld.locateSingleField(selector, receiverType); |
} |
HInstruction visitFieldGet(HFieldGet node) { |
@@ -916,7 +920,7 @@ class SsaInstructionSimplifier extends HBaseVisitor |
HInstruction folded = handleInterceptedCall(node); |
if (folded != node) return folded; |
} |
- HInstruction receiver = node.getDartReceiver(compiler); |
+ HInstruction receiver = node.getDartReceiver(closedWorld); |
FieldElement field = |
findConcreteFieldForDynamicAccess(receiver, node.selector); |
if (field != null) return directFieldGet(receiver, field); |
@@ -943,9 +947,10 @@ class SsaInstructionSimplifier extends HBaseVisitor |
TypeMask type; |
if (backend.isNative(field.enclosingClass)) { |
type = TypeMaskFactory.fromNativeBehavior( |
- backend.getNativeFieldLoadBehavior(field), compiler); |
+ backend.getNativeFieldLoadBehavior(field), closedWorld); |
} else { |
- type = TypeMaskFactory.inferredTypeForElement(field, compiler); |
+ type = |
+ TypeMaskFactory.inferredTypeForElement(field, globalInferenceResults); |
} |
return new HFieldGet(field, receiver, type, isAssignable: isAssignable); |
@@ -957,7 +962,7 @@ class SsaInstructionSimplifier extends HBaseVisitor |
if (folded != node) return folded; |
} |
- HInstruction receiver = node.getDartReceiver(compiler); |
+ HInstruction receiver = node.getDartReceiver(closedWorld); |
FieldElement field = |
findConcreteFieldForDynamicAccess(receiver, node.selector); |
if (field == null || !field.isAssignable) return node; |
@@ -1094,7 +1099,7 @@ class SsaInstructionSimplifier extends HBaseVisitor |
if (input.canBeNull()) return null; |
Selector selector = Selectors.toString_; |
TypeMask toStringType = TypeMaskFactory.inferredTypeForSelector( |
- selector, input.instructionType, compiler); |
+ selector, input.instructionType, globalInferenceResults); |
if (!toStringType.containsOnlyString(closedWorld)) return null; |
// All intercepted classes extend `Interceptor`, so if the receiver can't |
// be a class extending `Interceptor` then it can be called directly. |
@@ -1437,10 +1442,10 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { |
/// effects after [instruction], throws [NoSuchMethodError] on the |
/// same receiver of [instruction]. |
bool hasFollowingThrowingNSM(HInstruction instruction) { |
- HInstruction receiver = instruction.getDartReceiver(compiler); |
+ HInstruction receiver = instruction.getDartReceiver(closedWorld); |
HInstruction current = instruction.next; |
do { |
- if ((current.getDartReceiver(compiler) == receiver) && |
+ if ((current.getDartReceiver(closedWorld) == receiver) && |
current.canThrow()) { |
return true; |
} |
@@ -1484,9 +1489,9 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { |
if (use is HFieldSet) { |
// The use must be the receiver. Even if the use is also the argument, |
// i.e. a.x = a, the store is still dead if all other uses are dead. |
- if (use.getDartReceiver(compiler) == instruction) return true; |
+ if (use.getDartReceiver(closedWorld) == instruction) return true; |
} else if (use is HFieldGet) { |
- assert(use.getDartReceiver(compiler) == instruction); |
+ assert(use.getDartReceiver(closedWorld) == instruction); |
if (isDeadCode(use)) return true; |
} |
return false; |
@@ -1500,7 +1505,7 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { |
bool isTrivialDeadStore(HInstruction instruction) { |
return instruction is HFieldSet && |
- isTrivialDeadStoreReceiver(instruction.getDartReceiver(compiler)); |
+ isTrivialDeadStoreReceiver(instruction.getDartReceiver(closedWorld)); |
} |
bool isDeadCode(HInstruction instruction) { |
@@ -2229,6 +2234,8 @@ class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase { |
SsaLoadElimination(this.compiler); |
+ ClosedWorld get closedWorld => compiler.closedWorld; |
+ |
void visitGraph(HGraph graph) { |
memories = new List<MemorySet>(graph.blocks.length); |
List<HBasicBlock> blocks = graph.blocks; |
@@ -2249,7 +2256,7 @@ class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase { |
void visitBasicBlock(HBasicBlock block) { |
if (block.predecessors.length == 0) { |
// Entry block. |
- memorySet = new MemorySet(compiler); |
+ memorySet = new MemorySet(closedWorld); |
} else if (block.predecessors.length == 1 && |
block.predecessors[0].successors.length == 1) { |
// No need to clone, there is no other successor for |
@@ -2283,7 +2290,7 @@ class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase { |
void visitFieldGet(HFieldGet instruction) { |
if (instruction.isNullCheck) return; |
MemberElement element = instruction.element; |
- HInstruction receiver = instruction.getDartReceiver(compiler).nonCheck(); |
+ HInstruction receiver = instruction.getDartReceiver(closedWorld).nonCheck(); |
HInstruction existing = memorySet.lookupFieldValue(element, receiver); |
if (existing != null) { |
instruction.block.rewriteWithBetterUser(instruction, existing); |
@@ -2294,7 +2301,7 @@ class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase { |
} |
void visitFieldSet(HFieldSet instruction) { |
- HInstruction receiver = instruction.getDartReceiver(compiler).nonCheck(); |
+ HInstruction receiver = instruction.getDartReceiver(closedWorld).nonCheck(); |
memorySet.registerFieldValueUpdate( |
instruction.element, receiver, instruction.inputs.last); |
} |
@@ -2434,7 +2441,7 @@ class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase { |
* refinements to help further optimizations. |
*/ |
class MemorySet { |
- final Compiler compiler; |
+ final ClosedWorld closedWorld; |
/** |
* Maps a field to a map of receiver to value. |
@@ -2453,9 +2460,7 @@ class MemorySet { |
*/ |
final Setlet<HInstruction> nonEscapingReceivers = new Setlet<HInstruction>(); |
- MemorySet(this.compiler); |
- |
- JavaScriptBackend get backend => compiler.backend; |
+ MemorySet(this.closedWorld); |
/** |
* Returns whether [first] and [second] always alias to the same object. |
@@ -2475,11 +2480,11 @@ class MemorySet { |
// Typed arrays of different types might have a shared buffer. |
if (couldBeTypedArray(first) && couldBeTypedArray(second)) return true; |
return !first.instructionType |
- .isDisjoint(second.instructionType, compiler.closedWorld); |
+ .isDisjoint(second.instructionType, closedWorld); |
} |
bool isFinal(Element element) { |
- return compiler.closedWorld.fieldNeverChanges(element); |
+ return closedWorld.fieldNeverChanges(element); |
} |
bool isConcrete(HInstruction instruction) { |
@@ -2489,8 +2494,7 @@ class MemorySet { |
} |
bool couldBeTypedArray(HInstruction receiver) { |
- JavaScriptBackend backend = compiler.backend; |
- return backend.couldBeTypedArray(receiver.instructionType); |
+ return closedWorld.commonMasks.couldBeTypedArray(receiver.instructionType); |
} |
/** |
@@ -2513,7 +2517,7 @@ class MemorySet { |
void registerFieldValueUpdate( |
MemberElement element, HInstruction receiver, HInstruction value) { |
assert(receiver == null || receiver == receiver.nonCheck()); |
- if (backend.isNative(element)) { |
+ if (closedWorld.backendClasses.isNative(element)) { |
return; // TODO(14955): Remove this restriction? |
} |
// [value] is being set in some place in memory, we remove it from |
@@ -2533,7 +2537,7 @@ class MemorySet { |
void registerFieldValue( |
MemberElement element, HInstruction receiver, HInstruction value) { |
assert(receiver == null || receiver == receiver.nonCheck()); |
- if (backend.isNative(element)) { |
+ if (closedWorld.backendClasses.isNative(element)) { |
return; // TODO(14955): Remove this restriction? |
} |
Map<HInstruction, HInstruction> map = |
@@ -2643,8 +2647,8 @@ class MemorySet { |
HBasicBlock block, int predecessorIndex) { |
if (first == null || second == null) return null; |
if (first == second) return first; |
- TypeMask phiType = second.instructionType |
- .union(first.instructionType, compiler.closedWorld); |
+ TypeMask phiType = |
+ second.instructionType.union(first.instructionType, closedWorld); |
if (first is HPhi && first.block == block) { |
HPhi phi = first; |
phi.addInput(second); |
@@ -2668,7 +2672,7 @@ class MemorySet { |
*/ |
MemorySet intersectionFor( |
MemorySet other, HBasicBlock block, int predecessorIndex) { |
- MemorySet result = new MemorySet(compiler); |
+ MemorySet result = new MemorySet(closedWorld); |
if (other == null) { |
// This is the first visit to a loop header ([other] is `null` because we |
// have not visited the back edge). Copy the nonEscapingReceivers that are |
@@ -2733,7 +2737,7 @@ class MemorySet { |
* Returns a copy of [this]. |
*/ |
MemorySet clone() { |
- MemorySet result = new MemorySet(compiler); |
+ MemorySet result = new MemorySet(closedWorld); |
fieldValues.forEach((element, values) { |
result.fieldValues[element] = |