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

Unified Diff: lib/compiler/implementation/ssa/optimize.dart

Issue 10827180: Move types out of the HInstructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Cosmetic change (updated comment). 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/ssa/optimize.dart
diff --git a/lib/compiler/implementation/ssa/optimize.dart b/lib/compiler/implementation/ssa/optimize.dart
index 2b4831ad2a2097aa905c57f98ba09560826f80c2..fc21d22e062f59658e8e14925c75f7c30ed55a31 100644
--- a/lib/compiler/implementation/ssa/optimize.dart
+++ b/lib/compiler/implementation/ssa/optimize.dart
@@ -17,26 +17,30 @@ class SsaOptimizerTask extends CompilerTask {
void runPhases(HGraph graph, List<OptimizationPhase> phases) {
for (OptimizationPhase phase in phases) {
- phase.visitGraph(graph);
- compiler.tracer.traceGraph(phase.name, graph);
+ runPhase(graph, phase);
}
}
- void optimize(WorkItem work, HGraph graph) {
+ void runPhase(HGraph graph, OptimizationPhase phase) {
+ phase.visitGraph(graph);
+ compiler.tracer.traceGraph(phase.name, graph);
+ }
+
+ void optimize(JavaScriptWorkItem work, HGraph graph) {
measure(() {
List<OptimizationPhase> phases = <OptimizationPhase>[
// Run trivial constant folding first to optimize
// some patterns useful for type conversion.
new SsaConstantFolder(backend, work),
new SsaTypeConversionInserter(compiler),
- new SsaTypePropagator(compiler),
- new SsaCheckInserter(backend),
+ new SsaTypePropagator(compiler, work),
+ new SsaCheckInserter(backend, work),
new SsaConstantFolder(backend, work),
new SsaRedundantPhiEliminator(),
new SsaDeadPhiEliminator(),
- new SsaGlobalValueNumberer(compiler),
+ new SsaGlobalValueNumberer(compiler, work),
new SsaCodeMotion(),
- new SsaDeadCodeEliminator(),
+ new SsaDeadCodeEliminator(work),
new SsaRegisterRecompilationCandidates(backend, work)];
runPhases(graph, phases);
});
@@ -47,7 +51,7 @@ class SsaOptimizerTask extends CompilerTask {
// Run the phases that will generate type guards.
List<OptimizationPhase> phases = <OptimizationPhase>[
new SsaRecompilationFieldTypePropagator(backend, work),
- new SsaSpeculativeTypePropagator(compiler),
+ new SsaSpeculativeTypePropagator(compiler, work),
new SsaTypeGuardInserter(compiler, work),
new SsaEnvironmentBuilder(compiler),
// Change the propagated types back to what they were before we
@@ -56,11 +60,11 @@ class SsaOptimizerTask extends CompilerTask {
// Note that we do this even if there were no guards inserted. If a
// guard is not beneficial enough we don't emit one, but there might
// still be speculative types on the instructions.
- new SsaTypePropagator(compiler),
+ new SsaTypePropagator(compiler, work),
// Then run the [SsaCheckInserter] because the type propagator also
// propagated types non-speculatively. For example, it might have
// propagated the type array for a call to the List constructor.
- new SsaCheckInserter(backend)];
+ new SsaCheckInserter(backend, work)];
runPhases(graph, phases);
return !work.guards.isEmpty();
});
@@ -79,8 +83,8 @@ class SsaOptimizerTask extends CompilerTask {
// Also run the type propagator, to please the codegen in case
// no other optimization is run.
runPhases(graph,
- <OptimizationPhase>[new SsaCheckInserter(backend),
- new SsaTypePropagator(compiler)]);
+ <OptimizationPhase>[new SsaCheckInserter(backend, work),
+ new SsaTypePropagator(compiler, work)]);
});
}
}
@@ -92,7 +96,7 @@ class SsaOptimizerTask extends CompilerTask {
class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
final String name = "SsaConstantFolder";
final JavaScriptBackend backend;
- final WorkItem work;
+ final JavaScriptWorkItem work;
HGraph graph;
Compiler get compiler() => backend.compiler;
@@ -104,6 +108,7 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
}
visitBasicBlock(HBasicBlock block) {
+ HTypeMap types = work.types;
HInstruction instruction = block.first;
while (instruction !== null) {
HInstruction next = instruction.next;
@@ -120,8 +125,8 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
// If the replacement instruction does not know its type or
// source element yet, use the type and source element of the
// instruction.
- if (!replacement.propagatedType.isUseful()) {
- replacement.propagatedType = instruction.propagatedType;
+ if (!types[replacement].isUseful()) {
+ types[replacement] = types[instruction];
}
if (replacement.sourceElement === null) {
replacement.sourceElement = instruction.sourceElement;
@@ -136,12 +141,13 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
}
HInstruction visitBoolify(HBoolify node) {
+ HTypeMap types = work.types;
List<HInstruction> inputs = node.inputs;
assert(inputs.length == 1);
HInstruction input = inputs[0];
- if (input.isBoolean()) return input;
+ if (input.isBoolean(types)) return input;
// All values !== true are boolified to false.
- Type type = input.propagatedType.computeType(compiler);
+ Type type = types[input].computeType(compiler);
if (type !== null && type.element !== compiler.boolClass) {
return graph.addConstantBool(false);
}
@@ -191,14 +197,16 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
}
}
- if (input.isString()
+ HTypeMap types = work.types;
+
+ if (input.isString(types)
&& node.name == const SourceString('toString')) {
return node.inputs[1];
}
- if (!input.canBePrimitive() && !node.getter && !node.setter) {
+ if (!input.canBePrimitive(types) && !node.getter && !node.setter) {
bool transformToDynamicInvocation = true;
- if (input.canBeNull()) {
+ if (input.canBeNull(types)) {
// Check if the method exists on Null. If yes we must not transform
// the static interceptor call to a dynamic invocation.
// TODO(floitsch): get a list of methods that exist on 'null' and only
@@ -214,7 +222,7 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
}
HInstruction visitInvokeDynamic(HInvokeDynamic node) {
- HType receiverType = node.receiver.propagatedType;
+ HType receiverType = work.types[node.receiver];
if (receiverType.isExact()) {
HBoundedType type = receiverType;
Element element = type.lookupMember(node.name);
@@ -236,7 +244,7 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
HInstruction fromInterceptorToDynamicInvocation(
HInvokeStatic node, SourceString methodName) {
- HBoundedType type = node.inputs[1].propagatedType;
+ HBoundedType type = work.types[node.inputs[1]];
HInvokeDynamicMethod result = new HInvokeDynamicMethod(
node.selector,
methodName,
@@ -288,7 +296,7 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
HInstruction visitIntegerCheck(HIntegerCheck node) {
HInstruction value = node.value;
- if (value.isInteger()) return value;
+ if (value.isInteger(work.types)) return value;
if (value.isConstant()) {
assert((){
HConstant constantInstruction = value;
@@ -301,7 +309,7 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
HInstruction visitIndex(HIndex node) {
- if (!node.receiver.canBePrimitive()) {
+ if (!node.receiver.canBePrimitive(work.types)) {
SourceString methodName = Elements.constructOperatorName(
const SourceString('operator'), const SourceString('[]'));
return fromInterceptorToDynamicInvocation(node, methodName);
@@ -310,7 +318,7 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
}
HInstruction visitIndexAssign(HIndexAssign node) {
- if (!node.receiver.canBePrimitive()) {
+ if (!node.receiver.canBePrimitive(work.types)) {
SourceString methodName = Elements.constructOperatorName(
const SourceString('operator'), const SourceString('[]='));
return fromInterceptorToDynamicInvocation(node, methodName);
@@ -329,7 +337,7 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
if (folded !== null) return graph.addConstant(folded);
}
- if (!left.canBePrimitive()
+ if (!left.canBePrimitive(work.types)
&& node.operation.isUserDefinable()
// The equals operation is being optimized in visitEquals.
&& node.operation !== const EqualsOperation()) {
@@ -368,7 +376,7 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
node.inputs[0] = boolifiedTarget;
boolifiedTarget.usedBy.add(node);
node.usesBoolifiedInterceptor = true;
- node.propagatedType = HType.BOOLEAN;
+ work.types[node] = HType.BOOLEAN;
}
// This node stays the same, but the Boolify node will go away.
}
@@ -378,19 +386,20 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
}
HInstruction handleIdentityCheck(HInvokeBinary node) {
+ HTypeMap types = work.types;
HInstruction left = node.left;
HInstruction right = node.right;
- HType leftType = left.propagatedType;
- HType rightType = right.propagatedType;
+ HType leftType = types[left];
+ HType rightType = types[right];
assert(!leftType.isConflicting() && !rightType.isConflicting());
// We don't optimize on numbers to preserve the runtime semantics.
- if (!(left.isNumber() && right.isNumber()) &&
+ if (!(left.isNumber(types) && right.isNumber(types)) &&
leftType.intersection(rightType).isConflicting()) {
return graph.addConstantBool(false);
}
- if (left.isConstantBoolean() && right.isBoolean()) {
+ if (left.isConstantBoolean() && right.isBoolean(types)) {
HConstant constant = left;
if (constant.constant.isTrue()) {
return right;
@@ -399,7 +408,7 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
}
}
- if (right.isConstantBoolean() && left.isBoolean()) {
+ if (right.isConstantBoolean() && left.isBoolean(types)) {
HConstant constant = right;
if (constant.constant.isTrue()) {
return left;
@@ -430,10 +439,11 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
}
HInstruction visitEquals(HEquals node) {
+ HTypeMap types = work.types;
HInstruction left = node.left;
HInstruction right = node.right;
- if (node.builtin) {
+ if (node.isBuiltin(types)) {
return foldBuiltinEqualsCheck(node);
}
@@ -441,8 +451,9 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
return super.visitEquals(node);
}
- if (left.propagatedType.isExact()) {
- HBoundedType type = left.propagatedType;
+ HType leftType = types[left];
+ if (leftType.isExact()) {
+ HBoundedType type = leftType;
Element element = type.lookupMember(Elements.OPERATOR_EQUALS);
if (element !== null) {
// If the left-hand side is guaranteed to be a non-primitive
@@ -459,7 +470,7 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
}
if (right.isConstantNull()) {
- if (left.propagatedType.isPrimitive()) {
+ if (leftType.isPrimitive()) {
return graph.addConstantBool(false);
}
}
@@ -471,12 +482,13 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
}
HInstruction visitTypeGuard(HTypeGuard node) {
+ HTypeMap types = work.types;
HInstruction value = node.guarded;
// If the intersection of the types is still the incoming type then
// the incoming type was a subtype of the guarded type, and no check
// is required.
- HType combinedType = value.propagatedType.intersection(node.guardedType);
- return (combinedType == value.propagatedType) ? value : node;
+ HType combinedType = types[value].intersection(node.guardedType);
+ return (combinedType == types[value]) ? value : node;
}
HInstruction visitIs(HIs node) {
@@ -486,7 +498,7 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
compiler.unimplemented("visitIs for type variables");
}
- HType expressionType = node.expression.propagatedType;
+ HType expressionType = work.types[node.expression];
if (element === compiler.objectClass
|| element === compiler.dynamicClass) {
return graph.addConstantBool(true);
@@ -548,21 +560,23 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
}
HInstruction visitTypeConversion(HTypeConversion node) {
+ HTypeMap types = work.types;
HInstruction value = node.inputs[0];
- Type type = node.propagatedType.computeType(compiler);
+ Type type = types[node].computeType(compiler);
if (type.element === compiler.dynamicClass
|| type.element === compiler.objectClass) {
return value;
}
- HType combinedType = value.propagatedType.intersection(node.propagatedType);
- return (combinedType == value.propagatedType) ? value : node;
+ HType combinedType = types[value].intersection(types[node]);
+ return (combinedType == types[value]) ? value : node;
}
HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
HInstruction receiver = node.inputs[0];
- if (!receiver.propagatedType.isUseful()) return node;
- if (receiver.propagatedType.canBeNull()) return node;
- Type type = receiver.propagatedType.computeType(compiler);
+ HType receiverType = work.types[receiver];
+ if (!receiverType.isUseful()) return node;
+ if (receiverType.canBeNull()) return node;
+ Type type = receiverType.computeType(compiler);
if (type === null) return node;
Element field = compiler.world.locateSingleField(type, node.name);
if (field === null) return node;
@@ -597,9 +611,10 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
HInstruction receiver = node.inputs[0];
- if (!receiver.propagatedType.isUseful()) return node;
- if (receiver.propagatedType.canBeNull()) return node;
- Type type = receiver.propagatedType.computeType(compiler);
+ HType receiverType = work.types[receiver];
+ if (!receiverType.isUseful()) return node;
+ if (receiverType.canBeNull()) return node;
+ Type type = receiverType.computeType(compiler);
if (type === null) return node;
Element field = compiler.world.locateSingleField(type, node.name);
if (field === null) return node;
@@ -621,10 +636,13 @@ class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
}
class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase {
+ final JavaScriptBackend backend;
Lasse Reichstein Nielsen 2012/08/08 07:44:53 Used?
floitsch 2012/08/08 19:18:37 Done.
+ final JavaScriptWorkItem work;
final String name = "SsaCheckInserter";
Element lengthInterceptor;
- SsaCheckInserter(JavaScriptBackend backend) {
+ SsaCheckInserter(JavaScriptBackend backend, this.work)
+ : this.backend = backend {
SourceString lengthString = const SourceString('length');
lengthInterceptor =
backend.builder.interceptors.getStaticGetInterceptor(lengthString);
@@ -653,7 +671,7 @@ class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase {
const SourceString("length"),
<HInstruction>[interceptor, receiver],
getter: true);
- length.propagatedType = HType.INTEGER;
+ work.types[length] = HType.INTEGER;
node.block.addBefore(node, length);
HBoundsCheck check = new HBoundsCheck(index, length);
@@ -672,10 +690,11 @@ class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase {
}
void visitIndex(HIndex node) {
- if (!node.receiver.isIndexablePrimitive()) return;
+ HTypeMap types = work.types;
+ if (!node.receiver.isIndexablePrimitive(types)) return;
HInstruction index = node.index;
if (index is HBoundsCheck) return;
- if (!node.index.isInteger()) {
+ if (!node.index.isInteger(types)) {
index = insertIntegerCheck(node, index);
}
index = insertBoundsCheck(node, node.receiver, index);
@@ -683,10 +702,11 @@ class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase {
}
void visitIndexAssign(HIndexAssign node) {
- if (!node.receiver.isMutableArray()) return;
+ HTypeMap types = work.types;
+ if (!node.receiver.isMutableArray(types)) return;
HInstruction index = node.index;
if (index is HBoundsCheck) return;
- if (!node.index.isInteger()) {
+ if (!node.index.isInteger(types)) {
index = insertIntegerCheck(node, index);
}
index = insertBoundsCheck(node, node.receiver, index);
@@ -695,10 +715,14 @@ class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase {
}
class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
+ final HTypeMap types;
final String name = "SsaDeadCodeEliminator";
- static bool isDeadCode(HInstruction instruction) {
- return !instruction.hasSideEffects()
+ SsaDeadCodeEliminator(JavaScriptWorkItem work)
+ : types = work.types;
+
+ bool isDeadCode(HInstruction instruction) {
+ return !instruction.hasSideEffects(types)
&& instruction.usedBy.isEmpty()
&& instruction is !HCheck
&& instruction is !HTypeGuard
@@ -825,12 +849,13 @@ class SsaRedundantPhiEliminator implements OptimizationPhase {
class SsaGlobalValueNumberer implements OptimizationPhase {
final String name = "SsaGlobalValueNumberer";
final Compiler compiler;
+ final JavaScriptWorkItem work;
Lasse Reichstein Nielsen 2012/08/08 07:44:53 Do you need the work item, or do you just need the
floitsch 2012/08/08 19:18:37 Done.
final Set<int> visited;
List<int> blockChangesFlags;
List<int> loopChangesFlags;
- SsaGlobalValueNumberer(this.compiler) : visited = new Set<int>();
+ SsaGlobalValueNumberer(this.compiler, this.work) : visited = new Set<int>();
void visitGraph(HGraph graph) {
computeChangesFlags(graph);
@@ -938,6 +963,8 @@ class SsaGlobalValueNumberer implements OptimizationPhase {
}
void computeChangesFlags(HGraph graph) {
+ HTypeMap types = work.types;
+
// Create the changes flags lists. Make sure to initialize the
// loop changes flags list to zero so we can use bitwise or when
// propagating loop changes upwards.
@@ -956,7 +983,7 @@ class SsaGlobalValueNumberer implements OptimizationPhase {
int changesFlags = 0;
HInstruction instruction = block.first;
while (instruction !== null) {
- instruction.prepareGvn();
+ instruction.prepareGvn(types);
changesFlags |= instruction.getChangesFlags();
instruction = instruction.next;
}
@@ -1163,7 +1190,7 @@ class SsaTypeConversionInserter extends HBaseVisitor
// field types.
class BaseRecompilationVisitor extends HBaseVisitor {
final JavaScriptBackend backend;
- final WorkItem work;
+ final JavaScriptWorkItem work;
Lasse Reichstein Nielsen 2012/08/08 07:44:53 Just needed for types?
floitsch 2012/08/08 19:18:37 Done.
Compiler get compiler() => backend.compiler;
BaseRecompilationVisitor(this.backend, this.work);
@@ -1265,8 +1292,9 @@ class SsaRecompilationFieldTypePropagator
final String name = "SsaRecompilationFieldTypePropagator";
HGraph graph;
- SsaRecompilationFieldTypePropagator(
- JavaScriptBackend backend, WorkItem work) : super(backend, work);
+ SsaRecompilationFieldTypePropagator(JavaScriptBackend backend,
+ JavaScriptWorkItem work)
+ : super(backend, work);
void visitGraph(HGraph visitee) {
graph = visitee;
@@ -1287,8 +1315,7 @@ class SsaRecompilationFieldTypePropagator
field.guaranteedType =
type.union(backend.fieldSettersTypeSoFar(element));
} else {
- field.propagatedType =
- type.union(backend.fieldSettersTypeSoFar(element));
+ work.types[field] = type.union(backend.fieldSettersTypeSoFar(element));
}
}
}
@@ -1301,7 +1328,7 @@ class SsaRecompilationFieldTypePropagator
// type, but the fact that the class itself sticks to
// this type for the field is still a strong signal
// indicating the expected type of the field.
- field.propagatedType = type;
+ work.types[field] = type;
} else {
// If there are no invoked setters we know the type of
// this field for sure.

Powered by Google App Engine
This is Rietveld 408576698