Chromium Code Reviews| Index: lib/compiler/implementation/ssa/codegen.dart |
| diff --git a/lib/compiler/implementation/ssa/codegen.dart b/lib/compiler/implementation/ssa/codegen.dart |
| index e7bb18399fd799743546577fa73aa1f069ac29df..e768ac2c02e407051b0f3eeb0c51b9b8e0578321 100644 |
| --- a/lib/compiler/implementation/ssa/codegen.dart |
| +++ b/lib/compiler/implementation/ssa/codegen.dart |
| @@ -155,6 +155,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| final JavaScriptBackend backend; |
| final WorkItem work; |
| + final HTypeMap types; |
| final CodeBuffer buffer; |
| final String parameters; |
| @@ -250,10 +251,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| } |
| SsaCodeGenerator(this.backend, |
|
Lasse Reichstein Nielsen
2012/08/16 10:41:34
Why is the constructor down here. Move it up just
floitsch
2012/08/16 14:10:04
Done.
|
| - this.work, |
| + WorkItem work, |
| this.parameters, |
| this.parameterNames) |
| - : declaredVariables = new Set<String>(), |
| + : this.work = work, |
| + this.types = |
| + (work.compilationContext as JavaScriptItemCompilationContext).types, |
|
Lasse Reichstein Nielsen
2012/08/16 10:41:34
Why not just expect a JavaScriptWorkItem if you kn
floitsch
2012/08/16 14:10:04
There is no JavaScriptWorkItem anymore.
Keeping as
|
| + declaredVariables = new Set<String>(), |
| delayedVariableDeclarations = new Set<String>(), |
| buffer = new CodeBuffer(), |
| generateAtUseSite = new Set<HInstruction>(), |
| @@ -299,9 +303,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| } |
| void preGenerateMethod(HGraph graph) { |
| - new SsaInstructionMerger(generateAtUseSite).visitGraph(graph); |
| - new SsaConditionMerger(generateAtUseSite, |
| - controlFlowOperators).visitGraph(graph); |
| + new SsaInstructionMerger(types, generateAtUseSite).visitGraph(graph); |
| + new SsaConditionMerger( |
| + types, generateAtUseSite, controlFlowOperators).visitGraph(graph); |
| SsaLiveIntervalBuilder intervalBuilder = |
| new SsaLiveIntervalBuilder(compiler, generateAtUseSite); |
| intervalBuilder.visitGraph(graph); |
| @@ -566,7 +570,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| // Is it a builtin operation involving +, -, /, or *? |
| HBinaryArithmetic binaryInstruction = instruction; |
| assert(binaryInstruction.inputs.length == 3); |
| - if (binaryInstruction.builtin) { |
| + if (binaryInstruction.isBuiltin(types)) { |
| var left = binaryInstruction.left; |
| var right = binaryInstruction.right; |
| if (isCommutative && variableNames.getName(right) == name) { |
| @@ -1185,7 +1189,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| } |
| visitInvokeBinary(HInvokeBinary node, String op) { |
| - if (node.builtin) { |
| + if (node.isBuiltin(types)) { |
| JSBinaryOperatorPrecedence operatorPrecedences = JSPrecedence.binary[op]; |
| beginExpression(operatorPrecedences.precedence); |
| use(node.left, operatorPrecedences.left); |
| @@ -1200,7 +1204,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| // We want the outcome of bit-operations to be positive. We use the unsigned |
| // shift operator to achieve this. |
| visitBitInvokeBinary(HBinaryBitOp node, String op) { |
| - if (node.builtin && requiresUintConversion(node)) { |
| + if (node.isBuiltin(types) && requiresUintConversion(node)) { |
| beginExpression(unsignedShiftPrecedences.precedence); |
| int oldPrecedence = this.expectedPrecedence; |
| this.expectedPrecedence = JSPrecedence.SHIFT_PRECEDENCE; |
| @@ -1214,7 +1218,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| } |
| visitInvokeUnary(HInvokeUnary node, String op) { |
| - if (node.builtin) { |
| + if (node.isBuiltin(types)) { |
| beginExpression(JSPrecedence.PREFIX_PRECEDENCE); |
| buffer.add('$op'); |
| use(node.operand, JSPrecedence.PREFIX_PRECEDENCE); |
| @@ -1227,7 +1231,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| // We want the outcome of bit-operations to be positive. We use the unsigned |
| // shift operator to achieve this. |
| visitBitInvokeUnary(HInvokeUnary node, String op) { |
| - if (node.builtin && requiresUintConversion(node)) { |
| + if (node.isBuiltin(types) && requiresUintConversion(node)) { |
| beginExpression(unsignedShiftPrecedences.precedence); |
| int oldPrecedence = this.expectedPrecedence; |
| this.expectedPrecedence = JSPrecedence.SHIFT_PRECEDENCE; |
| @@ -1241,7 +1245,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| } |
| void emitIdentityComparison(HInstruction left, HInstruction right) { |
| - String op = singleIdentityComparison(left, right); |
| + String op = singleIdentityComparison(left, right, types); |
| if (op != null) { |
| beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| use(left, JSPrecedence.EQUALITY_PRECEDENCE); |
| @@ -1274,7 +1278,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| } |
| visitEquals(HEquals node) { |
| - if (node.builtin) { |
| + if (node.isBuiltin(types)) { |
| emitIdentityComparison(node.left, node.right); |
| } else { |
| visitInvokeStatic(node); |
| @@ -1282,7 +1286,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| } |
| visitIdentity(HIdentity node) { |
| - assert(node.builtin); |
| + assert(node.isBuiltin(types)); |
| emitIdentityComparison(node.left, node.right); |
| } |
| @@ -1435,7 +1439,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| for (HInstruction instruction = start.first; |
| instruction != start.last; |
| instruction = instruction.next) { |
| - if (instruction.isStatement) { |
| + if (instruction.isStatement(types)) { |
| if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS; |
| } else if (!isGenerateAtUseSite(instruction)) { |
| if (!updateKind(ONE_EXPRESSION)) return MULTIPLE_STATEMENTS; |
| @@ -1444,7 +1448,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| HInstruction last = start.last; |
| if (last is !HGoto) { |
| - if (!updateKind(last.isStatement ? ONE_STATEMENT : ONE_EXPRESSION)) { |
| + if (!updateKind(last.isStatement(types) |
| + ? ONE_STATEMENT |
| + : ONE_EXPRESSION)) { |
| return MULTIPLE_STATEMENTS; |
| } |
| } |
| @@ -1748,7 +1754,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| } |
| Selector getOptimizedSelectorFor(HInvoke node, Selector defaultSelector) { |
| - Type receiverType = node.inputs[0].propagatedType.computeType(compiler); |
| + HType receiverHType = types[node.inputs[0]]; |
| + Type receiverType = receiverHType.computeType(compiler); |
| if (receiverType !== null) { |
| return new TypedSelector(receiverType, defaultSelector); |
| } else { |
| @@ -1845,7 +1852,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| buffer.add('.'); |
| buffer.add(name); |
| beginExpression(JSPrecedence.MEMBER_PRECEDENCE); |
| - Type type = node.receiver.propagatedType.computeType(compiler); |
| + HType receiverHType = types[node.receiver]; |
| + Type type = receiverHType.computeType(compiler); |
| if (type != null) { |
| world.registerFieldGetter(node.element.name, type); |
| } |
| @@ -1878,7 +1886,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); |
| buffer.add('.'); |
| buffer.add(name); |
| - Type type = node.receiver.propagatedType.computeType(compiler); |
| + Type type = types[node.receiver].computeType(compiler); |
| if (type != null) { |
| if (!work.element.isGenerativeConstructorBody()) { |
| world.registerFieldSetter(node.element.name, type); |
| @@ -1894,8 +1902,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| isSimpleFieldNumberComputation(node.value, node)) { |
| backend.updateFieldSetters(node.element, HType.NUMBER); |
| } else { |
| - backend.updateFieldSetters(node.element, |
| - node.value.propagatedType); |
| + backend.updateFieldSetters(node.element, types[node.value]); |
| } |
| } |
| buffer.add(' = '); |
| @@ -1936,8 +1943,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| includeBackendMembers: true, |
| includeSuperMembers: true, |
| f: (ClassElement enclosingClass, Element member) { |
| - backend.updateFieldInitializers(member, |
| - node.inputs[j].propagatedType); |
| + backend.updateFieldInitializers(member, types[node.inputs[j]]); |
| j++; |
| }); |
| String jsClassReference = compiler.namer.isolateAccess(node.element); |
| @@ -2030,7 +2036,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| bool isBuiltinRelational(HInstruction instruction) { |
| if (instruction is !HRelational) return false; |
| HRelational relational = instruction; |
| - return relational.builtin; |
| + return relational.isBuiltin(types); |
| } |
| if (input is HBoolify && isGenerateAtUseSite(input)) { |
| @@ -2040,10 +2046,10 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| } else if (isBuiltinRelational(input) && |
| isGenerateAtUseSite(input) && |
| - input.inputs[0].propagatedType.isUseful() && |
| - !input.inputs[0].isDouble() && |
| - input.inputs[1].propagatedType.isUseful() && |
| - !input.inputs[1].isDouble()) { |
| + types[input.inputs[0]].isUseful() && |
| + !input.inputs[0].isDouble(types) && |
| + types[input.inputs[1]].isUseful() && |
| + !input.inputs[1].isDouble(types)) { |
| // This optimization doesn't work for NaN, so we only do it if the |
| // type is known to be non-Double. |
| Map<String, String> inverseOperator = const <String>{ |
| @@ -2241,7 +2247,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| } |
| void useStringified(HInstruction node, int precedence) { |
| - if (node.isString()) { |
| + if (node.isString(types)) { |
| use(node, precedence); |
| } else { |
| Element convertToString = compiler.findHelper(const SourceString("S")); |
| @@ -2268,7 +2274,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| } |
| void visitIndex(HIndex node) { |
| - if (node.builtin) { |
| + if (node.isBuiltin(types)) { |
| beginExpression(JSPrecedence.MEMBER_PRECEDENCE); |
| use(node.inputs[1], JSPrecedence.MEMBER_PRECEDENCE); |
| buffer.add('['); |
| @@ -2281,7 +2287,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| } |
| void visitIndexAssign(HIndexAssign node) { |
| - if (node.builtin) { |
| + if (node.isBuiltin(types)) { |
| beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| use(node.inputs[1], JSPrecedence.MEMBER_PRECEDENCE); |
| buffer.add('['); |
| @@ -2301,19 +2307,19 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| bool getter = interceptor.getter; |
| SourceString name = interceptor.name; |
| - if (interceptor.isLengthGetterOnStringOrArray()) { |
| + if (interceptor.isLengthGetterOnStringOrArray(types)) { |
| return 'length'; |
| - } else if (receiver.isExtendableArray() && !getter) { |
| + } else if (receiver.isExtendableArray(types) && !getter) { |
| if (name == const SourceString('add') && arity == 1) { |
| return 'push'; |
| } |
| if (name == const SourceString('removeLast') && arity == 0) { |
| return 'pop'; |
| } |
| - } else if (receiver.isString() && !getter) { |
| + } else if (receiver.isString(types) && !getter) { |
| if (name == const SourceString('concat') && |
| arity == 1 && |
| - interceptor.inputs[2].isString()) { |
| + interceptor.inputs[2].isString(types)) { |
| return '+'; |
| } |
| } |
| @@ -2568,8 +2574,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
| } else if (element === compiler.listClass |
| || Elements.isListSupertype(element, compiler)) { |
| handleListOrSupertypeCheck(input, element); |
| - } else if (input.propagatedType.canBePrimitive() |
| - || input.propagatedType.canBeNull()) { |
| + } else if (types[input].canBePrimitive() || types[input].canBeNull()) { |
| beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); |
| checkObject(input, '==='); |
| buffer.add(' && '); |
| @@ -2768,31 +2773,31 @@ class SsaOptimizedCodeGenerator extends SsaCodeGenerator { |
| addIndentation(); |
| HInstruction input = node.guarded; |
| Element indexingBehavior = compiler.jsIndexingBehaviorInterface; |
| - if (node.isInteger()) { |
| + if (node.isInteger(types)) { |
| // if (input is !int) bailout |
| buffer.add('if ('); |
| checkInt(input, '!=='); |
| buffer.add(') '); |
| bailout(node, 'Not an integer'); |
| - } else if (node.isNumber()) { |
| + } else if (node.isNumber(types)) { |
| // if (input is !num) bailout |
| buffer.add('if ('); |
| checkNum(input, '!=='); |
| buffer.add(') '); |
| bailout(node, 'Not a number'); |
| - } else if (node.isBoolean()) { |
| + } else if (node.isBoolean(types)) { |
| // if (input is !bool) bailout |
| buffer.add('if ('); |
| checkBool(input, '!=='); |
| buffer.add(') '); |
| bailout(node, 'Not a boolean'); |
| - } else if (node.isString()) { |
| + } else if (node.isString(types)) { |
| // if (input is !string) bailout |
| buffer.add('if ('); |
| checkString(input, '!=='); |
| buffer.add(') '); |
| bailout(node, 'Not a string'); |
| - } else if (node.isExtendableArray()) { |
| + } else if (node.isExtendableArray(types)) { |
| // if (input is !Object || input is !Array || input.isFixed) bailout |
| buffer.add('if ('); |
| checkObject(input, '!=='); |
| @@ -2802,7 +2807,7 @@ class SsaOptimizedCodeGenerator extends SsaCodeGenerator { |
| checkFixedArray(input); |
| buffer.add(') '); |
| bailout(node, 'Not an extendable array'); |
| - } else if (node.isMutableArray()) { |
| + } else if (node.isMutableArray(types)) { |
| // if (input is !Object |
| // || ((input is !Array || input.isImmutable) |
| // && input is !JsIndexingBehavior)) bailout |
| @@ -2816,7 +2821,7 @@ class SsaOptimizedCodeGenerator extends SsaCodeGenerator { |
| checkType(input, indexingBehavior, negative: true); |
| buffer.add(')) '); |
| bailout(node, 'Not a mutable array'); |
| - } else if (node.isReadableArray()) { |
| + } else if (node.isReadableArray(types)) { |
| // if (input is !Object |
| // || (input is !Array && input is !JsIndexingBehavior)) bailout |
| buffer.add('if ('); |
| @@ -2827,7 +2832,7 @@ class SsaOptimizedCodeGenerator extends SsaCodeGenerator { |
| checkType(input, indexingBehavior, negative: true); |
| buffer.add(')) '); |
| bailout(node, 'Not an array'); |
| - } else if (node.isIndexablePrimitive()) { |
| + } else if (node.isIndexablePrimitive(types)) { |
| // if (input is !String |
| // && (input is !Object |
| // || (input is !Array && input is !JsIndexingBehavior))) bailout |
| @@ -3184,11 +3189,13 @@ class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator { |
| } |
| } |
| -String singleIdentityComparison(HInstruction left, HInstruction right) { |
| +String singleIdentityComparison(HInstruction left, |
| + HInstruction right, |
| + HTypeMap propagatedTypes) { |
| // Returns the single identity comparison (== or ===) or null if a more |
| // complex expression is required. |
| - HType leftType = left.propagatedType; |
| - HType rightType = right.propagatedType; |
| + HType leftType = propagatedTypes[left]; |
| + HType rightType = propagatedTypes[right]; |
| if (leftType.canBeNull() && rightType.canBeNull()) { |
| if (left.isConstantNull() || right.isConstantNull() || |
| (leftType.isPrimitive() && leftType == rightType)) { |