| Index: lib/compiler/implementation/ssa/codegen.dart
|
| diff --git a/lib/compiler/implementation/ssa/codegen.dart b/lib/compiler/implementation/ssa/codegen.dart
|
| index 1ef09f150366d92b7012dd2e92fe84fd3cc3afb6..9b1d584746e126aae92f72faa0a46228a06967d8 100644
|
| --- a/lib/compiler/implementation/ssa/codegen.dart
|
| +++ b/lib/compiler/implementation/ssa/codegen.dart
|
| @@ -154,7 +154,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| static final int TYPE_DECLARATION = 2;
|
|
|
| final JavaScriptBackend backend;
|
| - final WorkItem work;
|
| + final JavaScriptWorkItem work;
|
| final CodeBuffer buffer;
|
| final String parameters;
|
|
|
| @@ -299,9 +299,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| void preGenerateMethod(HGraph graph) {
|
| - new SsaInstructionMerger(generateAtUseSite).visitGraph(graph);
|
| - new SsaConditionMerger(generateAtUseSite,
|
| - controlFlowOperators).visitGraph(graph);
|
| + new SsaInstructionMerger(work, generateAtUseSite).visitGraph(graph);
|
| + new SsaConditionMerger(
|
| + work, generateAtUseSite, controlFlowOperators).visitGraph(graph);
|
| SsaLiveIntervalBuilder intervalBuilder =
|
| new SsaLiveIntervalBuilder(compiler, generateAtUseSite);
|
| intervalBuilder.visitGraph(graph);
|
| @@ -563,10 +563,12 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| return false;
|
| }
|
|
|
| + HTypeMap types = work.types;
|
| +
|
| // 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 +1187,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| visitInvokeBinary(HInvokeBinary node, String op) {
|
| - if (node.builtin) {
|
| + if (node.isBuiltin(work.types)) {
|
| JSBinaryOperatorPrecedence operatorPrecedences = JSPrecedence.binary[op];
|
| beginExpression(operatorPrecedences.precedence);
|
| use(node.left, operatorPrecedences.left);
|
| @@ -1200,7 +1202,8 @@ 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)) {
|
| + HTypeMap types = work.types;
|
| + if (node.isBuiltin(types) && requiresUintConversion(node)) {
|
| beginExpression(unsignedShiftPrecedences.precedence);
|
| int oldPrecedence = this.expectedPrecedence;
|
| this.expectedPrecedence = JSPrecedence.SHIFT_PRECEDENCE;
|
| @@ -1214,7 +1217,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| visitInvokeUnary(HInvokeUnary node, String op) {
|
| - if (node.builtin) {
|
| + if (node.isBuiltin(work.types)) {
|
| beginExpression(JSPrecedence.PREFIX_PRECEDENCE);
|
| buffer.add('$op');
|
| use(node.operand, JSPrecedence.PREFIX_PRECEDENCE);
|
| @@ -1227,7 +1230,8 @@ 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)) {
|
| + HTypeMap types = work.types;
|
| + 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, work.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(work.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(work.types));
|
| emitIdentityComparison(node.left, node.right);
|
| }
|
|
|
| @@ -1432,10 +1436,12 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| return true;
|
| }
|
|
|
| + HTypeMap types = work.types;
|
| +
|
| 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 +1450,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 +1756,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| Selector getOptimizedSelectorFor(HInvoke node, Selector defaultSelector) {
|
| - Type receiverType = node.inputs[0].propagatedType.computeType(compiler);
|
| + HType receiverHType = work.types[node.inputs[0]];
|
| + Type receiverType = receiverHType.computeType(compiler);
|
| if (receiverType !== null) {
|
| return new TypedSelector(receiverType, defaultSelector);
|
| } else {
|
| @@ -1837,7 +1846,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| buffer.add('.');
|
| buffer.add(name);
|
| beginExpression(JSPrecedence.MEMBER_PRECEDENCE);
|
| - Type type = node.receiver.propagatedType.computeType(compiler);
|
| + HType receiverHType = work.types[node.receiver];
|
| + Type type = receiverHType.computeType(compiler);
|
| if (type != null) {
|
| world.registerFieldGetter(node.element.name, type);
|
| }
|
| @@ -1869,7 +1879,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
|
| buffer.add('.');
|
| buffer.add(name);
|
| - Type type = node.receiver.propagatedType.computeType(compiler);
|
| + HTypeMap types = work.types;
|
| + Type type = types[node.receiver].computeType(compiler);
|
| if (type != null) {
|
| if (!work.element.isGenerativeConstructorBody()) {
|
| world.registerFieldSetter(node.element.name, type);
|
| @@ -1885,8 +1896,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(' = ');
|
| @@ -1922,13 +1932,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| visitForeignNew(HForeignNew node) {
|
| + HTypeMap types = work.types;
|
| int j = 0;
|
| node.element.forEachInstanceField(
|
| 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);
|
| @@ -2018,10 +2028,12 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|
|
|
|
| void generateNot(HInstruction input) {
|
| + HTypeMap types = work.types;
|
| +
|
| 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)) {
|
| @@ -2031,10 +2043,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>{
|
| @@ -2232,7 +2244,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| void useStringified(HInstruction node, int precedence) {
|
| - if (node.isString()) {
|
| + if (node.isString(work.types)) {
|
| use(node, precedence);
|
| } else {
|
| Element convertToString = compiler.findHelper(const SourceString("S"));
|
| @@ -2259,7 +2271,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| void visitIndex(HIndex node) {
|
| - if (node.builtin) {
|
| + if (node.isBuiltin(work.types)) {
|
| beginExpression(JSPrecedence.MEMBER_PRECEDENCE);
|
| use(node.inputs[1], JSPrecedence.MEMBER_PRECEDENCE);
|
| buffer.add('[');
|
| @@ -2272,7 +2284,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| void visitIndexAssign(HIndexAssign node) {
|
| - if (node.builtin) {
|
| + if (node.isBuiltin(work.types)) {
|
| beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
|
| use(node.inputs[1], JSPrecedence.MEMBER_PRECEDENCE);
|
| buffer.add('[');
|
| @@ -2292,19 +2304,21 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| bool getter = interceptor.getter;
|
| SourceString name = interceptor.name;
|
|
|
| - if (interceptor.isLengthGetterOnStringOrArray()) {
|
| + HTypeMap types = work.types;
|
| +
|
| + 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 '+';
|
| }
|
| }
|
| @@ -2559,8 +2573,8 @@ 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 (work.types[input].canBePrimitive()
|
| + || work.types[input].canBeNull()) {
|
| beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
|
| checkObject(input, '===');
|
| buffer.add(' && ');
|
| @@ -2756,34 +2770,35 @@ class SsaOptimizedCodeGenerator extends SsaCodeGenerator {
|
| }
|
|
|
| void visitTypeGuard(HTypeGuard node) {
|
| + HTypeMap types = work.types;
|
| 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, '!==');
|
| @@ -2793,7 +2808,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
|
| @@ -2807,7 +2822,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 (');
|
| @@ -2818,7 +2833,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
|
| @@ -3175,11 +3190,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)) {
|
|
|