Chromium Code Reviews| Index: src/ia32/fast-codegen-ia32.cc |
| =================================================================== |
| --- src/ia32/fast-codegen-ia32.cc (revision 3115) |
| +++ src/ia32/fast-codegen-ia32.cc (working copy) |
| @@ -460,4 +460,86 @@ |
| } |
| +void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| + // Compile a short-circuited boolean or operation in a non-test |
| + // context. |
| + ASSERT(expr->op() == Token::OR); |
| + // Compile (e0 || e1) as if it were |
| + // (let (temp = e0) temp ? temp : e1). |
| + |
| + Label eval_right, done; |
| + Location destination = expr->location(); |
| + ASSERT(!destination.is_constant()); |
| + |
| + Expression* left = expr->left(); |
| + Location left_source = left->location(); |
| + ASSERT(!left_source.is_nowhere()); |
| + |
| + Expression* right = expr->right(); |
| + Location right_source = right->location(); |
| + ASSERT(!right_source.is_nowhere()); |
| + |
| + Visit(left); |
| + // Use the shared ToBoolean stub to find the boolean value of the |
| + // left-hand subexpression. Load the value into eax to perform some |
| + // inlined checks assumed by the stub. |
| + if (left_source.is_temporary()) { |
| + if (destination.is_temporary()) { |
| + // Copy the left-hand value into eax because we may need it as the |
| + // final result. |
| + __ mov(eax, Operand(esp, 0)); |
| + } else { |
| + // Pop the left-hand value into eax because we will not need it as the |
| + // final result. |
| + __ pop(eax); |
| + } |
| + } else { |
| + // Load the left-hand value into eax. Put it on the stack if we may |
| + // need it. |
| + ASSERT(left->AsLiteral() != NULL); |
| + __ mov(eax, left->AsLiteral()->handle()); |
| + if (destination.is_temporary()) __ push(eax); |
| + } |
| + // The left-hand value is in eax. It is also on the stack iff the |
| + // destination location is temporary. |
| + |
| + // Perform fast checks assumed by the stub. |
| + __ cmp(eax, Factory::undefined_value()); // The undefined value is false. |
| + __ j(equal, &eval_right); |
| + __ cmp(eax, Factory::true_value()); // True is true. |
| + __ j(equal, &done); |
| + __ cmp(eax, Factory::false_value()); // False is false. |
| + __ j(equal, &eval_right); |
| + ASSERT(kSmiTag == 0); |
| + __ test(eax, Operand(eax)); // The smi zero is false. |
| + __ j(zero, &eval_right); |
| + __ test(eax, Immediate(kSmiTagMask)); // All other smis are true. |
| + __ j(zero, &done); |
| + |
|
fschneider
2009/10/23 08:41:37
Idea: I don't know how relevant these expressions
|
| + // Call the stub for all other cases. |
| + __ push(eax); |
| + ToBooleanStub stub; |
| + __ CallStub(&stub); |
| + __ test(eax, Operand(eax)); // The stub returns nonzero for true. |
| + __ j(not_zero, &done); |
| + |
| + __ bind(&eval_right); |
| + // Discard the left-hand value if present on the stack. |
| + if (destination.is_temporary()) { |
| + __ add(Operand(esp), Immediate(kPointerSize)); |
| + } |
| + Visit(right); |
| + |
| + // Save or discard the right-hand value as needed. |
| + if (destination.is_temporary() && right_source.is_constant()) { |
| + ASSERT(right->AsLiteral() != NULL); |
| + __ push(Immediate(right->AsLiteral()->handle())); |
| + } else if (destination.is_nowhere() && right_source.is_temporary()) { |
| + __ add(Operand(esp), Immediate(kPointerSize)); |
| + } |
| + |
| + __ bind(&done); |
| +} |
| + |
| + |
| } } // namespace v8::internal |