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

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

Issue 10702039: Revert "Generate JS operators using helper functions with thunks for operands." because of buildbot… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 6 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
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen_helpers.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/compiler/implementation/ssa/codegen.dart
diff --git a/lib/compiler/implementation/ssa/codegen.dart b/lib/compiler/implementation/ssa/codegen.dart
index e166566a22a53b24078e8171f9842244cbd40d45..145761d9419a02556bf47bbec9a9c78c541fdad4 100644
--- a/lib/compiler/implementation/ssa/codegen.dart
+++ b/lib/compiler/implementation/ssa/codegen.dart
@@ -273,85 +273,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
}
}
- /**
- * Adds parenthes around the code generated by [body] if necessary.
- * The precedence level of the body is assumed to be [precedence].
- */
- void parenthesize(int precedence, void body()) {
- int oldPrecedence = expectedPrecedence;
- beginExpression(precedence);
- // Raise the expected precedence-level to what the body expects.
- expectedPrecedence = precedence;
- body();
- expectedPrecedence = oldPrecedence;
- endExpression(precedence);
- }
-
void withPrecedence(int precedence, void action()) {
int oldPrecedence = expectedPrecedence;
+ beginExpression(precedence);
expectedPrecedence = precedence;
action();
expectedPrecedence = oldPrecedence;
- }
-
- /**
- * Generates code for a JavaScript binary operator.
- * The code is parenthesized if necessary, and the expected
- * precedence level of the left- and right-hand sides is set,
- * based on the operator.
- */
- void binary(String operator, void lhs(), void rhs()) {
- JSBinaryOperatorPrecedence op = JSPrecedence.binary[operator];
- beginExpression(op.precedence);
- withPrecedence(op.left, lhs);
- buffer.add(' ');
- buffer.add(operator);
- buffer.add(' ');
- withPrecedence(op.right, rhs);
- endExpression(op.precedence);
- }
-
- /**
- * Generate code for a JavaScript postfix operator (only -- and ++
- * exist).
- */
- void PostfixExpression(String operator, void body()) {
- // Corresponds to a JavaScript production of the form (ES5 11.3):
- // PostfixExpression ::= LeftHandSideExpression <operator>
- beginExpression(JSPrecedence.POSTFIX_PRECEDENCE);
- withPrecedence(JSPrecedence.CALL_PRECEDENCE, body);
- buffer.add(operator);
- endExpression(JSPrecedence.PSOTFIX_PRECEDENCE);
- }
-
- /**
- * Generate code for a JavaScript prefix operator.
- * There are no validation on the operator text. If it is a "word"
- * operator (e.g., "typeof" or "void") the caller should put in a
- * trailing space if necessary to delimit it from the following
- * expression.
- */
- void prefix(String operator, void body()) {
- // Corresponds to a JavaScript production of the form (ES5 11.4):
- // UnaryExpression ::= <operator> UnaryExpression
- beginExpression(JSPrecedence.PREFIX_PRECEDENCE);
- buffer.add(operator);
- withPrecedence(JSPrecedence.PREFIX_PRECEDENCE, body);
- endExpression(JSPrecedence.PREFIX_PRECEDENCE);
- }
-
- void conditional(void condition(), [void ifTrue(), void ifFalse()]) {
- beginExpression(JSPrecedence.CONDITIONAL_PRECEDENCE);
- withPrecedence(JSPrecedence.LOGICAL_OR_PRECEDENCE, condition);
- buffer.add(" ? ");
- withPrecedence(JSPrecedence.ASSIGNMENT_PRECEDENCE, ifTrue);
- buffer.add(" : ");
- withPrecedence(JSPrecedence.ASSIGNMENT_PRECEDENCE, ifFalse);
- endExpression(JSPrecedence.CONDITIONAL_PRECEDENCE);
- }
-
- void literal(String text) {
- buffer.add(text);
+ endExpression(precedence);
}
void preGenerateMethod(HGraph graph) {
@@ -642,14 +570,22 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
rightIsOne = (numConstant.value == 1);
}
if (binaryInstruction is HAdd && rightIsOne) {
- prefix('++', () => declareVariable(name));
+ beginExpression(JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add('++');
+ declareVariable(name);
+ endExpression(JSPrecedence.PREFIX_PRECEDENCE);
} else if (binaryInstruction is HSubtract && rightIsOne) {
- prefix("--", () => declareVariable(name));
+ beginExpression(JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add('--');
+ declareVariable(name);
+ endExpression(JSPrecedence.PREFIX_PRECEDENCE);
} else {
var operation = binaryInstruction.operation.name;
- binary('$operation=',
- () => declareVariable(name),
- () => use(right, expectedPrecedence));
+ beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
+ declareVariable(name);
+ buffer.add(' ${operation}= ');
+ use(right, JSPrecedence.ASSIGNMENT_PRECEDENCE);
+ endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
}
return true;
}
@@ -679,9 +615,11 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
var name = variableNames.getName(instruction);
if (!handleSimpleUpdateDefinition(instruction, name)
&& !handleTypeConversion(instruction, name)) {
- binary("=",
- () => declareInstruction(instruction),
- () => visit(instruction, expectedPrecedence));
+ withPrecedence(JSPrecedence.ASSIGNMENT_PRECEDENCE, () {
+ declareInstruction(instruction);
+ buffer.add(" = ");
+ visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE);
+ });
}
} else {
visit(instruction, expectedPrecedence);
@@ -1227,9 +1165,12 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
visitInvokeBinary(HInvokeBinary node, String op) {
if (node.builtin) {
- binary(op,
- () => use(node.left, expectedPrecedence),
- () => use(node.right, expectedPrecedence));
+ JSBinaryOperatorPrecedence operatorPrecedences = JSPrecedence.binary[op];
+ beginExpression(operatorPrecedences.precedence);
+ use(node.left, operatorPrecedences.left);
+ buffer.add(' $op ');
+ use(node.right, operatorPrecedences.right);
+ endExpression(operatorPrecedences.precedence);
} else {
visitInvokeStatic(node);
}
@@ -1239,9 +1180,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
// shift operator to achieve this.
visitBitInvokeBinary(HBinaryBitOp node, String op) {
if (node.builtin && requiresUintConversion(node)) {
- binary(">>>",
- () => visitInvokeBinary(node, op),
- () => literal("0"));
+ beginExpression(unsignedShiftPrecedences.precedence);
+ int oldPrecedence = this.expectedPrecedence;
+ this.expectedPrecedence = JSPrecedence.SHIFT_PRECEDENCE;
+ visitInvokeBinary(node, op);
+ buffer.add(' >>> 0');
+ this.expectedPrecedence = oldPrecedence;
+ endExpression(unsignedShiftPrecedences.precedence);
} else {
visitInvokeBinary(node, op);
}
@@ -1249,7 +1194,10 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
visitInvokeUnary(HInvokeUnary node, String op) {
if (node.builtin) {
- prefix(op, () => use(node.operand, expectedPrecedence));
+ beginExpression(JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add('$op');
+ use(node.operand, JSPrecedence.PREFIX_PRECEDENCE);
+ endExpression(JSPrecedence.PREFIX_PRECEDENCE);
} else {
visitInvokeStatic(node);
}
@@ -1258,10 +1206,14 @@ 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)){
- binary(">>>",
- () => visitInvokeUnary(node, op),
- () => literal("0"));
+ if (node.builtin && requiresUintConversion(node)) {
+ beginExpression(unsignedShiftPrecedences.precedence);
+ int oldPrecedence = this.expectedPrecedence;
+ this.expectedPrecedence = JSPrecedence.SHIFT_PRECEDENCE;
+ visitInvokeUnary(node, op);
+ buffer.add(' >>> 0');
+ this.expectedPrecedence = oldPrecedence;
+ endExpression(unsignedShiftPrecedences.precedence);
} else {
visitInvokeUnary(node, op);
}
@@ -1273,32 +1225,40 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
if (leftType.canBeNull() && rightType.canBeNull()) {
if (left.isConstantNull() || right.isConstantNull() ||
(leftType.isPrimitive() && leftType == rightType)) {
- binary("==",
- () => use(left, expectedPrecedence),
- () => use(right, expectedPrecedence));
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ use(left, JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(' == ');
+ use(right, JSPrecedence.RELATIONAL_PRECEDENCE);
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
} else {
assert(NullConstant.JsNull == 'null');
- void condition() {
- binary("==",
- () => use(left, expectedPrecedence),
- () => literal("null"));
- }
- void ifTrue() {
- binary("==",
- () => use(right, expectedPrecedence),
- () => literal("null"));
- }
- void ifFalse() {
- binary("===",
- () => use(left, expectedPrecedence),
- () => use(right, expectedPrecedence));
- }
- conditional(condition, ifTrue, ifFalse);
+ withPrecedence(JSPrecedence.CONDITIONAL_PRECEDENCE, () {
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ use(left, JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(' == null');
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(' ? ');
+ this.expectedPrecedence = JSPrecedence.ASSIGNMENT_PRECEDENCE;
+ withPrecedence(JSPrecedence.LOGICAL_AND_PRECEDENCE, () {
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ use(right, JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(' == null');
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(" : ");
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ use(left, JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(' === ');
+ use(right, JSPrecedence.EQUALITY_PRECEDENCE);
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ });
+ });
}
} else {
- binary("===",
- () => use(left, expectedPrecedence),
- () => use(right, expectedPrecedence));
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ use(left, JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(' === ');
+ use(right, JSPrecedence.RELATIONAL_PRECEDENCE);
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
}
}
@@ -1578,9 +1538,18 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
buffer.add(') ');
}
+ JSBinaryOperatorPrecedence operatorPrecedence = JSPrecedence.binary['&&'];
void generateAnd(HStatementInformation toVisit, Function condition) {
addIndentation();
- binary("&&", condition, () => visitExpression(toVisit));
+ beginExpression(operatorPrecedence.precedence);
+ var oldPrecedence = expectedPrecedence;
+ expectedPrecedence = operatorPrecedence.left;
+ condition();
+ buffer.add(" && ");
+ expectedPrecedence = operatorPrecedence.right;
+ visitExpression(toVisit);
+ expectedPrecedence = oldPrecedence;
+ endExpression(operatorPrecedence.precedence);
buffer.add(";\n");
}
@@ -1626,8 +1595,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
switch (elseKind) {
case EMPTY:
if (thenKind == ONE_EXPRESSION) {
- generateAnd(thenGraph,
- () => use(node.inputs[0], expectedPrecedence));
+ int precedence = operatorPrecedence.left;
+ generateAnd(thenGraph, () { use(node.inputs[0], precedence); });
} else {
emitIf();
visitWithoutIndent(thenGraph);
@@ -1883,19 +1852,19 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
node.value.guaranteedType);
}
String name = compiler.namer.getName(node.element);
- binary("=", () {
- use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
- buffer.add('.');
- buffer.add(name);
- Type type = node.receiver.propagatedType.computeType(compiler);
- if (type != null) {
- world.registerFieldSetter(node.element.name, type);
- backend.updateFieldIntegerSetters(node.element,
- node.value.isInteger());
- }
- }, () {
- use(node.value, expectedPrecedence);
- });
+ beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
+ use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
+ buffer.add('.');
+ buffer.add(name);
+ Type type = node.receiver.propagatedType.computeType(compiler);
+ if (type != null) {
+ world.registerFieldSetter(node.element.name, type);
+ backend.updateFieldIntegerSetters(node.element,
+ node.value.isInteger());
+ }
+ buffer.add(' = ');
+ use(node.value, JSPrecedence.ASSIGNMENT_PRECEDENCE);
+ endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
}
visitLocalGet(HLocalGet node) {
@@ -1903,9 +1872,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
}
visitLocalSet(HLocalSet node) {
- binary("=",
- () => declareInstruction(node.receiver),
- () => use(node.value, expectedPrecedence));
+ declareInstruction(node.receiver);
+ buffer.add(' = ');
+ use(node.value, JSPrecedence.ASSIGNMENT_PRECEDENCE);
}
visitForeign(HForeign node) {
@@ -2029,9 +1998,10 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
}
if (input is HBoolify && isGenerateAtUseSite(input)) {
- binary("!==",
- () => use(input.inputs[0], JSPrecedence.EQUALITY_PRECEDENCE),
- () => literal("true"));
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ use(input.inputs[0], JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(' !== true');
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
} else if (isBuiltinRelational(input) &&
isGenerateAtUseSite(input) &&
input.inputs[0].propagatedType.isUseful() &&
@@ -2054,7 +2024,10 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
visitInvokeBinary(input,
inverseOperator[relational.operation.name.stringValue]);
} else {
- prefix("!", () => use(input, JSPrecedence.PREFIX_PRECEDENCE));
+ beginExpression(JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add('!');
+ use(input, JSPrecedence.PREFIX_PRECEDENCE);
+ endExpression(JSPrecedence.PREFIX_PRECEDENCE);
}
}
@@ -2078,24 +2051,29 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
use(node.inputs[0], expectedPrecedence);
} else if (node.inputs[1].isConstantBoolean()) {
String operation = node.inputs[1].isConstantFalse() ? '&&' : '||';
- binary(operation, () {
- if (operation == '||') {
- if (input is HNot) {
- use(input.inputs[0], expectedPrecedence);
- } else {
- generateNot(input);
- }
+ JSBinaryOperatorPrecedence operatorPrecedence =
+ JSPrecedence.binary[operation];
+ beginExpression(operatorPrecedence.precedence);
+ if (operation == '||') {
+ if (input is HNot) {
+ use(input.inputs[0], operatorPrecedence.left);
} else {
- use(input, expectedPrecedence);
+ generateNot(input);
}
- }, () {
- use(node.inputs[0], expectedPrecedence);
- });
+ } else {
+ use(input, operatorPrecedence.left);
+ }
+ buffer.add(" $operation ");
+ use(node.inputs[0], operatorPrecedence.right);
+ endExpression(operatorPrecedence.precedence);
} else {
- conditional(
- () => use(input, expectedPrecedence),
- ifTrue: () => use(node.inputs[0], expectedPrecedence),
- ifFalse: () => use(node.inputs[1], expectedPrecedence));
+ beginExpression(JSPrecedence.CONDITIONAL_PRECEDENCE);
+ use(input, JSPrecedence.LOGICAL_OR_PRECEDENCE);
+ buffer.add(' ? ');
+ use(node.inputs[0], JSPrecedence.ASSIGNMENT_PRECEDENCE);
+ buffer.add(' : ');
+ use(node.inputs[1], JSPrecedence.ASSIGNMENT_PRECEDENCE);
+ endExpression(JSPrecedence.CONDITIONAL_PRECEDENCE);
}
}
@@ -2135,22 +2113,15 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
// completely.
assert(node.staticChecks != HBoundsCheck.ALWAYS_TRUE);
if (node.staticChecks != HBoundsCheck.ALWAYS_FALSE) {
- void checkUpperBound() {
- binary(">=",
- () => use(node.index, expectedPrecedence),
- () => use(node.length, expectedPrecedence));
- }
buffer.add('if (');
if (node.staticChecks != HBoundsCheck.ALWAYS_ABOVE_ZERO) {
assert(node.staticChecks == HBoundsCheck.FULL_CHECK);
- binary("||",
- () => binary("<",
- () => use(node.index, expectedPrecedence),
- () => literal("0")),
- checkUpperBound);
- } else {
- checkUpperBound();
+ use(node.index, JSPrecedence.RELATIONAL_PRECEDENCE);
+ buffer.add(' < 0 || ');
}
+ use(node.index, JSPrecedence.RELATIONAL_PRECEDENCE);
+ buffer.add(' >= ');
+ use(node.length, JSPrecedence.SHIFT_PRECEDENCE);
buffer.add(") ");
}
generateThrowWithHelper('ioore', node.index);
@@ -2212,15 +2183,17 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
} else if (isEmptyString(node.right)) {
useStringified(node.left, expectedPrecedence);
} else {
+ JSBinaryOperatorPrecedence operatorPrecedences = JSPrecedence.binary['+'];
+ beginExpression(operatorPrecedences.precedence);
+ useStringified(node.left, operatorPrecedences.left);
+ buffer.add(' + ');
// If the right hand side is a string concatenation itself it is
- // safe to make it left associative by omitting parentheses.
- bool useAdditivePrecedence = node.right is HStringConcat;
- binary("+",
- () => useStringified(node.left, expectedPrecedence),
- () => useStringified(node.right,
- useAdditivePrecedence
- ? JSPrecedence.ADDITIVE_PRECEDENCE
- : expectedPrecedence));
+ // safe to make it left associative.
+ int rightPrecedence = (node.right is HStringConcat)
+ ? JSPrecedence.ADDITIVE_PRECEDENCE
+ : operatorPrecedences.right;
+ useStringified(node.right, rightPrecedence);
+ endExpression(operatorPrecedences.precedence);
}
}
@@ -2316,9 +2289,11 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
String builtin = builtinJsName(node);
if (builtin !== null) {
if (builtin == '+') {
- binary('+',
- () => use(node.inputs[1], expectedPrecedence),
- () => use(node.inputs[2], expectedPrecedence));
+ beginExpression(JSPrecedence.ADDITIVE_PRECEDENCE);
+ use(node.inputs[1], JSPrecedence.ADDITIVE_PRECEDENCE);
+ buffer.add(' + ');
+ use(node.inputs[2], JSPrecedence.MULTIPLICATIVE_PRECEDENCE);
+ endExpression(JSPrecedence.ADDITIVE_PRECEDENCE);
} else {
beginExpression(JSPrecedence.CALL_PRECEDENCE);
use(node.inputs[1], JSPrecedence.MEMBER_PRECEDENCE);
@@ -2339,21 +2314,20 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
}
void checkInt(HInstruction input, String cmp) {
- binary(cmp,
- () => use(input, expectedPrecedence),
- () => binary("|",
- () => use(input, expectedPrecedence),
- () => literal("0")));
- }
-
- void checkJSType(HInstruction input, String cmp, String type) {
- binary(cmp,
- () => prefix("typeof ", () => use(input, expectedPrecedence)),
- () => literal("'$type'"));
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ use(input, JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(' $cmp (');
+ use(input, JSPrecedence.BITWISE_OR_PRECEDENCE);
+ buffer.add(' | 0)');
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
}
void checkNum(HInstruction input, String cmp) {
- checkJSType(input, cmp, "number");
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add('typeof ');
+ use(input, JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add(" $cmp 'number'");
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
}
void checkDouble(HInstruction input, String cmp) {
@@ -2361,99 +2335,123 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
}
void checkString(HInstruction input, String cmp) {
- checkJSType(input, cmp, "string");
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add('typeof ');
+ use(input, JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add(" $cmp 'string'");
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
}
void checkBool(HInstruction input, String cmp) {
- checkJSType(input, cmp, "boolean");
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add('typeof ');
+ use(input, JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add(" $cmp 'boolean'");
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
}
void checkObject(HInstruction input, String cmp) {
assert(NullConstant.JsNull == 'null');
if (cmp == "===") {
- binary("&&",
- () => checkJSType(input, "===", "object"),
- () => binary("!==",
- () => use(input, expectedPrecedence),
- () => literal("null")));
+ withPrecedence(JSPrecedence.LOGICAL_AND_PRECEDENCE, () {
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add('typeof ');
+ use(input, JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add(" === 'object'");
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(" && ");
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ use(input, JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add(" !== null");
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ });
} else {
assert(cmp == "!==");
- binary("||",
- () => checkJSType(input, "!==", "object"),
- () => binary("===",
- () => use(input, expectedPrecedence),
- () => literal("null")));
+ withPrecedence(JSPrecedence.LOGICAL_OR_PRECEDENCE, () {
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add('typeof ');
+ use(input, JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add(" !== 'object'");
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(" || ");
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ use(input, JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add(" === null");
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ });
}
}
void checkArray(HInstruction input, String cmp) {
- binary(cmp,
- () {
- use(input, JSPrecedence.MEMBER_PRECEDENCE);
- buffer.add('.constructor');
- },
- () => literal("Array"));
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ use(input, JSPrecedence.MEMBER_PRECEDENCE);
+ buffer.add('.constructor $cmp Array');
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
}
void checkImmutableArray(HInstruction input) {
- prefix("!!", () {
- use(input, JSPrecedence.MEMBER_PRECEDENCE);
- buffer.add('.immutable\$list');
- });
+ beginExpression(JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add('!!');
+ use(input, JSPrecedence.MEMBER_PRECEDENCE);
+ buffer.add('.immutable\$list');
+ endExpression(JSPrecedence.PREFIX_PRECEDENCE);
}
void checkExtendableArray(HInstruction input) {
- prefix("!!" , () {
- use(input, JSPrecedence.MEMBER_PRECEDENCE);
- buffer.add('.fixed\$length');
- });
+ beginExpression(JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add('!!');
+ use(input, JSPrecedence.MEMBER_PRECEDENCE);
+ buffer.add('.fixed\$length');
+ endExpression(JSPrecedence.PREFIX_PRECEDENCE);
}
void checkFixedArray(HInstruction input) {
- parenthesize(JSPrecedence.MEMBER_PRECEDENCE, () {
- use(input, JSPrecedence.MEMBER_PRECEDENCE);
- buffer.add('.fixed\$length');
- });
+ beginExpression(JSPrecedence.PREFIX_PRECEDENCE);
+ use(input, JSPrecedence.MEMBER_PRECEDENCE);
+ buffer.add('.fixed\$length');
+ endExpression(JSPrecedence.PREFIX_PRECEDENCE);
}
void checkNull(HInstruction input) {
- binary("==",
- () => use(input, expectedPrecedence),
- () => literal("null"));
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ use(input, JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(" == null");
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
}
void checkFunction(HInstruction input, Element element) {
- binary("||",
- () => checkJSType(input, "===", "function"),
- () => binary('&&',
- () => checkObject(input, '==='),
- () => checkType(input, element)));
+ withPrecedence(JSPrecedence.LOGICAL_OR_PRECEDENCE, () {
+ beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add('typeof ');
+ use(input, JSPrecedence.PREFIX_PRECEDENCE);
+ buffer.add(" === 'function'");
+ endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(" || ");
+ beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
+ checkObject(input, '===');
+ buffer.add(" && ");
+ checkType(input, element);
+ endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
+ });
}
void checkType(HInstruction input, Element element, [bool negative = false]) {
world.registerIsCheck(element);
bool requiresNativeIsCheck =
backend.emitter.nativeEmitter.requiresNativeIsCheck(element);
- void body() {
- assert(JSPrecedence.CALL_PRECEDENCE == JSPrecedence.MEMBER_PRECEDENCE);
- parenthesize(JSPrecedence.CALL_PRECEDENCE, () {
- use(input, JSPrecedence.MEMBER_PRECEDENCE);
- buffer.add('.');
- buffer.add(compiler.namer.operatorIs(element));
- if (requiresNativeIsCheck) buffer.add('()');
- });
- }
if (!requiresNativeIsCheck) {
if (negative) {
- prefix("!", body);
+ buffer.add('!');
} else {
- prefix("!!", body);
+ buffer.add('!!');
}
} else if (negative) {
- prefix("!", body);
- } else {
- body();
+ buffer.add('!');
}
+ use(input, JSPrecedence.MEMBER_PRECEDENCE);
+ buffer.add('.');
+ buffer.add(compiler.namer.operatorIs(element));
+ if (requiresNativeIsCheck) buffer.add('()');
}
void handleStringSupertypeCheck(HInstruction input, Element element) {
@@ -2461,11 +2459,15 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
// would need to check for List too.
assert(element !== compiler.listClass
&& !Elements.isListSupertype(element, compiler));
- binary("||",
- () => checkString(input, '==='),
- () => binary("&&",
- () => checkObject(input, '==='),
- () => checkType(input, element)));
+ withPrecedence(JSPrecedence.LOGICAL_OR_PRECEDENCE, () {
+ checkString(input, '===');
+ buffer.add(' || ');
+ withPrecedence(JSPrecedence.LOGICAL_AND_PRECEDENCE, () {
+ checkObject(input, '===');
+ buffer.add(' && ');
+ checkType(input, element);
+ });
+ });
}
void handleListOrSupertypeCheck(HInstruction input, Element element) {
@@ -2473,11 +2475,16 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
// would need to check for String too.
assert(element !== compiler.stringClass
&& !Elements.isStringSupertype(element, compiler));
- binary("&&",
- () => checkObject(input, '==='),
- () => binary("||",
- () => checkArray(input, '==='),
- () => checkType(input, element)));
+ beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
+ checkObject(input, '===');
+ buffer.add(' && (');
+ beginExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE);
+ checkArray(input, '===');
+ buffer.add(' || ');
+ checkType(input, element);
+ buffer.add(')');
+ endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE);
+ endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
}
void visitIs(HIs node) {
@@ -2492,70 +2499,66 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
ClassElement objectClass = compiler.objectClass;
HInstruction input = node.expression;
- void plainTypeCheck() {
- if (element === objectClass || element === compiler.dynamicClass) {
- // The constant folder also does this optimization, but we make
- // it safe by assuming it may have not run.
- literal('true');
- } else if (element == compiler.stringClass) {
- checkString(input, '===');
- } else if (element == compiler.doubleClass) {
- checkDouble(input, '===');
- } else if (element == compiler.numClass) {
- checkNum(input, '===');
- } else if (element == compiler.boolClass) {
- checkBool(input, '===');
- } else if (element == compiler.functionClass) {
- checkFunction(input, element);
- } else if (element == compiler.intClass) {
- binary("&&",
- () => checkNum(input, '==='),
- () => checkInt(input, '==='));
- } else if (Elements.isStringSupertype(element, compiler)) {
- handleStringSupertypeCheck(input, element);
- } else if (element === compiler.listClass
- || Elements.isListSupertype(element, compiler)) {
- handleListOrSupertypeCheck(input, element);
- } else if (input.propagatedType.canBePrimitive()
- || input.propagatedType.canBeNull()) {
- binary("&&",
- () => checkObject(input, '==='),
- () => checkType(input, element));
- } else {
- checkType(input, element);
- }
- }
-
- void typeArgumentCheck() {
- if (compiler.codegenWorld.rti.hasTypeArguments(type)) {
- InterfaceType interfaceType = type;
- ClassElement cls = type.element;
- Link<Type> arguments = interfaceType.arguments;
- binary("&&", plainTypeCheck, () {
- var base = () => checkObject(node.typeInfoCall, '===');
- // Do left-fold on elements with [base] as initial value.
- cls.typeParameters.forEach((name, _) {
- Type argument = arguments.head;
- // TODO(lrn): Should we advance arguments here?
- // What if there aren't any?
- var oldBase = base;
- base = () => binary("&&", oldBase, () {
- parenthesize(JSPrecedence.ASSIGNMENT_PRECEDENCE, () {
- use(node.typeInfoCall, JSPrecedence.MEMBER_PRECEDENCE);
- buffer.add(".${name.slowToString()} === '${argument}'");
- });
- });
- });
- base();
- });
- } else {
- plainTypeCheck();
- }
- }
+ int oldPrecedence;
if (node.nullOk) {
- binary("||", () => checkNull(input), typeArgumentCheck);
+ oldPrecedence = expectedPrecedence;
+ beginExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE);
+ expectedPrecedence = JSPrecedence.LOGICAL_OR_PRECEDENCE;
+ checkNull(input);
+ buffer.add(' || ');
+ }
+ if (element === objectClass || element === compiler.dynamicClass) {
+ // The constant folder also does this optimization, but we make
+ // it safe by assuming it may have not run.
+ buffer.add('true');
+ } else if (element == compiler.stringClass) {
+ checkString(input, '===');
+ } else if (element == compiler.doubleClass) {
+ checkDouble(input, '===');
+ } else if (element == compiler.numClass) {
+ checkNum(input, '===');
+ } else if (element == compiler.boolClass) {
+ checkBool(input, '===');
+ } else if (element == compiler.functionClass) {
+ checkFunction(input, element);
+ } else if (element == compiler.intClass) {
+ beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
+ checkNum(input, '===');
+ buffer.add(' && ');
+ checkInt(input, '===');
+ endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
+ } else if (Elements.isStringSupertype(element, compiler)) {
+ handleStringSupertypeCheck(input, element);
+ } else if (element === compiler.listClass
+ || Elements.isListSupertype(element, compiler)) {
+ handleListOrSupertypeCheck(input, element);
+ } else if (input.propagatedType.canBePrimitive()
+ || input.propagatedType.canBeNull()) {
+ beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
+ checkObject(input, '===');
+ buffer.add(' && ');
+ checkType(input, element);
+ endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
} else {
- typeArgumentCheck();
+ checkType(input, element);
+ }
+ if (compiler.codegenWorld.rti.hasTypeArguments(type)) {
+ InterfaceType interfaceType = type;
+ ClassElement cls = type.element;
+ Link<Type> arguments = interfaceType.arguments;
+ buffer.add(' && ');
+ checkObject(node.typeInfoCall, '===');
+ cls.typeParameters.forEach((name, _) {
+ buffer.add(' && ');
+ beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
+ use(node.typeInfoCall, JSPrecedence.EQUALITY_PRECEDENCE);
+ buffer.add(".${name.slowToString()} === '${arguments.head}'");
+ endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
+ });
+ }
+ if (node.nullOk) {
+ expectedPrecedence = oldPrecedence;
+ endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE);
}
}
@@ -2749,11 +2752,11 @@ class SsaOptimizedCodeGenerator extends SsaCodeGenerator {
} else if (node.isExtendableArray()) {
// if (input is !Object || input is !Array || input.isFixed) bailout
buffer.add('if (');
- binary("||",
- () => binary("||",
- () => checkObject(input, '!=='),
- () => checkArray(input, '!==')),
- () => checkFixedArray(input));
+ checkObject(input, '!==');
+ buffer.add('||');
+ checkArray(input, '!==');
+ buffer.add('||');
+ checkFixedArray(input);
buffer.add(') ');
bailout(node, 'Not an extendable array');
} else if (node.isMutableArray()) {
@@ -2761,43 +2764,39 @@ class SsaOptimizedCodeGenerator extends SsaCodeGenerator {
// || ((input is !Array || input.isImmutable)
// && input is !JsIndexingBehavior)) bailout
buffer.add('if (');
- binary("||",
- () => checkObject(input, '!=='),
- () => binary("&&",
- () => binary("||",
- () => checkArray(input, '!=='),
- () => checkImmutableArray(input)),
- () => checkType(input, indexingBehavior,
- negative: true)));
- buffer.add(") ");
+ checkObject(input, '!==');
+ buffer.add(' || ((');
+ checkArray(input, '!==');
+ buffer.add(' || ');
+ checkImmutableArray(input);
+ buffer.add(') && ');
+ checkType(input, indexingBehavior, negative: true);
+ buffer.add(')) ');
bailout(node, 'Not a mutable array');
} else if (node.isReadableArray()) {
// if (input is !Object
// || (input is !Array && input is !JsIndexingBehavior)) bailout
buffer.add('if (');
- binary("||",
- () => checkObject(input, '!=='),
- () => binary("&&",
- () => checkArray(input, '!=='),
- () => checkType(input, indexingBehavior,
- negative: true)));
- buffer.add(') ');
+ checkObject(input, '!==');
+ buffer.add(' || (');
+ checkArray(input, '!==');
+ buffer.add(' && ');
+ checkType(input, indexingBehavior, negative: true);
+ buffer.add(')) ');
bailout(node, 'Not an array');
} else if (node.isIndexablePrimitive()) {
// if (input is !String
// && (input is !Object
// || (input is !Array && input is !JsIndexingBehavior))) bailout
buffer.add('if (');
- binary("&&",
- () => checkString(input, '!=='),
- () => binary("||",
- () => checkObject(input, '!=='),
- () => binary("&&",
- () => checkArray(input, '!=='),
- () => checkType(input,
- indexingBehavior,
- negative: true))));
- buffer.add(') ');
+ checkString(input, '!==');
+ buffer.add(' && (');
+ checkObject(input, '!==');
+ buffer.add(' || (');
+ checkArray(input, '!==');
+ buffer.add(' && ');
+ checkType(input, indexingBehavior, negative: true);
+ buffer.add('))) ');
bailout(node, 'Not a string or array');
} else {
compiler.internalError('Unexpected type guard', instruction: input);
@@ -3063,33 +3062,15 @@ class SsaUnoptimizedCodeGenerator extends SsaCodeGenerator {
int precedence = JSPrecedence.EXPRESSION_PRECEDENCE;
// TODO(ngeoffray): Put the condition initialization in the
// [setup] buffer.
-
- void stateTest() {
- binary("&&",
- () => binary("==", () => literal("state"), () => literal("0")),
- () => use(node.inputs[0], expectedPrecedence));
- }
-
List<HTypeGuard> guards = node.thenBlock.guards;
- if (guards.length > 0) {
- // Fold guards from the left using '||'.
- Function buildGuard(int i) => () {
- binary("==",
- () => literal("state"),
- () => literal("${guards[i].state}"));
- }
- Function guard = buildGuard(0);
- for (int i = 1, len = guards.length; i < len; i++) {
- int index = i;
- Function oldGuard = guard;
- guard = () => binary("||", oldGuard, buildGuard(index));
- }
- binary("||", guard, stateTest);
- } else {
- stateTest();
+ for (int i = 0, len = guards.length; i < len; i++) {
+ buffer.add('state == ${guards[i].state} || ');
}
+ buffer.add('(state == 0 && ');
+ precedence = JSPrecedence.BITWISE_OR_PRECEDENCE;
+ use(node.inputs[0], precedence);
- buffer.add(') {\n');
+ buffer.add(')) {\n');
indent++;
if (thenHasGuards) startBailoutSwitch();
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698