| Index: src/ia32/fast-codegen-ia32.cc
|
| ===================================================================
|
| --- src/ia32/fast-codegen-ia32.cc (revision 3635)
|
| +++ src/ia32/fast-codegen-ia32.cc (working copy)
|
| @@ -214,17 +214,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())) __ mov(result_register(), reg);
|
| DoTest(context);
|
| break;
|
| +
|
| + case Expression::kValueTest:
|
| + case Expression::kTestValue:
|
| + if (!reg.is(result_register())) __ mov(result_register(), reg);
|
| + switch (location_) {
|
| + case kAccumulator:
|
| + break;
|
| + case kStack:
|
| + __ push(result_register());
|
| + break;
|
| + }
|
| + DoTest(context);
|
| + break;
|
| }
|
| }
|
|
|
| @@ -251,6 +258,7 @@
|
| }
|
|
|
| case Expression::kTest:
|
| + // For simplicity we always test the accumulator register.
|
| Move(result_register(), slot);
|
| DoTest(context);
|
| break;
|
| @@ -258,7 +266,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;
|
| }
|
| @@ -285,6 +299,7 @@
|
| break;
|
|
|
| case Expression::kTest:
|
| + // For simplicity we always test the accumulator register.
|
| __ mov(result_register(), lit->handle());
|
| DoTest(context);
|
| break;
|
| @@ -292,7 +307,13 @@
|
| case Expression::kValueTest:
|
| case Expression::kTestValue:
|
| __ mov(result_register(), lit->handle());
|
| - __ push(result_register());
|
| + switch (location_) {
|
| + case kAccumulator:
|
| + break;
|
| + case kStack:
|
| + __ push(result_register());
|
| + break;
|
| + }
|
| DoTest(context);
|
| break;
|
| }
|
| @@ -319,13 +340,21 @@
|
| break;
|
|
|
| case Expression::kTest:
|
| + // For simplicity we always test the accumulator register.
|
| __ pop(result_register());
|
| DoTest(context);
|
| break;
|
|
|
| case Expression::kValueTest:
|
| case Expression::kTestValue:
|
| - __ mov(result_register(), Operand(esp, 0));
|
| + switch (location_) {
|
| + case kAccumulator:
|
| + __ pop(result_register());
|
| + break;
|
| + case kStack:
|
| + __ mov(result_register(), Operand(esp, 0));
|
| + break;
|
| + }
|
| DoTest(context);
|
| break;
|
| }
|
| @@ -359,6 +388,7 @@
|
| break;
|
|
|
| case Expression::kTest:
|
| + // For simplicity we always test the accumulator register.
|
| __ Drop(count);
|
| if (!reg.is(result_register())) __ mov(result_register(), reg);
|
| DoTest(context);
|
| @@ -366,9 +396,17 @@
|
|
|
| case Expression::kValueTest:
|
| case Expression::kTestValue:
|
| - if (count > 1) __ Drop(count - 1);
|
| - if (!reg.is(result_register())) __ mov(result_register(), reg);
|
| - __ mov(Operand(esp, 0), result_register());
|
| + switch (location_) {
|
| + case kAccumulator:
|
| + __ Drop(count);
|
| + if (!reg.is(result_register())) __ mov(result_register(), reg);
|
| + break;
|
| + case kStack:
|
| + if (count > 1) __ Drop(count - 1);
|
| + __ mov(result_register(), reg);
|
| + __ mov(Operand(esp, 0), result_register());
|
| + break;
|
| + }
|
| DoTest(context);
|
| break;
|
| }
|
| @@ -440,18 +478,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.
|
| __ cmp(result_register(), Factory::undefined_value());
|
| @@ -466,6 +530,34 @@
|
| __ test(result_register(), Immediate(kSmiTagMask));
|
| __ j(zero, 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());
|
|
|