Index: src/ia32/codegen-ia32.cc |
=================================================================== |
--- src/ia32/codegen-ia32.cc (revision 3685) |
+++ src/ia32/codegen-ia32.cc (working copy) |
@@ -741,6 +741,12 @@ |
} |
+enum ArgLocation { |
Kevin Millikin (Chromium)
2010/01/25 16:27:44
It seems like this should be a member of FloatingP
Vladislav Kaznacheev
2010/01/25 17:44:53
Done.
|
+ ARGS_ON_STACK, |
+ ARGS_IN_REGISTERS |
+}; |
+ |
+ |
class FloatingPointHelper : public AllStatic { |
public: |
// Code pattern for loading a floating point value. Input value must |
@@ -750,9 +756,18 @@ |
static void LoadFloatOperand(MacroAssembler* masm, Register number); |
// Code pattern for loading floating point values. Input values must |
// be either smi or heap number objects (fp values). Requirements: |
- // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as |
- // floating point numbers on FPU stack. |
- static void LoadFloatOperands(MacroAssembler* masm, Register scratch); |
+ // operand_1 on TOS+1 or in edx, operand_2 on TOS+2 or in eax. |
+ // Returns operands as floating point numbers on FPU stack. |
+ static void LoadFloatOperands(MacroAssembler* masm, |
+ Register scratch, |
+ ArgLocation arg_location = ARGS_ON_STACK); |
+ |
+ // Similar to LoadFloatOperand but assumes that both operands are smis. |
+ // Accepts operands on stack or in eax, ebx. |
+ static void LoadFloatSmis(MacroAssembler* masm, |
+ Register scratch, |
+ ArgLocation arg_location); |
+ |
// Test if operands are smi or number objects (fp). Requirements: |
// operand_1 in eax, operand_2 in edx; falls through on float |
// operands, jumps to the non_float label otherwise. |
@@ -769,6 +784,12 @@ |
// either operand is not a number. Operands are in edx and eax. |
// Leaves operands unchanged. |
static void LoadSse2Operands(MacroAssembler* masm, Label* not_numbers); |
+ |
+ // Similar to LoadSse2Operands but assumes that both operands are smis. |
+ // Accepts operands on stack or in eax, ebx. |
+ static void LoadSse2Smis(MacroAssembler* masm, |
+ Register scratch, |
+ ArgLocation arg_location); |
}; |
@@ -1331,12 +1352,12 @@ |
__ mov(answer.reg(), left->reg()); |
switch (op) { |
case Token::ADD: |
- __ add(answer.reg(), Operand(right->reg())); // Add optimistically. |
+ __ add(answer.reg(), Operand(right->reg())); |
deferred->Branch(overflow); |
break; |
case Token::SUB: |
- __ sub(answer.reg(), Operand(right->reg())); // Subtract optimistically. |
+ __ sub(answer.reg(), Operand(right->reg())); |
deferred->Branch(overflow); |
break; |
@@ -7056,6 +7077,17 @@ |
void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) { |
+ if (HasArgumentsInRegisters()) { |
+ __ mov(ebx, eax); |
+ __ mov(eax, edx); |
+ } else { |
+ __ mov(ebx, Operand(esp, 1 * kPointerSize)); |
+ __ mov(eax, Operand(esp, 2 * kPointerSize)); |
+ } |
+ |
+ Label not_smis, not_smis_or_overflow, not_smis_undo_optimistic; |
+ Label use_fp_on_smis, done; |
+ |
// Perform fast-case smi code for the operation (eax <op> ebx) and |
// leave result in register eax. |
@@ -7067,12 +7099,12 @@ |
switch (op_) { |
case Token::ADD: |
__ add(eax, Operand(ebx)); // add optimistically |
- __ j(overflow, slow, not_taken); |
+ __ j(overflow, ¬_smis_or_overflow, not_taken); |
break; |
case Token::SUB: |
__ sub(eax, Operand(ebx)); // subtract optimistically |
- __ j(overflow, slow, not_taken); |
+ __ j(overflow, ¬_smis_or_overflow, not_taken); |
break; |
case Token::DIV: |
@@ -7081,7 +7113,7 @@ |
__ cdq(); |
// Check for 0 divisor. |
__ test(ebx, Operand(ebx)); |
- __ j(zero, slow, not_taken); |
+ __ j(zero, ¬_smis_or_overflow, not_taken); |
break; |
default: |
@@ -7092,7 +7124,7 @@ |
// Perform the actual smi check. |
ASSERT(kSmiTag == 0); // adjust zero check if not the case |
__ test(ecx, Immediate(kSmiTagMask)); |
- __ j(not_zero, slow, not_taken); |
+ __ j(not_zero, ¬_smis_undo_optimistic, not_taken); |
switch (op_) { |
case Token::ADD: |
@@ -7108,9 +7140,9 @@ |
// Do multiplication. |
__ imul(eax, Operand(ebx)); // multiplication of smis; result in eax |
// Go slow on overflows. |
- __ j(overflow, slow, not_taken); |
+ __ j(overflow, &use_fp_on_smis, not_taken); |
// Check for negative zero result. |
- __ NegativeZeroTest(eax, ecx, slow); // use ecx = x | y |
+ __ NegativeZeroTest(eax, ecx, &use_fp_on_smis); // use ecx = x | y |
break; |
case Token::DIV: |
@@ -7121,12 +7153,12 @@ |
// by idiv instruction. |
ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
__ cmp(eax, 0x40000000); |
- __ j(equal, slow); |
+ __ j(equal, &use_fp_on_smis); |
// Check for negative zero result. |
- __ NegativeZeroTest(eax, ecx, slow); // use ecx = x | y |
+ __ NegativeZeroTest(eax, ecx, &use_fp_on_smis); // use ecx = x | y |
// Check that the remainder is zero. |
__ test(edx, Operand(edx)); |
- __ j(not_zero, slow); |
+ __ j(not_zero, &use_fp_on_smis); |
// Tag the result and store it in register eax. |
__ SmiTag(eax); |
break; |
@@ -7181,7 +7213,7 @@ |
__ shl_cl(eax); |
// Check that the *signed* result fits in a smi. |
__ cmp(eax, 0xc0000000); |
- __ j(sign, slow, not_taken); |
+ __ j(sign, &use_fp_on_smis, not_taken); |
break; |
default: |
UNREACHABLE(); |
@@ -7194,6 +7226,116 @@ |
UNREACHABLE(); |
break; |
} |
+ GenerateReturn(masm); |
+ |
+ __ bind(¬_smis_or_overflow); |
+ // Revert optimistic operation. |
+ switch (op_) { |
+ case Token::ADD: __ sub(eax, Operand(ebx)); break; |
+ case Token::SUB: __ add(eax, Operand(ebx)); break; |
+ default: break; |
+ } |
+ ASSERT(kSmiTag == 0); // Adjust zero check if not the case. |
+ __ test(ecx, Immediate(kSmiTagMask)); |
+ __ j(not_zero, ¬_smis, not_taken); |
+ // Correct operand values are in eax, ebx at this point. |
+ |
+ __ bind(&use_fp_on_smis); |
+ // Both operands are known to be SMIs but the result does not fit into a SMI. |
+ switch (op_) { |
+ case Token::ADD: |
+ case Token::SUB: |
+ case Token::MUL: |
+ case Token::DIV: { |
+ Label after_alloc_failure; |
+ |
+ ArgLocation arg_location = |
+ (op_ == Token::ADD || op_ == Token::SUB) ? |
+ ARGS_IN_REGISTERS : |
+ ARGS_ON_STACK; |
+ |
+ __ AllocateHeapNumber( |
+ edx, |
+ ecx, |
+ no_reg, |
+ arg_location == ARGS_IN_REGISTERS ? &after_alloc_failure : slow); |
+ |
+ if (CpuFeatures::IsSupported(SSE2)) { |
+ CpuFeatures::Scope use_sse2(SSE2); |
+ FloatingPointHelper::LoadSse2Smis(masm, ecx, arg_location); |
+ 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(); |
+ } |
+ __ movdbl(FieldOperand(edx, HeapNumber::kValueOffset), xmm0); |
+ } else { // SSE2 not available, use FPU. |
+ FloatingPointHelper::LoadFloatSmis(masm, ecx, arg_location); |
+ 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(); |
+ } |
+ __ fstp_d(FieldOperand(edx, HeapNumber::kValueOffset)); |
+ } |
+ __ mov(eax, edx); |
+ GenerateReturn(masm); |
+ |
+ if (HasArgumentsInRegisters()) { |
Kevin Millikin (Chromium)
2010/01/25 16:27:44
Is this right? What if op_ == Token::ADD or Token
Vladislav Kaznacheev
2010/01/25 17:44:53
This was a bug. Fixed.
On 2010/01/25 16:27:44, Kev
|
+ __ bind(&after_alloc_failure); |
+ __ mov(edx, eax); |
+ __ mov(eax, ebx); |
+ __ jmp(slow); |
+ } |
+ } |
Kevin Millikin (Chromium)
2010/01/25 16:27:44
Missing break would be a problem (at least dead co
Vladislav Kaznacheev
2010/01/25 17:44:53
Done.
|
+ case Token::BIT_OR: |
+ case Token::BIT_AND: |
+ case Token::BIT_XOR: |
+ case Token::SAR: |
+ // Do nothing here as these operations always succeed on a pair of smis. |
+ break; |
+ |
+ case Token::MOD: |
+ case Token::SHR: |
+ // Do nothing here as these go directly to runtime. |
+ break; |
+ |
+ case Token::SHL: { |
+ __ AllocateHeapNumber(ebx, ecx, edx, slow); |
+ // Store the result in the HeapNumber and return. |
+ if (CpuFeatures::IsSupported(SSE2)) { |
+ CpuFeatures::Scope use_sse2(SSE2); |
+ __ cvtsi2sd(xmm0, Operand(eax)); |
+ __ movdbl(FieldOperand(ebx, HeapNumber::kValueOffset), xmm0); |
+ } else { |
+ __ mov(Operand(esp, 1 * kPointerSize), eax); |
+ __ fild_s(Operand(esp, 1 * kPointerSize)); |
+ __ fstp_d(FieldOperand(ebx, HeapNumber::kValueOffset)); |
+ } |
+ __ mov(eax, ebx); |
+ GenerateReturn(masm); |
+ break; |
+ } |
+ |
+ default: UNREACHABLE(); break; |
+ } |
+ |
+ __ bind(¬_smis_undo_optimistic); |
+ switch (op_) { |
+ case Token::ADD: __ sub(eax, Operand(ebx)); break; |
+ case Token::SUB: __ add(eax, Operand(ebx)); break; |
+ default: break; |
+ } |
+ |
+ __ bind(¬_smis); |
+ __ mov(edx, eax); |
+ __ mov(eax, ebx); |
+ |
+ __ bind(&done); |
} |
@@ -7206,27 +7348,17 @@ |
// case smi code is not generated by the caller. Generating it here will speed |
// up common operations. |
if (HasSmiCodeInStub()) { |
- Label slow; |
- __ mov(ebx, Operand(esp, 1 * kPointerSize)); |
- __ mov(eax, Operand(esp, 2 * kPointerSize)); |
- GenerateSmiCode(masm, &slow); |
- GenerateReturn(masm); |
- // Too bad. The fast case smi code didn't succeed. |
- __ bind(&slow); |
+ GenerateSmiCode(masm, &call_runtime); |
+ } else if (op_ != Token::MOD) { // MOD goes straight to runtime. |
+ GenerateLoadArguments(masm); |
} |
- // Make sure the arguments are in edx and eax. |
- GenerateLoadArguments(masm); |
- |
// Floating point case. |
switch (op_) { |
case Token::ADD: |
case Token::SUB: |
case Token::MUL: |
case Token::DIV: { |
- // eax: y |
- // edx: x |
- |
if (CpuFeatures::IsSupported(SSE2)) { |
CpuFeatures::Scope use_sse2(SSE2); |
FloatingPointHelper::LoadSse2Operands(masm, &call_runtime); |
@@ -7238,59 +7370,12 @@ |
case Token::DIV: __ divsd(xmm0, xmm1); break; |
default: UNREACHABLE(); |
} |
- // Allocate a heap number, if needed. |
- Label skip_allocation; |
- switch (mode_) { |
- case OVERWRITE_LEFT: |
- __ mov(eax, Operand(edx)); |
- // Fall through! |
- case OVERWRITE_RIGHT: |
- // If the argument in eax is already an object, we skip the |
- // allocation of a heap number. |
- __ test(eax, Immediate(kSmiTagMask)); |
- __ j(not_zero, &skip_allocation, not_taken); |
- // Fall through! |
- case NO_OVERWRITE: { |
- // Allocate a heap number for the result. Keep eax and edx intact |
- // for the possible runtime call. |
- __ AllocateHeapNumber(ebx, ecx, no_reg, &call_runtime); |
- // Now eax can be overwritten losing one of the arguments as we are |
- // now done and will not need it any more. |
- __ mov(eax, ebx); |
- __ bind(&skip_allocation); |
- break; |
- } |
- default: UNREACHABLE(); |
- } |
+ GenerateHeapResultAllocation(masm, &call_runtime); |
__ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
GenerateReturn(masm); |
} else { // SSE2 not available, use FPU. |
FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); |
- // Allocate a heap number, if needed. |
- Label skip_allocation; |
- switch (mode_) { |
- case OVERWRITE_LEFT: |
- __ mov(eax, Operand(edx)); |
- // Fall through! |
- case OVERWRITE_RIGHT: |
- // If the argument in eax is already an object, we skip the |
- // allocation of a heap number. |
- __ test(eax, Immediate(kSmiTagMask)); |
- __ j(not_zero, &skip_allocation, not_taken); |
- // Fall through! |
- case NO_OVERWRITE: |
- // Allocate a heap number for the result. Keep eax and edx intact |
- // for the possible runtime call. |
- __ AllocateHeapNumber(ebx, ecx, no_reg, &call_runtime); |
- // Now eax can be overwritten losing one of the arguments as we are |
- // now done and will not need it any more. |
- __ mov(eax, ebx); |
- __ bind(&skip_allocation); |
- break; |
- default: UNREACHABLE(); |
- } |
- FloatingPointHelper::LoadFloatOperands(masm, ecx); |
- |
+ FloatingPointHelper::LoadFloatOperands(masm, ecx, ARGS_IN_REGISTERS); |
switch (op_) { |
case Token::ADD: __ faddp(1); break; |
case Token::SUB: __ fsubp(1); break; |
@@ -7298,8 +7383,13 @@ |
case Token::DIV: __ fdivp(1); break; |
default: UNREACHABLE(); |
} |
+ Label after_alloc_failure; |
+ GenerateHeapResultAllocation(masm, &after_alloc_failure); |
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
GenerateReturn(masm); |
+ __ bind(&after_alloc_failure); |
+ __ ffree(); |
+ __ jmp(&call_runtime); |
} |
} |
case Token::MOD: { |
@@ -7312,12 +7402,8 @@ |
case Token::SAR: |
case Token::SHL: |
case Token::SHR: { |
- Label non_smi_result, skip_allocation; |
- Label operand_conversion_failure; |
- FloatingPointHelper::LoadAsIntegers( |
- masm, |
- use_sse3_, |
- &operand_conversion_failure); |
+ Label non_smi_result; |
+ FloatingPointHelper::LoadAsIntegers(masm, use_sse3_, &call_runtime); |
switch (op_) { |
case Token::BIT_OR: __ or_(eax, Operand(ecx)); break; |
case Token::BIT_AND: __ and_(eax, Operand(ecx)); break; |
@@ -7330,7 +7416,7 @@ |
if (op_ == Token::SHR) { |
// Check if result is non-negative and fits in a smi. |
__ test(eax, Immediate(0xc0000000)); |
- __ j(not_zero, &non_smi_result); |
+ __ j(not_zero, &call_runtime); |
} else { |
// Check if result fits in a smi. |
__ cmp(eax, 0xc0000000); |
@@ -7345,6 +7431,7 @@ |
__ bind(&non_smi_result); |
// Allocate a heap number if needed. |
__ mov(ebx, Operand(eax)); // ebx: result |
+ Label skip_allocation; |
switch (mode_) { |
case OVERWRITE_LEFT: |
case OVERWRITE_RIGHT: |
@@ -7373,15 +7460,6 @@ |
} |
GenerateReturn(masm); |
} |
- |
- // Go to runtime for non-number inputs. |
- __ bind(&operand_conversion_failure); |
- // SHR should return uint32 - go to runtime for non-smi/negative result. |
- if (op_ == Token::SHR) { |
- __ bind(&non_smi_result); |
- } |
- __ mov(eax, Operand(esp, 1 * kPointerSize)); |
- __ mov(edx, Operand(esp, 2 * kPointerSize)); |
break; |
} |
default: UNREACHABLE(); break; |
@@ -7407,17 +7485,15 @@ |
// Test for string arguments before calling runtime. |
Label not_strings, not_string1, string1; |
Result answer; |
- __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. |
- __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. |
- __ test(eax, Immediate(kSmiTagMask)); |
+ __ test(edx, Immediate(kSmiTagMask)); |
__ j(zero, ¬_string1); |
- __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, eax); |
+ __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ecx); |
__ j(above_equal, ¬_string1); |
- // First argument is a a string, test second. |
- __ test(edx, Immediate(kSmiTagMask)); |
+ // First argument is a string, test second. |
+ __ test(eax, Immediate(kSmiTagMask)); |
__ j(zero, &string1); |
- __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, edx); |
+ __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx); |
__ j(above_equal, &string1); |
// First and second argument are strings. Jump to the string add stub. |
@@ -7426,17 +7502,25 @@ |
// Only first argument is a string. |
__ bind(&string1); |
- __ InvokeBuiltin(Builtins::STRING_ADD_LEFT, JUMP_FUNCTION); |
+ __ InvokeBuiltin( |
+ HasArgumentsReversed() ? |
Mads Ager (chromium)
2010/01/25 15:44:03
Indent by one more space. Looks like 3-space inden
Vladislav Kaznacheev
2010/01/25 16:24:47
Done.
|
+ Builtins::STRING_ADD_RIGHT : |
+ Builtins::STRING_ADD_LEFT, |
+ JUMP_FUNCTION); |
// First argument was not a string, test second. |
__ bind(¬_string1); |
- __ test(edx, Immediate(kSmiTagMask)); |
+ __ test(eax, Immediate(kSmiTagMask)); |
__ j(zero, ¬_strings); |
- __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, edx); |
+ __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx); |
__ j(above_equal, ¬_strings); |
// Only second argument is a string. |
- __ InvokeBuiltin(Builtins::STRING_ADD_RIGHT, JUMP_FUNCTION); |
+ __ InvokeBuiltin( |
+ HasArgumentsReversed() ? |
Mads Ager (chromium)
2010/01/25 15:44:03
Indent by one more space.
Vladislav Kaznacheev
2010/01/25 16:24:47
Done.
|
+ Builtins::STRING_ADD_LEFT : |
+ Builtins::STRING_ADD_RIGHT, |
+ JUMP_FUNCTION); |
__ bind(¬_strings); |
// Neither argument is a string. |
@@ -7448,7 +7532,7 @@ |
break; |
case Token::MUL: |
__ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION); |
- break; |
+ break; |
case Token::DIV: |
__ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION); |
break; |
@@ -7479,6 +7563,53 @@ |
} |
+void GenericBinaryOpStub::GenerateHeapResultAllocation(MacroAssembler* masm, |
+ Label* alloc_failure) { |
+ Label skip_allocation; |
+ OverwriteMode mode = mode_; |
+ if (HasArgumentsReversed()) { |
+ if (mode == OVERWRITE_RIGHT) |
Mads Ager (chromium)
2010/01/25 15:44:03
Please uses '{' and '}' when having multi-line if
Vladislav Kaznacheev
2010/01/25 16:24:47
Done.
|
+ mode = OVERWRITE_LEFT; |
+ else if (mode == OVERWRITE_LEFT) |
+ mode = OVERWRITE_RIGHT; |
+ } |
+ switch (mode) { |
+ case OVERWRITE_LEFT: { |
+ // If the argument in edx is already an object, we skip the |
+ // allocation of a heap number. |
+ __ test(edx, Immediate(kSmiTagMask)); |
+ __ j(not_zero, &skip_allocation, not_taken); |
+ // Allocate a heap number for the result. Keep eax and edx intact |
+ // for the possible runtime call. |
+ __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure); |
+ // Now edx can be overwritten losing one of the arguments as we are |
+ // now done and will not need it any more. |
+ __ mov(edx, Operand(ebx)); |
+ __ bind(&skip_allocation); |
+ // Use object in edx as a result holder |
+ __ mov(eax, Operand(edx)); |
+ break; |
+ } |
+ case OVERWRITE_RIGHT: |
+ // If the argument in eax is already an object, we skip the |
+ // allocation of a heap number. |
+ __ test(eax, Immediate(kSmiTagMask)); |
+ __ j(not_zero, &skip_allocation, not_taken); |
+ // Fall through! |
+ case NO_OVERWRITE: |
+ // Allocate a heap number for the result. Keep eax and edx intact |
+ // for the possible runtime call. |
+ __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure); |
+ // Now eax can be overwritten losing one of the arguments as we are |
+ // now done and will not need it any more. |
+ __ mov(eax, ebx); |
+ __ bind(&skip_allocation); |
+ break; |
+ default: UNREACHABLE(); |
+ } |
+} |
+ |
+ |
void GenericBinaryOpStub::GenerateLoadArguments(MacroAssembler* masm) { |
// If arguments are not passed in registers read them from the stack. |
if (!HasArgumentsInRegisters()) { |
@@ -7741,16 +7872,47 @@ |
} |
+void FloatingPointHelper::LoadSse2Smis(MacroAssembler* masm, |
+ Register scratch, |
+ ArgLocation arg_location) { |
+ if (arg_location == ARGS_IN_REGISTERS) { |
+ __ mov(scratch, eax); |
+ } else { |
+ __ mov(scratch, Operand(esp, 2 * kPointerSize)); |
+ } |
+ __ SmiUntag(scratch); // Untag smi before converting to float. |
+ __ cvtsi2sd(xmm0, Operand(scratch)); |
+ |
+ |
+ if (arg_location == ARGS_IN_REGISTERS) { |
+ __ mov(scratch, ebx); |
+ } else { |
+ __ mov(scratch, Operand(esp, 1 * kPointerSize)); |
+ } |
+ __ SmiUntag(scratch); // Untag smi before converting to float. |
+ __ cvtsi2sd(xmm1, Operand(scratch)); |
+} |
+ |
+ |
void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, |
- Register scratch) { |
+ Register scratch, |
+ ArgLocation arg_location) { |
Label load_smi_1, load_smi_2, done_load_1, done; |
- __ mov(scratch, Operand(esp, 2 * kPointerSize)); |
+ if (arg_location == ARGS_IN_REGISTERS) { |
+ __ mov(scratch, edx); |
+ } else { |
+ __ mov(scratch, Operand(esp, 2 * kPointerSize)); |
+ } |
__ test(scratch, Immediate(kSmiTagMask)); |
__ j(zero, &load_smi_1, not_taken); |
__ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); |
__ bind(&done_load_1); |
- __ mov(scratch, Operand(esp, 1 * kPointerSize)); |
+ if (arg_location == ARGS_IN_REGISTERS) { |
+ __ mov(scratch, eax); |
+ } else { |
+ __ mov(scratch, Operand(esp, 1 * kPointerSize)); |
+ } |
__ test(scratch, Immediate(kSmiTagMask)); |
__ j(zero, &load_smi_2, not_taken); |
__ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); |
@@ -7773,6 +7935,31 @@ |
} |
+void FloatingPointHelper::LoadFloatSmis(MacroAssembler* masm, |
+ Register scratch, |
+ ArgLocation arg_location) { |
+ if (arg_location == ARGS_IN_REGISTERS) { |
+ __ mov(scratch, eax); |
+ } else { |
+ __ mov(scratch, Operand(esp, 2 * kPointerSize)); |
+ } |
+ __ SmiUntag(scratch); |
+ __ push(scratch); |
+ __ fild_s(Operand(esp, 0)); |
+ __ pop(scratch); |
+ |
+ if (arg_location == ARGS_IN_REGISTERS) { |
+ __ mov(scratch, ebx); |
+ } else { |
+ __ mov(scratch, Operand(esp, 1 * kPointerSize)); |
+ } |
+ __ SmiUntag(scratch); |
+ __ push(scratch); |
+ __ fild_s(Operand(esp, 0)); |
+ __ pop(scratch); |
+} |
+ |
+ |
void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, |
Label* non_float, |
Register scratch) { |