Index: src/x64/fast-codegen-x64.cc |
=================================================================== |
--- src/x64/fast-codegen-x64.cc (revision 3635) |
+++ src/x64/fast-codegen-x64.cc (working copy) |
@@ -221,17 +221,24 @@ |
} |
break; |
- case Expression::kValueTest: |
- case Expression::kTestValue: |
- // Push an extra copy of the value in case it's needed. |
- __ push(reg); |
- // Fall through. |
- |
case Expression::kTest: |
// For simplicity we always test the accumulator register. |
if (!reg.is(result_register())) __ movq(result_register(), reg); |
DoTest(context); |
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; |
} |
} |
@@ -265,7 +272,13 @@ |
case Expression::kValueTest: |
case Expression::kTestValue: |
Move(result_register(), slot); |
- __ push(result_register()); |
+ switch (location_) { |
+ case kAccumulator: |
+ break; |
+ case kStack: |
+ __ push(result_register()); |
+ break; |
+ } |
DoTest(context); |
break; |
} |
@@ -298,7 +311,13 @@ |
case Expression::kValueTest: |
case Expression::kTestValue: |
__ Move(result_register(), lit->handle()); |
- __ push(result_register()); |
+ switch (location_) { |
+ case kAccumulator: |
+ break; |
+ case kStack: |
+ __ push(result_register()); |
+ break; |
+ } |
DoTest(context); |
break; |
} |
@@ -331,7 +350,14 @@ |
case Expression::kValueTest: |
case Expression::kTestValue: |
- __ movq(result_register(), Operand(rsp, 0)); |
+ switch (location_) { |
+ case kAccumulator: |
+ __ pop(result_register()); |
+ break; |
+ case kStack: |
+ __ movq(result_register(), Operand(rsp, 0)); |
+ break; |
+ } |
DoTest(context); |
break; |
} |
@@ -372,9 +398,17 @@ |
case Expression::kValueTest: |
case Expression::kTestValue: |
- if (count > 1) __ Drop(count - 1); |
- if (!reg.is(result_register())) __ movq(result_register(), reg); |
- __ movq(Operand(rsp, 0), result_register()); |
+ 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; |
} |
@@ -446,18 +480,44 @@ |
void FastCodeGenerator::DoTest(Expression::Context context) { |
- // The value to test is in the accumulator, and duplicated on the stack if |
- // necessary (for value/test and test/value contexts). |
+ // 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_); |
- // If there is a value on the stack, use a discard label for the |
- // value-is-unneeded branch in the inlined part of the test. |
+ // 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 = |
- (context == Expression::kTestValue) ? &discard : true_label_; |
- Label* if_false = |
- (context == Expression::kValueTest) ? &discard : false_label_; |
+ 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; |
+ } |
// Emit the inlined tests assumed by the stub. |
__ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); |
@@ -472,6 +532,34 @@ |
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()); |