Index: src/x64/full-codegen-x64.cc |
=================================================================== |
--- src/x64/full-codegen-x64.cc (revision 5316) |
+++ src/x64/full-codegen-x64.cc (working copy) |
@@ -253,21 +253,8 @@ |
case Expression::kTest: |
// For simplicity we always test the accumulator register. |
if (!reg.is(result_register())) __ movq(result_register(), reg); |
- DoTest(context); |
+ DoTest(true_label_, false_label_, NULL); |
break; |
- |
- case Expression::kValueTest: |
- case Expression::kTestValue: |
- if (!reg.is(result_register())) __ movq(result_register(), reg); |
- switch (location_) { |
- case kAccumulator: |
- break; |
- case kStack: |
- __ push(result_register()); |
- break; |
- } |
- DoTest(context); |
- break; |
} |
} |
@@ -295,21 +282,8 @@ |
case Expression::kTest: |
Move(result_register(), slot); |
- DoTest(context); |
+ DoTest(true_label_, false_label_, NULL); |
break; |
- |
- case Expression::kValueTest: |
- case Expression::kTestValue: |
- Move(result_register(), slot); |
- switch (location_) { |
- case kAccumulator: |
- break; |
- case kStack: |
- __ push(result_register()); |
- break; |
- } |
- DoTest(context); |
- break; |
} |
} |
@@ -334,21 +308,8 @@ |
case Expression::kTest: |
__ Move(result_register(), lit->handle()); |
- DoTest(context); |
+ DoTest(true_label_, false_label_, NULL); |
break; |
- |
- case Expression::kValueTest: |
- case Expression::kTestValue: |
- __ Move(result_register(), lit->handle()); |
- switch (location_) { |
- case kAccumulator: |
- break; |
- case kStack: |
- __ push(result_register()); |
- break; |
- } |
- DoTest(context); |
- break; |
} |
} |
@@ -374,21 +335,8 @@ |
case Expression::kTest: |
__ pop(result_register()); |
- DoTest(context); |
+ DoTest(true_label_, false_label_, NULL); |
break; |
- |
- case Expression::kValueTest: |
- case Expression::kTestValue: |
- switch (location_) { |
- case kAccumulator: |
- __ pop(result_register()); |
- break; |
- case kStack: |
- __ movq(result_register(), Operand(rsp, 0)); |
- break; |
- } |
- DoTest(context); |
- break; |
} |
} |
@@ -422,24 +370,8 @@ |
case Expression::kTest: |
__ Drop(count); |
if (!reg.is(result_register())) __ movq(result_register(), reg); |
- DoTest(context); |
+ DoTest(true_label_, false_label_, NULL); |
break; |
- |
- case Expression::kValueTest: |
- case Expression::kTestValue: |
- switch (location_) { |
- case kAccumulator: |
- __ Drop(count); |
- if (!reg.is(result_register())) __ movq(result_register(), reg); |
- break; |
- case kStack: |
- if (count > 1) __ Drop(count - 1); |
- __ movq(result_register(), reg); |
- __ movq(Operand(rsp, 0), result_register()); |
- break; |
- } |
- DoTest(context); |
- break; |
} |
} |
@@ -465,14 +397,6 @@ |
*if_true = true_label_; |
*if_false = false_label_; |
break; |
- case Expression::kValueTest: |
- *if_true = materialize_true; |
- *if_false = false_label_; |
- break; |
- case Expression::kTestValue: |
- *if_true = true_label_; |
- *if_false = materialize_false; |
- break; |
} |
} |
@@ -512,32 +436,6 @@ |
case Expression::kTest: |
break; |
- |
- case Expression::kValueTest: |
- __ bind(materialize_true); |
- switch (location_) { |
- case kAccumulator: |
- __ Move(result_register(), Factory::true_value()); |
- break; |
- case kStack: |
- __ Push(Factory::true_value()); |
- break; |
- } |
- __ jmp(true_label_); |
- break; |
- |
- case Expression::kTestValue: |
- __ bind(materialize_false); |
- switch (location_) { |
- case kAccumulator: |
- __ Move(result_register(), Factory::false_value()); |
- break; |
- case kStack: |
- __ Push(Factory::false_value()); |
- break; |
- } |
- __ jmp(false_label_); |
- break; |
} |
} |
@@ -567,76 +465,13 @@ |
case Expression::kTest: |
__ jmp(flag ? true_label_ : false_label_); |
break; |
- case Expression::kTestValue: |
- switch (location_) { |
- case kAccumulator: |
- // If value is false it's needed. |
- if (!flag) __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); |
- break; |
- case kStack: |
- // If value is false it's needed. |
- if (!flag) __ PushRoot(Heap::kFalseValueRootIndex); |
- break; |
- } |
- __ jmp(flag ? true_label_ : false_label_); |
- break; |
- case Expression::kValueTest: |
- switch (location_) { |
- case kAccumulator: |
- // If value is true it's needed. |
- if (flag) __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); |
- break; |
- case kStack: |
- // If value is true it's needed. |
- if (flag) __ PushRoot(Heap::kTrueValueRootIndex); |
- break; |
- } |
- __ jmp(flag ? true_label_ : false_label_); |
- break; |
} |
} |
-void FullCodeGenerator::DoTest(Expression::Context context) { |
- // The value to test is in the accumulator. If the value might be needed |
- // on the stack (value/test and test/value contexts with a stack location |
- // desired), then the value is already duplicated on the stack. |
- ASSERT_NE(NULL, true_label_); |
- ASSERT_NE(NULL, false_label_); |
- |
- // In value/test and test/value expression contexts with stack as the |
- // desired location, there is already an extra value on the stack. Use a |
- // label to discard it if unneeded. |
- Label discard; |
- Label* if_true = true_label_; |
- Label* if_false = false_label_; |
- switch (context) { |
- case Expression::kUninitialized: |
- case Expression::kEffect: |
- case Expression::kValue: |
- UNREACHABLE(); |
- case Expression::kTest: |
- break; |
- case Expression::kValueTest: |
- switch (location_) { |
- case kAccumulator: |
- break; |
- case kStack: |
- if_false = &discard; |
- break; |
- } |
- break; |
- case Expression::kTestValue: |
- switch (location_) { |
- case kAccumulator: |
- break; |
- case kStack: |
- if_true = &discard; |
- break; |
- } |
- break; |
- } |
- |
+void FullCodeGenerator::DoTest(Label* if_true, |
+ Label* if_false, |
+ Label* fall_through) { |
// Emit the inlined tests assumed by the stub. |
__ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); |
__ j(equal, if_false); |
@@ -650,83 +485,28 @@ |
Condition is_smi = masm_->CheckSmi(result_register()); |
__ j(is_smi, if_true); |
- // Save a copy of the value if it may be needed and isn't already saved. |
- switch (context) { |
- case Expression::kUninitialized: |
- case Expression::kEffect: |
- case Expression::kValue: |
- UNREACHABLE(); |
- case Expression::kTest: |
- break; |
- case Expression::kValueTest: |
- switch (location_) { |
- case kAccumulator: |
- __ push(result_register()); |
- break; |
- case kStack: |
- break; |
- } |
- break; |
- case Expression::kTestValue: |
- switch (location_) { |
- case kAccumulator: |
- __ push(result_register()); |
- break; |
- case kStack: |
- break; |
- } |
- break; |
- } |
- |
// Call the ToBoolean stub for all other cases. |
ToBooleanStub stub; |
__ push(result_register()); |
__ CallStub(&stub); |
__ testq(rax, rax); |
- // The stub returns nonzero for true. Complete based on the context. |
- switch (context) { |
- case Expression::kUninitialized: |
- case Expression::kEffect: |
- case Expression::kValue: |
- UNREACHABLE(); |
+ // The stub returns nonzero for true. |
+ Split(not_zero, if_true, if_false, fall_through); |
+} |
- case Expression::kTest: |
- __ j(not_zero, true_label_); |
- __ jmp(false_label_); |
- break; |
- case Expression::kValueTest: |
- switch (location_) { |
- case kAccumulator: |
- __ j(zero, &discard); |
- __ pop(result_register()); |
- __ jmp(true_label_); |
- break; |
- case kStack: |
- __ j(not_zero, true_label_); |
- break; |
- } |
- __ bind(&discard); |
- __ Drop(1); |
- __ jmp(false_label_); |
- break; |
- |
- case Expression::kTestValue: |
- switch (location_) { |
- case kAccumulator: |
- __ j(not_zero, &discard); |
- __ pop(result_register()); |
- __ jmp(false_label_); |
- break; |
- case kStack: |
- __ j(zero, false_label_); |
- break; |
- } |
- __ bind(&discard); |
- __ Drop(1); |
- __ jmp(true_label_); |
- break; |
+void FullCodeGenerator::Split(Condition cc, |
+ Label* if_true, |
+ Label* if_false, |
+ Label* fall_through) { |
+ if (if_false == fall_through) { |
+ __ j(cc, if_true); |
+ } else if (if_true == fall_through) { |
+ __ j(NegateCondition(cc), if_false); |
+ } else { |
+ __ j(cc, if_true); |
+ __ jmp(if_false); |
} |
} |
@@ -1206,7 +986,7 @@ |
__ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
__ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
int literal_offset = |
- FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
+ FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
__ movq(rbx, FieldOperand(rcx, literal_offset)); |
__ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); |
__ j(not_equal, &materialized); |
@@ -1987,8 +1767,7 @@ |
PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
Condition positive_smi = __ CheckPositiveSmi(rax); |
- __ j(positive_smi, if_true); |
- __ jmp(if_false); |
+ Split(positive_smi, if_true, if_false, NULL); |
Apply(context_, if_true, if_false); |
} |
@@ -2016,8 +1795,7 @@ |
__ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); |
__ j(below, if_false); |
__ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); |
- __ j(below_equal, if_true); |
- __ jmp(if_false); |
+ Split(below_equal, if_true, if_false, NULL); |
Apply(context_, if_true, if_false); |
} |
@@ -2035,8 +1813,7 @@ |
__ JumpIfSmi(rax, if_false); |
__ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); |
- __ j(above_equal, if_true); |
- __ jmp(if_false); |
+ Split(above_equal, if_true, if_false, NULL); |
Apply(context_, if_true, if_false); |
} |
@@ -2056,8 +1833,7 @@ |
__ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
__ testb(FieldOperand(rbx, Map::kBitFieldOffset), |
Immediate(1 << Map::kIsUndetectable)); |
- __ j(not_zero, if_true); |
- __ jmp(if_false); |
+ Split(not_zero, if_true, if_false, NULL); |
Apply(context_, if_true, if_false); |
} |
@@ -2094,8 +1870,7 @@ |
__ JumpIfSmi(rax, if_false); |
__ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
- __ j(equal, if_true); |
- __ jmp(if_false); |
+ Split(equal, if_true, if_false, NULL); |
Apply(context_, if_true, if_false); |
} |
@@ -2113,8 +1888,7 @@ |
__ JumpIfSmi(rax, if_false); |
__ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); |
- __ j(equal, if_true); |
- __ jmp(if_false); |
+ Split(equal, if_true, if_false, NULL); |
Apply(context_, if_true, if_false); |
} |
@@ -2132,8 +1906,7 @@ |
__ JumpIfSmi(rax, if_false); |
__ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); |
- __ j(equal, if_true); |
- __ jmp(if_false); |
+ Split(equal, if_true, if_false, NULL); |
Apply(context_, if_true, if_false); |
} |
@@ -2162,8 +1935,7 @@ |
__ bind(&check_frame_marker); |
__ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), |
Smi::FromInt(StackFrame::CONSTRUCT)); |
- __ j(equal, if_true); |
- __ jmp(if_false); |
+ Split(equal, if_true, if_false, NULL); |
Apply(context_, if_true, if_false); |
} |
@@ -2183,8 +1955,7 @@ |
__ pop(rbx); |
__ cmpq(rax, rbx); |
- __ j(equal, if_true); |
- __ jmp(if_false); |
+ Split(equal, if_true, if_false, NULL); |
Apply(context_, if_true, if_false); |
} |
@@ -2840,19 +2611,7 @@ |
break; |
} |
break; |
- case Expression::kTestValue: |
- // Value is false so it's needed. |
- switch (location_) { |
- case kAccumulator: |
- __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); |
- break; |
- case kStack: |
- __ PushRoot(Heap::kUndefinedValueRootIndex); |
- break; |
- } |
- // Fall through. |
case Expression::kTest: |
- case Expression::kValueTest: |
__ jmp(false_label_); |
break; |
} |
@@ -3033,8 +2792,6 @@ |
break; |
case Expression::kValue: |
case Expression::kTest: |
- case Expression::kValueTest: |
- case Expression::kTestValue: |
// Save the result on the stack. If we have a named or keyed property |
// we store the result under the receiver that is currently on top |
// of the stack. |
@@ -3138,41 +2895,7 @@ |
} |
} |
-void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
- Comment cmnt(masm_, "[ BinaryOperation"); |
- switch (expr->op()) { |
- case Token::COMMA: |
- VisitForEffect(expr->left()); |
- Visit(expr->right()); |
- break; |
- case Token::OR: |
- case Token::AND: |
- EmitLogicalOperation(expr); |
- break; |
- |
- case Token::ADD: |
- case Token::SUB: |
- case Token::DIV: |
- case Token::MOD: |
- case Token::MUL: |
- case Token::BIT_OR: |
- case Token::BIT_AND: |
- case Token::BIT_XOR: |
- case Token::SHL: |
- case Token::SHR: |
- case Token::SAR: |
- VisitForValue(expr->left(), kStack); |
- VisitForValue(expr->right(), kAccumulator); |
- EmitBinaryOp(expr->op(), context_); |
- break; |
- |
- default: |
- UNREACHABLE(); |
- } |
-} |
- |
- |
void FullCodeGenerator::EmitNullCompare(bool strict, |
Register obj, |
Register null_const, |
@@ -3181,7 +2904,7 @@ |
Register scratch) { |
__ cmpq(obj, null_const); |
if (strict) { |
- __ j(equal, if_true); |
+ Split(equal, if_true, if_false, NULL); |
} else { |
__ j(equal, if_true); |
__ CompareRoot(obj, Heap::kUndefinedValueRootIndex); |
@@ -3191,9 +2914,8 @@ |
__ movq(scratch, FieldOperand(obj, HeapObject::kMapOffset)); |
__ testb(FieldOperand(scratch, Map::kBitFieldOffset), |
Immediate(1 << Map::kIsUndetectable)); |
- __ j(not_zero, if_true); |
+ Split(not_zero, if_true, if_false, NULL); |
} |
- __ jmp(if_false); |
} |
@@ -3213,8 +2935,7 @@ |
VisitForValue(expr->right(), kStack); |
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); |
__ CompareRoot(rax, Heap::kTrueValueRootIndex); |
- __ j(equal, if_true); |
- __ jmp(if_false); |
+ Split(equal, if_true, if_false, NULL); |
break; |
case Token::INSTANCEOF: { |
@@ -3222,8 +2943,8 @@ |
InstanceofStub stub; |
__ CallStub(&stub); |
__ testq(rax, rax); |
- __ j(zero, if_true); // The stub returns 0 for true. |
- __ jmp(if_false); |
+ // The stub returns 0 for true. |
+ Split(zero, if_true, if_false, NULL); |
break; |
} |
@@ -3291,8 +3012,7 @@ |
CompareStub stub(cc, strict); |
__ CallStub(&stub); |
__ testq(rax, rax); |
- __ j(cc, if_true); |
- __ jmp(if_false); |
+ Split(cc, if_true, if_false, NULL); |
} |
} |