| Index: src/ia32/codegen-ia32.cc
|
| ===================================================================
|
| --- src/ia32/codegen-ia32.cc (revision 2163)
|
| +++ src/ia32/codegen-ia32.cc (working copy)
|
| @@ -714,6 +714,11 @@
|
|
|
| class FloatingPointHelper : public AllStatic {
|
| public:
|
| + // Code pattern for loading a floating point value. Input value must
|
| + // be either a smi or a heap number object (fp value). Requirements:
|
| + // operand on TOS+1. Returns operand as floating point number on FPU
|
| + // stack.
|
| + static void LoadFloatOperand(MacroAssembler* masm, Register scratch);
|
| // 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
|
| @@ -730,7 +735,8 @@
|
| static void AllocateHeapNumber(MacroAssembler* masm,
|
| Label* need_gc,
|
| Register scratch1,
|
| - Register scratch2);
|
| + Register scratch2,
|
| + Register result);
|
| };
|
|
|
|
|
| @@ -4943,6 +4949,76 @@
|
| }
|
|
|
|
|
| +void CodeGenerator::GenerateFastMathOp(MathOp op, ZoneList<Expression*>* args) {
|
| + JumpTarget done;
|
| + JumpTarget call_runtime;
|
| + ASSERT(args->length() == 1);
|
| +
|
| + // Load number and duplicate it.
|
| + Load(args->at(0));
|
| + frame_->Dup();
|
| +
|
| + // Get the number into an unaliased register and load it onto the
|
| + // floating point stack still leaving one copy on the frame.
|
| + Result number = frame_->Pop();
|
| + number.ToRegister();
|
| + frame_->Spill(number.reg());
|
| + FloatingPointHelper::LoadFloatOperand(masm_, number.reg());
|
| + number.Unuse();
|
| +
|
| + // Perform the operation on the number.
|
| + switch (op) {
|
| + case SIN:
|
| + __ fsin();
|
| + break;
|
| + case COS:
|
| + __ fcos();
|
| + break;
|
| + }
|
| +
|
| + // Go slow case if argument to operation is out of range.
|
| + __ fnstsw_ax();
|
| + __ sahf();
|
| + call_runtime.Branch(parity_even, not_taken);
|
| +
|
| + // Allocate heap number for result if possible.
|
| + Result scratch1 = allocator()->Allocate();
|
| + Result scratch2 = allocator()->Allocate();
|
| + Result heap_number = allocator()->Allocate();
|
| + FloatingPointHelper::AllocateHeapNumber(masm_,
|
| + call_runtime.entry_label(),
|
| + scratch1.reg(),
|
| + scratch2.reg(),
|
| + heap_number.reg());
|
| + scratch1.Unuse();
|
| + scratch2.Unuse();
|
| +
|
| + // Store the result in the allocated heap number.
|
| + __ fstp_d(FieldOperand(heap_number.reg(), HeapNumber::kValueOffset));
|
| + // Pop the extra copy of the argument.
|
| + frame_->Pop();
|
| + // Push the result on the frame.
|
| + frame_->Push(&heap_number);
|
| + heap_number.Unuse();
|
| + done.Jump();
|
| +
|
| + call_runtime.Bind();
|
| + // Free ST(0) which was not popped before calling into the runtime.
|
| + __ ffree(0);
|
| + Result answer;
|
| + switch (op) {
|
| + case SIN:
|
| + answer = frame_->CallRuntime(Runtime::kMath_sin, 1);
|
| + break;
|
| + case COS:
|
| + answer = frame_->CallRuntime(Runtime::kMath_cos, 1);
|
| + break;
|
| + }
|
| + frame_->Push(&answer);
|
| + done.Bind();
|
| +}
|
| +
|
| +
|
| void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
|
| if (CheckForInlineRuntimeCall(node)) {
|
| return;
|
| @@ -6446,7 +6522,8 @@
|
| FloatingPointHelper::AllocateHeapNumber(masm,
|
| &call_runtime,
|
| ecx,
|
| - edx);
|
| + edx,
|
| + eax);
|
| __ bind(&skip_allocation);
|
| break;
|
| default: UNREACHABLE();
|
| @@ -6554,7 +6631,7 @@
|
| // Fall through!
|
| case NO_OVERWRITE:
|
| FloatingPointHelper::AllocateHeapNumber(masm, &call_runtime,
|
| - ecx, edx);
|
| + ecx, edx, eax);
|
| __ bind(&skip_allocation);
|
| break;
|
| default: UNREACHABLE();
|
| @@ -6639,25 +6716,45 @@
|
| void FloatingPointHelper::AllocateHeapNumber(MacroAssembler* masm,
|
| Label* need_gc,
|
| Register scratch1,
|
| - Register scratch2) {
|
| + Register scratch2,
|
| + Register result) {
|
| ExternalReference allocation_top =
|
| ExternalReference::new_space_allocation_top_address();
|
| ExternalReference allocation_limit =
|
| ExternalReference::new_space_allocation_limit_address();
|
| __ mov(Operand(scratch1), Immediate(allocation_top));
|
| - __ mov(eax, Operand(scratch1, 0));
|
| - __ lea(scratch2, Operand(eax, HeapNumber::kSize)); // scratch2: new top
|
| + __ mov(result, Operand(scratch1, 0));
|
| + __ lea(scratch2, Operand(result, HeapNumber::kSize)); // scratch2: new top
|
| __ cmp(scratch2, Operand::StaticVariable(allocation_limit));
|
| __ j(above, need_gc, not_taken);
|
|
|
| __ mov(Operand(scratch1, 0), scratch2); // store new top
|
| - __ mov(Operand(eax, HeapObject::kMapOffset),
|
| + __ mov(Operand(result, HeapObject::kMapOffset),
|
| Immediate(Factory::heap_number_map()));
|
| // Tag old top and use as result.
|
| - __ add(Operand(eax), Immediate(kHeapObjectTag));
|
| + __ add(Operand(result), Immediate(kHeapObjectTag));
|
| }
|
|
|
|
|
| +void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
|
| + Register scratch) {
|
| + Label load_smi, done;
|
| +
|
| + __ test(scratch, Immediate(kSmiTagMask));
|
| + __ j(zero, &load_smi, not_taken);
|
| + __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset));
|
| + __ jmp(&done);
|
| +
|
| + __ bind(&load_smi);
|
| + __ sar(scratch, kSmiTagSize);
|
| + __ push(scratch);
|
| + __ fild_s(Operand(esp, 0));
|
| + __ pop(scratch);
|
| +
|
| + __ bind(&done);
|
| +}
|
| +
|
| +
|
| void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
|
| Register scratch) {
|
| Label load_smi_1, load_smi_2, done_load_1, done;
|
| @@ -6763,7 +6860,7 @@
|
| } else {
|
| __ mov(edx, Operand(eax));
|
| // edx: operand
|
| - FloatingPointHelper::AllocateHeapNumber(masm, &undo, ebx, ecx);
|
| + FloatingPointHelper::AllocateHeapNumber(masm, &undo, ebx, ecx, eax);
|
| // eax: allocated 'empty' number
|
| __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset));
|
| __ xor_(ecx, HeapNumber::kSignMask); // Flip sign.
|
|
|