Fix evaluation order of GT and LTE operators.

According to the ES5 spec all ">" and "<=" expressions should be be
evaluated left-to-right. This obsoletes old hacks for reversing the
order to be ES3 compliant.

R=lrn@chromium.org
BUG=v8:1752

Review URL: http://codereview.chromium.org/8275035

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9641 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a8bb36f8
...@@ -4071,33 +4071,25 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { ...@@ -4071,33 +4071,25 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
case Token::EQ_STRICT: case Token::EQ_STRICT:
case Token::EQ: case Token::EQ:
cond = eq; cond = eq;
__ pop(r1);
break; break;
case Token::LT: case Token::LT:
cond = lt; cond = lt;
__ pop(r1);
break; break;
case Token::GT: case Token::GT:
// Reverse left and right sides to obtain ECMA-262 conversion order. cond = gt;
cond = lt;
__ mov(r1, result_register());
__ pop(r0);
break; break;
case Token::LTE: case Token::LTE:
// Reverse left and right sides to obtain ECMA-262 conversion order. cond = le;
cond = ge;
__ mov(r1, result_register());
__ pop(r0);
break; break;
case Token::GTE: case Token::GTE:
cond = ge; cond = ge;
__ pop(r1);
break; break;
case Token::IN: case Token::IN:
case Token::INSTANCEOF: case Token::INSTANCEOF:
default: default:
UNREACHABLE(); UNREACHABLE();
} }
__ pop(r1);
bool inline_smi_code = ShouldInlineSmiCase(op); bool inline_smi_code = ShouldInlineSmiCase(op);
JumpPatchSite patch_site(masm_); JumpPatchSite patch_site(masm_);
......
...@@ -1559,11 +1559,9 @@ Condition CompareIC::ComputeCondition(Token::Value op) { ...@@ -1559,11 +1559,9 @@ Condition CompareIC::ComputeCondition(Token::Value op) {
case Token::LT: case Token::LT:
return lt; return lt;
case Token::GT: case Token::GT:
// Reverse left and right operands to obtain ECMA-262 conversion order. return gt;
return lt;
case Token::LTE: case Token::LTE:
// Reverse left and right operands to obtain ECMA-262 conversion order. return le;
return ge;
case Token::GTE: case Token::GTE:
return ge; return ge;
default: default:
......
...@@ -1404,12 +1404,10 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) { ...@@ -1404,12 +1404,10 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) {
LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
Token::Value op = instr->token();
ASSERT(instr->left()->representation().IsTagged()); ASSERT(instr->left()->representation().IsTagged());
ASSERT(instr->right()->representation().IsTagged()); ASSERT(instr->right()->representation().IsTagged());
bool reversed = (op == Token::GT || op == Token::LTE); LOperand* left = UseFixed(instr->left(), r1);
LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1); LOperand* right = UseFixed(instr->right(), r0);
LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0);
LCmpT* result = new LCmpT(left, right); LCmpT* result = new LCmpT(left, right);
return MarkAsCall(DefineFixed(result, r0), instr); return MarkAsCall(DefineFixed(result, r0), instr);
} }
......
...@@ -2176,9 +2176,6 @@ void LCodeGen::DoCmpT(LCmpT* instr) { ...@@ -2176,9 +2176,6 @@ void LCodeGen::DoCmpT(LCmpT* instr) {
__ cmp(r0, Operand(0)); // This instruction also signals no smi code inlined. __ cmp(r0, Operand(0)); // This instruction also signals no smi code inlined.
Condition condition = ComputeCompareCondition(op); Condition condition = ComputeCompareCondition(op);
if (op == Token::GT || op == Token::LTE) {
condition = ReverseCondition(condition);
}
__ LoadRoot(ToRegister(instr->result()), __ LoadRoot(ToRegister(instr->result()),
Heap::kTrueValueRootIndex, Heap::kTrueValueRootIndex,
condition); condition);
......
...@@ -4147,33 +4147,25 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { ...@@ -4147,33 +4147,25 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
case Token::EQ_STRICT: case Token::EQ_STRICT:
case Token::EQ: case Token::EQ:
cc = equal; cc = equal;
__ pop(edx);
break; break;
case Token::LT: case Token::LT:
cc = less; cc = less;
__ pop(edx);
break; break;
case Token::GT: case Token::GT:
// Reverse left and right sizes to obtain ECMA-262 conversion order. cc = greater;
cc = less;
__ mov(edx, result_register());
__ pop(eax);
break; break;
case Token::LTE: case Token::LTE:
// Reverse left and right sizes to obtain ECMA-262 conversion order. cc = less_equal;
cc = greater_equal;
__ mov(edx, result_register());
__ pop(eax);
break; break;
case Token::GTE: case Token::GTE:
cc = greater_equal; cc = greater_equal;
__ pop(edx);
break; break;
case Token::IN: case Token::IN:
case Token::INSTANCEOF: case Token::INSTANCEOF:
default: default:
UNREACHABLE(); UNREACHABLE();
} }
__ pop(edx);
decrement_stack_height(); decrement_stack_height();
bool inline_smi_code = ShouldInlineSmiCase(op); bool inline_smi_code = ShouldInlineSmiCase(op);
......
...@@ -1591,11 +1591,9 @@ Condition CompareIC::ComputeCondition(Token::Value op) { ...@@ -1591,11 +1591,9 @@ Condition CompareIC::ComputeCondition(Token::Value op) {
case Token::LT: case Token::LT:
return less; return less;
case Token::GT: case Token::GT:
// Reverse left and right operands to obtain ECMA-262 conversion order. return greater;
return less;
case Token::LTE: case Token::LTE:
// Reverse left and right operands to obtain ECMA-262 conversion order. return less_equal;
return greater_equal;
case Token::GTE: case Token::GTE:
return greater_equal; return greater_equal;
default: default:
......
...@@ -2029,9 +2029,6 @@ void LCodeGen::DoCmpT(LCmpT* instr) { ...@@ -2029,9 +2029,6 @@ void LCodeGen::DoCmpT(LCmpT* instr) {
CallCode(ic, RelocInfo::CODE_TARGET, instr); CallCode(ic, RelocInfo::CODE_TARGET, instr);
Condition condition = ComputeCompareCondition(op); Condition condition = ComputeCompareCondition(op);
if (op == Token::GT || op == Token::LTE) {
condition = ReverseCondition(condition);
}
Label true_value, done; Label true_value, done;
__ test(eax, Operand(eax)); __ test(eax, Operand(eax));
__ j(condition, &true_value, Label::kNear); __ j(condition, &true_value, Label::kNear);
......
...@@ -1434,13 +1434,11 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) { ...@@ -1434,13 +1434,11 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) {
LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
Token::Value op = instr->token();
ASSERT(instr->left()->representation().IsTagged()); ASSERT(instr->left()->representation().IsTagged());
ASSERT(instr->right()->representation().IsTagged()); ASSERT(instr->right()->representation().IsTagged());
bool reversed = (op == Token::GT || op == Token::LTE);
LOperand* context = UseFixed(instr->context(), esi); LOperand* context = UseFixed(instr->context(), esi);
LOperand* left = UseFixed(instr->left(), reversed ? eax : edx); LOperand* left = UseFixed(instr->left(), edx);
LOperand* right = UseFixed(instr->right(), reversed ? edx : eax); LOperand* right = UseFixed(instr->right(), eax);
LCmpT* result = new LCmpT(context, left, right); LCmpT* result = new LCmpT(context, left, right);
return MarkAsCall(DefineFixed(result, eax), instr); return MarkAsCall(DefineFixed(result, eax), instr);
} }
......
...@@ -3997,33 +3997,25 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { ...@@ -3997,33 +3997,25 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
case Token::EQ_STRICT: case Token::EQ_STRICT:
case Token::EQ: case Token::EQ:
cc = equal; cc = equal;
__ pop(rdx);
break; break;
case Token::LT: case Token::LT:
cc = less; cc = less;
__ pop(rdx);
break; break;
case Token::GT: case Token::GT:
// Reverse left and right sizes to obtain ECMA-262 conversion order. cc = greater;
cc = less;
__ movq(rdx, result_register());
__ pop(rax);
break; break;
case Token::LTE: case Token::LTE:
// Reverse left and right sizes to obtain ECMA-262 conversion order. cc = less_equal;
cc = greater_equal;
__ movq(rdx, result_register());
__ pop(rax);
break; break;
case Token::GTE: case Token::GTE:
cc = greater_equal; cc = greater_equal;
__ pop(rdx);
break; break;
case Token::IN: case Token::IN:
case Token::INSTANCEOF: case Token::INSTANCEOF:
default: default:
UNREACHABLE(); UNREACHABLE();
} }
__ pop(rdx);
bool inline_smi_code = ShouldInlineSmiCase(op); bool inline_smi_code = ShouldInlineSmiCase(op);
JumpPatchSite patch_site(masm_); JumpPatchSite patch_site(masm_);
......
...@@ -1613,11 +1613,9 @@ Condition CompareIC::ComputeCondition(Token::Value op) { ...@@ -1613,11 +1613,9 @@ Condition CompareIC::ComputeCondition(Token::Value op) {
case Token::LT: case Token::LT:
return less; return less;
case Token::GT: case Token::GT:
// Reverse left and right operands to obtain ECMA-262 conversion order. return greater;
return less;
case Token::LTE: case Token::LTE:
// Reverse left and right operands to obtain ECMA-262 conversion order. return less_equal;
return greater_equal;
case Token::GTE: case Token::GTE:
return greater_equal; return greater_equal;
default: default:
......
...@@ -1979,9 +1979,6 @@ void LCodeGen::DoCmpT(LCmpT* instr) { ...@@ -1979,9 +1979,6 @@ void LCodeGen::DoCmpT(LCmpT* instr) {
CallCode(ic, RelocInfo::CODE_TARGET, instr); CallCode(ic, RelocInfo::CODE_TARGET, instr);
Condition condition = TokenToCondition(op, false); Condition condition = TokenToCondition(op, false);
if (op == Token::GT || op == Token::LTE) {
condition = ReverseCondition(condition);
}
Label true_value, done; Label true_value, done;
__ testq(rax, rax); __ testq(rax, rax);
__ j(condition, &true_value, Label::kNear); __ j(condition, &true_value, Label::kNear);
......
...@@ -1396,12 +1396,10 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) { ...@@ -1396,12 +1396,10 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) {
LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
Token::Value op = instr->token();
ASSERT(instr->left()->representation().IsTagged()); ASSERT(instr->left()->representation().IsTagged());
ASSERT(instr->right()->representation().IsTagged()); ASSERT(instr->right()->representation().IsTagged());
bool reversed = (op == Token::GT || op == Token::LTE); LOperand* left = UseFixed(instr->left(), rdx);
LOperand* left = UseFixed(instr->left(), reversed ? rax : rdx); LOperand* right = UseFixed(instr->right(), rax);
LOperand* right = UseFixed(instr->right(), reversed ? rdx : rax);
LCmpT* result = new LCmpT(left, right); LCmpT* result = new LCmpT(left, right);
return MarkAsCall(DefineFixed(result, rax), instr); return MarkAsCall(DefineFixed(result, rax), instr);
} }
......
...@@ -83,9 +83,9 @@ function TestNonPrimitive(order, f) { ...@@ -83,9 +83,9 @@ function TestNonPrimitive(order, f) {
} }
TestNonPrimitive("xy", MaxLT); TestNonPrimitive("xy", MaxLT);
TestNonPrimitive("yx", MaxLE); TestNonPrimitive("xy", MaxLE);
TestNonPrimitive("xy", MaxGE); TestNonPrimitive("xy", MaxGE);
TestNonPrimitive("yx", MaxGT); TestNonPrimitive("xy", MaxGT);
// Test compare in case of aliased registers. // Test compare in case of aliased registers.
function CmpX(x) { if (x == x) return 42; } function CmpX(x) { if (x == x) return 42; }
......
...@@ -161,7 +161,7 @@ assertEquals("fiskfisk", x, "Compare objects b >= b valueOf order"); ...@@ -161,7 +161,7 @@ assertEquals("fiskfisk", x, "Compare objects b >= b valueOf order");
x = ""; x = "";
assertFalse(a > b, "Compare objects a > b"); assertFalse(a > b, "Compare objects a > b");
assertEquals("fiskhest", x, "Compare objects a > b valueOf order"); assertEquals("hestfisk", x, "Compare objects a > b valueOf order");
x = ""; x = "";
assertFalse(a > void(0), "Compare objects a > undefined"); assertFalse(a > void(0), "Compare objects a > undefined");
...@@ -195,7 +195,7 @@ function identical_object_comparison() { ...@@ -195,7 +195,7 @@ function identical_object_comparison() {
x = ""; x = "";
assertFalse(a > b, "Compare objects a > b"); assertFalse(a > b, "Compare objects a > b");
assertEquals("fiskhest", x, "Compare objects a > b valueOf order"); assertEquals("hestfisk", x, "Compare objects a > b valueOf order");
x = ""; x = "";
assertFalse(a > void(0), "Compare objects a > undefined"); assertFalse(a > void(0), "Compare objects a > undefined");
......
...@@ -410,12 +410,6 @@ js1_5/extensions/regress-435345-01: FAIL_OK ...@@ -410,12 +410,6 @@ js1_5/extensions/regress-435345-01: FAIL_OK
js1_5/extensions/regress-455413: FAIL_OK js1_5/extensions/regress-455413: FAIL_OK
# The spec specifies reverse evaluation order for < and >=.
# See section 11.8.2 and 11.8.5.
# We implement the spec here but the test tests the more straigtforward order.
ecma_3/Operators/order-01: FAIL_OK
# Uses Mozilla-specific QName, XML, XMLList and Iterator. # Uses Mozilla-specific QName, XML, XMLList and Iterator.
js1_5/Regress/regress-407323: FAIL_OK js1_5/Regress/regress-407323: FAIL_OK
js1_5/Regress/regress-407957: FAIL_OK js1_5/Regress/regress-407957: FAIL_OK
......
...@@ -162,6 +162,10 @@ S11.1.5_A4.2: FAIL_OK ...@@ -162,6 +162,10 @@ S11.1.5_A4.2: FAIL_OK
S9.9_A1: FAIL_OK S9.9_A1: FAIL_OK
S9.9_A2: FAIL_OK S9.9_A2: FAIL_OK
# The expected evaluation order of comparison operations changed.
S11.8.2_A2.3_T1: FAIL_OK
S11.8.3_A2.3_T1: FAIL_OK
# Calls builtins without an explicit receiver which means that # Calls builtins without an explicit receiver which means that
# undefined is passed to the builtin. The tests expect the global # undefined is passed to the builtin. The tests expect the global
# object to be passed which was true in ES3 but not in ES5. # object to be passed which was true in ES3 but not in ES5.
......
...@@ -43,19 +43,6 @@ S8.7_A5_T2: FAIL ...@@ -43,19 +43,6 @@ S8.7_A5_T2: FAIL
# V8 Bug: http://code.google.com/p/v8/issues/detail?id=1624 # V8 Bug: http://code.google.com/p/v8/issues/detail?id=1624
S10.4.2.1_A1: FAIL S10.4.2.1_A1: FAIL
# V8 Bug: http://code.google.com/p/v8/issues/detail?id=1752
S11.8.2_A2.3_T1: FAIL
S11.8.3_A2.3_T1: FAIL
11.8.2-1: FAIL
11.8.2-2: FAIL
11.8.2-3: FAIL
11.8.2-4: FAIL
11.8.3-1: FAIL
11.8.3-2: FAIL
11.8.3-3: FAIL
11.8.3-4: FAIL
11.8.3-5: FAIL
# V8 Bug. # V8 Bug.
S13.2.3_A1: FAIL S13.2.3_A1: FAIL
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment