Chromium Code Reviews| Index: src/codegen-ia32.cc |
| =================================================================== |
| --- src/codegen-ia32.cc (revision 1324) |
| +++ src/codegen-ia32.cc (working copy) |
| @@ -4482,31 +4482,63 @@ |
| FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); |
| FloatingPointHelper::LoadFloatOperands(masm, ecx); |
| - Label non_int32_operands, non_smi_result, skip_allocation; |
| - // Reserve space for converted numbers. |
| - __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
| + Label non_smi_result, skip_allocation, operands_too_large; |
| - // Check if right operand is int32. |
| - __ fist_s(Operand(esp, 1 * kPointerSize)); |
| - __ fild_s(Operand(esp, 1 * kPointerSize)); |
| - __ fucompp(); |
| + // Make sure that the operands can be truncated into 64-bit |
| + // integers. Otherwise, the fistt instruction will signal an IA |
| + // exception which will cause us to overwrite the operand with |
| + // zero. |
| + __ push(Immediate(0x7fffffff)); |
| + __ push(Immediate(-1)); |
| + __ fild_d(Operand(esp, 0)); |
| + __ add(Operand(esp), Immediate(2 * kPointerSize)); |
| + |
| + // Convert the operands to absolute values before comparing |
| + // against the limit. |
| + __ fld(2); |
| + __ fabs(); |
| + __ fld(2); |
| + __ fabs(); |
| + |
| + // Do the comparison. If the operands are too large we go |
| + // slow-case through the runtime system. |
| + __ fucomp(2); |
| __ fnstsw_ax(); |
| __ sahf(); |
| - __ j(not_zero, &non_int32_operands); |
| - __ j(parity_even, &non_int32_operands); |
| - |
| - // Check if left operand is int32. |
| - __ fist_s(Operand(esp, 0 * kPointerSize)); |
| - __ fild_s(Operand(esp, 0 * kPointerSize)); |
| + __ j(above, &operands_too_large); |
| __ fucompp(); |
| __ fnstsw_ax(); |
| __ sahf(); |
| - __ j(not_zero, &non_int32_operands); |
| - __ j(parity_even, &non_int32_operands); |
| + __ j(above, &operands_too_large); |
| + // Reserve space for converted numbers. |
| + __ sub(Operand(esp), Immediate(4 * kPointerSize)); |
| + |
| + // Convert right operand to int32. |
| + Label done_right; |
| + __ fnclex(); |
| + __ fisttp_d(Operand(esp, 2 * kPointerSize)); |
|
Erik Corry
2009/02/20 16:40:41
This is an SSE3 instruction :-(. I guess we can s
|
| + __ fnstsw_ax(); |
| + __ test(eax, Immediate(1)); |
| + __ j(zero, &done_right); |
| + __ fnclex(); |
| + __ mov(Operand(esp, 2 * kPointerSize), Immediate(0)); |
| + __ bind(&done_right); |
| + |
| + // Convert left operand to int32. |
| + Label done_left; |
| + __ fisttp_d(Operand(esp, 0 * kPointerSize)); |
| + __ fnstsw_ax(); |
| + __ test(eax, Immediate(1)); |
| + __ j(zero, &done_left); |
| + __ mov(Operand(esp, 0 * kPointerSize), Immediate(0)); |
| + __ bind(&done_left); |
| + |
| // Get int32 operands and perform bitop. |
| __ pop(eax); |
| + __ add(Operand(esp), Immediate(kPointerSize)); |
| __ pop(ecx); |
| + __ add(Operand(esp), Immediate(kPointerSize)); |
| switch (op_) { |
| case Token::BIT_OR: __ or_(eax, Operand(ecx)); break; |
| case Token::BIT_AND: __ and_(eax, Operand(ecx)); break; |
| @@ -4554,10 +4586,11 @@ |
| __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| __ ret(2 * kPointerSize); |
| } |
| - __ bind(&non_int32_operands); |
| - // Restore stacks and operands before calling runtime. |
| + |
| + // Free ST(0) and ST(1) before calling runtime. |
| + __ bind(&operands_too_large); |
| __ ffree(0); |
| - __ add(Operand(esp), Immediate(2 * kPointerSize)); |
| + __ ffree(1); |
| // SHR should return uint32 - go to runtime for non-smi/negative result. |
| if (op_ == Token::SHR) __ bind(&non_smi_result); |