| Index: src/ia32/code-stubs-ia32.cc
|
| diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
|
| index 471114cbe4f219e04cb4b921de79326f6d3bebff..229e8fc536599476abb765d3f82835cab8a3e455 100644
|
| --- a/src/ia32/code-stubs-ia32.cc
|
| +++ b/src/ia32/code-stubs-ia32.cc
|
| @@ -1681,6 +1681,11 @@ void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
|
| }
|
|
|
|
|
| +// Input:
|
| +// edx: left operand (tagged)
|
| +// eax: right operand (tagged)
|
| +// Output:
|
| +// eax: result (tagged)
|
| void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
| Label call_runtime;
|
| ASSERT(operands_type_ == BinaryOpIC::INT32);
|
| @@ -1690,31 +1695,37 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
| case Token::ADD:
|
| case Token::SUB:
|
| case Token::MUL:
|
| - case Token::DIV: {
|
| + case Token::DIV:
|
| + case Token::MOD: {
|
| Label not_floats;
|
| Label not_int32;
|
| if (CpuFeatures::IsSupported(SSE2)) {
|
| CpuFeatures::Scope use_sse2(SSE2);
|
| FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats);
|
| FloatingPointHelper::CheckSSE2OperandsAreInt32(masm, ¬_int32, ecx);
|
| - switch (op_) {
|
| - case Token::ADD: __ addsd(xmm0, xmm1); break;
|
| - case Token::SUB: __ subsd(xmm0, xmm1); break;
|
| - case Token::MUL: __ mulsd(xmm0, xmm1); break;
|
| - case Token::DIV: __ divsd(xmm0, xmm1); break;
|
| - default: UNREACHABLE();
|
| - }
|
| - // Check result type if it is currently Int32.
|
| - if (result_type_ <= BinaryOpIC::INT32) {
|
| - __ cvttsd2si(ecx, Operand(xmm0));
|
| - __ cvtsi2sd(xmm2, ecx);
|
| - __ ucomisd(xmm0, xmm2);
|
| - __ j(not_zero, ¬_int32);
|
| - __ j(carry, ¬_int32);
|
| + if (op_ == Token::MOD) {
|
| + GenerateRegisterArgsPush(masm);
|
| + __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION);
|
| + } else {
|
| + switch (op_) {
|
| + case Token::ADD: __ addsd(xmm0, xmm1); break;
|
| + case Token::SUB: __ subsd(xmm0, xmm1); break;
|
| + case Token::MUL: __ mulsd(xmm0, xmm1); break;
|
| + case Token::DIV: __ divsd(xmm0, xmm1); break;
|
| + default: UNREACHABLE();
|
| + }
|
| + // Check result type if it is currently Int32.
|
| + if (result_type_ <= BinaryOpIC::INT32) {
|
| + __ cvttsd2si(ecx, Operand(xmm0));
|
| + __ cvtsi2sd(xmm2, ecx);
|
| + __ ucomisd(xmm0, xmm2);
|
| + __ j(not_zero, ¬_int32);
|
| + __ j(carry, ¬_int32);
|
| + }
|
| + GenerateHeapResultAllocation(masm, &call_runtime);
|
| + __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
|
| + __ ret(0);
|
| }
|
| - GenerateHeapResultAllocation(masm, &call_runtime);
|
| - __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
|
| - __ ret(0);
|
| } else { // SSE2 not available, use FPU.
|
| FloatingPointHelper::CheckFloatOperands(masm, ¬_floats, ebx);
|
| FloatingPointHelper::LoadFloatOperands(
|
| @@ -1722,20 +1733,25 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
| ecx,
|
| FloatingPointHelper::ARGS_IN_REGISTERS);
|
| FloatingPointHelper::CheckFloatOperandsAreInt32(masm, ¬_int32);
|
| - switch (op_) {
|
| - case Token::ADD: __ faddp(1); break;
|
| - case Token::SUB: __ fsubp(1); break;
|
| - case Token::MUL: __ fmulp(1); break;
|
| - case Token::DIV: __ fdivp(1); break;
|
| - default: UNREACHABLE();
|
| + if (op_ == Token::MOD) {
|
| + GenerateRegisterArgsPush(masm);
|
| + __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION);
|
| + } else {
|
| + switch (op_) {
|
| + case Token::ADD: __ faddp(1); break;
|
| + case Token::SUB: __ fsubp(1); break;
|
| + case Token::MUL: __ fmulp(1); break;
|
| + case Token::DIV: __ fdivp(1); break;
|
| + default: UNREACHABLE();
|
| + }
|
| + Label after_alloc_failure;
|
| + GenerateHeapResultAllocation(masm, &after_alloc_failure);
|
| + __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
| + __ ret(0);
|
| + __ bind(&after_alloc_failure);
|
| + __ fstp(0); // Pop FPU stack before calling runtime.
|
| + __ jmp(&call_runtime);
|
| }
|
| - Label after_alloc_failure;
|
| - GenerateHeapResultAllocation(masm, &after_alloc_failure);
|
| - __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
| - __ ret(0);
|
| - __ bind(&after_alloc_failure);
|
| - __ fstp(0); // Pop FPU stack before calling runtime.
|
| - __ jmp(&call_runtime);
|
| }
|
|
|
| __ bind(¬_floats);
|
| @@ -1744,10 +1760,6 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
| break;
|
| }
|
|
|
| - case Token::MOD: {
|
| - // For MOD we go directly to runtime in the non-smi case.
|
| - break;
|
| - }
|
| case Token::BIT_OR:
|
| case Token::BIT_AND:
|
| case Token::BIT_XOR:
|
| @@ -1758,11 +1770,6 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
| Label not_floats;
|
| Label not_int32;
|
| Label non_smi_result;
|
| - /* {
|
| - CpuFeatures::Scope use_sse2(SSE2);
|
| - FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats);
|
| - FloatingPointHelper::CheckSSE2OperandsAreInt32(masm, ¬_int32, ecx);
|
| - }*/
|
| FloatingPointHelper::LoadUnknownsAsIntegers(masm,
|
| use_sse3_,
|
| ¬_floats);
|
| @@ -1833,8 +1840,8 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
| default: UNREACHABLE(); break;
|
| }
|
|
|
| - // If an allocation fails, or SHR or MOD hit a hard case,
|
| - // use the runtime system to get the correct result.
|
| + // If an allocation fails, or SHR hits a hard case, use the runtime system to
|
| + // get the correct result.
|
| __ bind(&call_runtime);
|
|
|
| switch (op_) {
|
| @@ -1855,8 +1862,6 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
| __ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION);
|
| break;
|
| case Token::MOD:
|
| - GenerateRegisterArgsPush(masm);
|
| - __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION);
|
| break;
|
| case Token::BIT_OR:
|
| __ InvokeBuiltin(Builtins::BIT_OR, JUMP_FUNCTION);
|
|
|