Commit f1b908d5 authored by olivf@chromium.org's avatar olivf@chromium.org

Move ToInt conversions to the MacroAssembler for x64

+ Prevent truncating TaggedToI from bailing out.

(This is a port of r16464)

BUG=
R=titzer@chromium.org

Review URL: https://codereview.chromium.org/23938003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16615 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 7f0f84c0
......@@ -471,8 +471,8 @@ bool LCodeGen::GenerateDeferredCode() {
Comment(";;; Deferred code");
}
code->Generate();
__ bind(code->done());
if (NeedsDeferredFrame()) {
__ bind(code->done());
Comment(";;; Destroy frame");
ASSERT(frame_is_built_);
frame_is_built_ = false;
......
......@@ -551,7 +551,7 @@ class LDeferredCode : public ZoneObject {
void SetExit(Label* exit) { external_exit_ = exit; }
Label* entry() { return &entry_; }
Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
Label* done() { return &done_; }
Label* done() { return codegen_->NeedsDeferredFrame() ? &done_ : exit(); }
int instruction_index() const { return instruction_index_; }
const LCodeGen::X87Stack& x87_stack() const { return x87_stack_; }
......
......@@ -282,20 +282,25 @@ void MacroAssembler::DoubleToI(Register result_reg,
Label* conversion_failed,
Label::Distance dst) {
ASSERT(!input_reg.is(scratch));
Label done;
cvttsd2si(result_reg, Operand(input_reg));
cvtsi2sd(scratch, Operand(result_reg));
ucomisd(scratch, input_reg);
j(not_equal, conversion_failed, dst);
j(parity_even, conversion_failed, dst); // NaN.
if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
Label done;
// The integer converted back is equal to the original. We
// only have to test if we got -0 as an input.
test(result_reg, Operand(result_reg));
j(not_zero, &done, Label::kNear);
movmskpd(result_reg, input_reg);
// Bit 0 contains the sign of the double in input_reg.
// If input was positive, we are ok and return 0, otherwise
// jump to conversion_failed.
and_(result_reg, 1);
j(not_zero, conversion_failed, dst);
bind(&done);
}
bind(&done);
}
......
......@@ -1136,6 +1136,7 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
const bool tagged = (argument_type_ == TAGGED);
if (tagged) {
Label input_not_smi, loaded;
// Test that rax is a number.
StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
__ movq(rax, args.GetArgumentOperand(0));
......@@ -1153,14 +1154,7 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
__ jmp(&loaded, Label::kNear);
__ bind(&input_not_smi);
// Check if input is a HeapNumber.
__ LoadRoot(rbx, Heap::kHeapNumberMapRootIndex);
__ cmpq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
__ j(not_equal, &runtime_call);
// Input is a HeapNumber. Push it on the FPU stack and load its
// bits into rbx.
__ fld_d(FieldOperand(rax, HeapNumber::kValueOffset));
__ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
__ TaggedToI(rbx, rax, xmm1, TREAT_MINUS_ZERO_AS_ZERO, &runtime_call);
__ movq(rdx, rbx);
__ bind(&loaded);
......@@ -1446,10 +1440,8 @@ void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
__ bind(&arg1_is_object);
__ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map);
__ j(not_equal, &check_undefined_arg1);
// Get the untagged integer version of the rdx heap number in rcx.
DoubleToIStub stub1(rdx, r8, HeapNumber::kValueOffset - kHeapObjectTag,
true);
__ call(stub1.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
// Get the untagged integer version of the rdx heap number in r8.
__ TruncateHeapNumberToI(r8, rdx);
// Here r8 has the untagged integer, rax has a Smi or a heap number.
__ bind(&load_arg2);
......@@ -1469,9 +1461,7 @@ void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
__ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map);
__ j(not_equal, &check_undefined_arg2);
// Get the untagged integer version of the rax heap number in rcx.
DoubleToIStub stub2(rax, rcx, HeapNumber::kValueOffset - kHeapObjectTag,
true);
__ call(stub2.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
__ TruncateHeapNumberToI(rcx, rax);
__ bind(&done);
__ movl(rax, r8);
......@@ -1648,16 +1638,17 @@ void MathPowStub::Generate(MacroAssembler* masm) {
}
if (exponent_type_ != INTEGER) {
Label fast_power;
Label fast_power, try_arithmetic_simplification;
// Detect integer exponents stored as double.
__ DoubleToI(exponent, double_exponent, double_scratch,
TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification);
__ jmp(&int_exponent);
__ bind(&try_arithmetic_simplification);
__ cvttsd2si(exponent, double_exponent);
// Skip to runtime if possibly NaN (indicated by the indefinite integer).
__ cmpl(exponent, Immediate(0x80000000u));
__ j(equal, &call_runtime);
__ cvtlsi2sd(double_scratch, exponent);
// Already ruled out NaNs for exponent.
__ ucomisd(double_exponent, double_scratch);
__ j(equal, &int_exponent);
if (exponent_type_ == ON_STACK) {
// Detect square root case. Crankshaft detects constant +/-0.5 at
......
......@@ -373,6 +373,7 @@ bool LCodeGen::GenerateDeferredCode() {
}
code->Generate();
if (NeedsDeferredFrame()) {
__ bind(code->done());
Comment(";;; Destroy frame");
ASSERT(frame_is_built_);
frame_is_built_ = false;
......@@ -4698,50 +4699,35 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
}
void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
Label done, heap_number;
void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
Label heap_number;
Register input_reg = ToRegister(instr->value());
// Heap number map check.
__ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex);
if (instr->truncating()) {
// Heap number map check.
__ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex);
__ j(equal, &heap_number, Label::kNear);
// Check for undefined. Undefined is converted to zero for truncating
// conversions.
__ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
DeoptimizeIf(not_equal, instr->environment());
__ Set(input_reg, 0);
__ jmp(&done, Label::kNear);
__ jmp(done);
__ bind(&heap_number);
__ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
__ cvttsd2siq(input_reg, xmm0);
__ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000));
__ cmpq(input_reg, kScratchRegister);
DeoptimizeIf(equal, instr->environment());
__ TruncateHeapNumberToI(input_reg, input_reg);
} else {
// Deoptimize if we don't have a heap number.
DeoptimizeIf(not_equal, instr->environment());
Label bailout;
XMMRegister xmm_temp = ToDoubleRegister(instr->temp());
__ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
__ cvttsd2si(input_reg, xmm0);
__ cvtlsi2sd(xmm_temp, input_reg);
__ ucomisd(xmm0, xmm_temp);
DeoptimizeIf(not_equal, instr->environment());
DeoptimizeIf(parity_even, instr->environment()); // NaN.
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ testl(input_reg, input_reg);
__ j(not_zero, &done);
__ movmskpd(input_reg, xmm0);
__ andl(input_reg, Immediate(1));
DeoptimizeIf(not_zero, instr->environment());
}
__ TaggedToI(input_reg, input_reg, xmm_temp,
instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear);
__ jmp(done);
__ bind(&bailout);
DeoptimizeIf(no_condition, instr->environment());
}
__ bind(&done);
}
......@@ -4751,7 +4737,7 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
: LDeferredCode(codegen), instr_(instr) { }
virtual void Generate() V8_OVERRIDE {
codegen()->DoDeferredTaggedToI(instr_);
codegen()->DoDeferredTaggedToI(instr_, done());
}
virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
private:
......@@ -4801,34 +4787,16 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
Register result_reg = ToRegister(result);
if (instr->truncating()) {
// Performs a truncating conversion of a floating point number as used by
// the JS bitwise operations.
__ cvttsd2siq(result_reg, input_reg);
__ movq(kScratchRegister,
V8_INT64_C(0x8000000000000000),
RelocInfo::NONE64);
__ cmpq(result_reg, kScratchRegister);
DeoptimizeIf(equal, instr->environment());
__ TruncateDoubleToI(result_reg, input_reg);
} else {
__ cvttsd2si(result_reg, input_reg);
__ cvtlsi2sd(xmm0, result_reg);
__ ucomisd(xmm0, input_reg);
DeoptimizeIf(not_equal, instr->environment());
DeoptimizeIf(parity_even, instr->environment()); // NaN.
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label done;
// The integer converted back is equal to the original. We
// only have to test if we got -0 as an input.
__ testl(result_reg, result_reg);
__ j(not_zero, &done, Label::kNear);
__ movmskpd(result_reg, input_reg);
// Bit 0 contains the sign of the double in input_reg.
// If input was positive, we are ok and return 0, otherwise
// deoptimize.
__ andl(result_reg, Immediate(1));
DeoptimizeIf(not_zero, instr->environment());
__ bind(&done);
}
Label bailout, done;
__ DoubleToI(result_reg, input_reg, xmm0,
instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear);
__ jmp(&done, Label::kNear);
__ bind(&bailout);
DeoptimizeIf(no_condition, instr->environment());
__ bind(&done);
}
}
......@@ -4838,31 +4806,19 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
ASSERT(input->IsDoubleRegister());
LOperand* result = instr->result();
ASSERT(result->IsRegister());
CpuFeatureScope scope(masm(), SSE2);
XMMRegister input_reg = ToDoubleRegister(input);
Register result_reg = ToRegister(result);
Label done;
__ cvttsd2si(result_reg, input_reg);
__ cvtlsi2sd(xmm0, result_reg);
__ ucomisd(xmm0, input_reg);
DeoptimizeIf(not_equal, instr->environment());
DeoptimizeIf(parity_even, instr->environment()); // NaN.
Label bailout, done;
__ DoubleToI(result_reg, input_reg, xmm0,
instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear);
__ jmp(&done, Label::kNear);
__ bind(&bailout);
DeoptimizeIf(no_condition, instr->environment());
__ bind(&done);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
// The integer converted back is equal to the original. We
// only have to test if we got -0 as an input.
__ testl(result_reg, result_reg);
__ j(not_zero, &done, Label::kNear);
__ movmskpd(result_reg, input_reg);
// Bit 0 contains the sign of the double in input_reg.
// If input was positive, we are ok and return 0, otherwise
// deoptimize.
__ andl(result_reg, Immediate(1));
DeoptimizeIf(not_zero, instr->environment());
__ bind(&done);
}
__ Integer32ToSmi(result_reg, result_reg);
DeoptimizeIf(overflow, instr->environment());
}
......
......@@ -123,7 +123,7 @@ class LCodeGen V8_FINAL BASE_EMBEDDED {
// Deferred code support.
void DoDeferredNumberTagD(LNumberTagD* instr);
void DoDeferredNumberTagU(LNumberTagU* instr);
void DoDeferredTaggedToI(LTaggedToI* instr);
void DoDeferredTaggedToI(LTaggedToI* instr, Label* done);
void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr);
void DoDeferredStackCheck(LStackCheck* instr);
void DoDeferredRandom(LRandom* instr);
......@@ -430,6 +430,7 @@ class LDeferredCode: public ZoneObject {
void SetExit(Label* exit) { external_exit_ = exit; }
Label* entry() { return &entry_; }
Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; }
Label* done() { return codegen_->NeedsDeferredFrame() ? &done_ : exit(); }
int instruction_index() const { return instruction_index_; }
protected:
......@@ -440,6 +441,7 @@ class LDeferredCode: public ZoneObject {
LCodeGen* codegen_;
Label entry_;
Label exit_;
Label done_;
Label* external_exit_;
int instruction_index_;
};
......
......@@ -2992,6 +2992,117 @@ void MacroAssembler::LoadUint32(XMMRegister dst,
}
void MacroAssembler::SlowTruncateToI(Register result_reg,
Register input_reg,
int offset) {
DoubleToIStub stub(input_reg, result_reg, offset, true);
call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
}
void MacroAssembler::TruncateHeapNumberToI(Register result_reg,
Register input_reg) {
Label done;
movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
cvttsd2siq(result_reg, xmm0);
Set(kScratchRegister, V8_UINT64_C(0x8000000000000000));
cmpq(result_reg, kScratchRegister);
j(not_equal, &done, Label::kNear);
// Slow case.
if (input_reg.is(result_reg)) {
subq(rsp, Immediate(kDoubleSize));
movsd(MemOperand(rsp, 0), xmm0);
SlowTruncateToI(result_reg, rsp, 0);
addq(rsp, Immediate(kDoubleSize));
} else {
SlowTruncateToI(result_reg, input_reg);
}
bind(&done);
}
void MacroAssembler::TruncateDoubleToI(Register result_reg,
XMMRegister input_reg) {
Label done;
cvttsd2siq(result_reg, input_reg);
movq(kScratchRegister,
V8_INT64_C(0x8000000000000000),
RelocInfo::NONE64);
cmpq(result_reg, kScratchRegister);
j(not_equal, &done, Label::kNear);
subq(rsp, Immediate(kDoubleSize));
movsd(MemOperand(rsp, 0), input_reg);
SlowTruncateToI(result_reg, rsp, 0);
addq(rsp, Immediate(kDoubleSize));
bind(&done);
}
void MacroAssembler::DoubleToI(Register result_reg,
XMMRegister input_reg,
XMMRegister scratch,
MinusZeroMode minus_zero_mode,
Label* conversion_failed,
Label::Distance dst) {
cvttsd2si(result_reg, input_reg);
cvtlsi2sd(xmm0, result_reg);
ucomisd(xmm0, input_reg);
j(not_equal, conversion_failed, dst);
j(parity_even, conversion_failed, dst); // NaN.
if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
Label done;
// The integer converted back is equal to the original. We
// only have to test if we got -0 as an input.
testl(result_reg, result_reg);
j(not_zero, &done, Label::kNear);
movmskpd(result_reg, input_reg);
// Bit 0 contains the sign of the double in input_reg.
// If input was positive, we are ok and return 0, otherwise
// jump to conversion_failed.
andl(result_reg, Immediate(1));
j(not_zero, conversion_failed, dst);
bind(&done);
}
}
void MacroAssembler::TaggedToI(Register result_reg,
Register input_reg,
XMMRegister temp,
MinusZeroMode minus_zero_mode,
Label* lost_precision,
Label::Distance dst) {
Label done;
ASSERT(!temp.is(xmm0));
// Heap number map check.
CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex);
j(not_equal, lost_precision, dst);
movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
cvttsd2si(result_reg, xmm0);
cvtlsi2sd(temp, result_reg);
ucomisd(xmm0, temp);
RecordComment("Deferred TaggedToI: lost precision");
j(not_equal, lost_precision, dst);
RecordComment("Deferred TaggedToI: NaN");
j(parity_even, lost_precision, dst); // NaN.
if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
testl(result_reg, result_reg);
j(not_zero, &done, Label::kNear);
movmskpd(result_reg, xmm0);
andl(result_reg, Immediate(1));
j(not_zero, lost_precision, dst);
}
bind(&done);
}
void MacroAssembler::LoadInstanceDescriptors(Register map,
Register descriptors) {
movq(descriptors, FieldOperand(map, Map::kDescriptorsOffset));
......
......@@ -975,6 +975,20 @@ class MacroAssembler: public Assembler {
XMMRegister temp_xmm_reg,
Register result_reg);
void SlowTruncateToI(Register result_reg, Register input_reg,
int offset = HeapNumber::kValueOffset - kHeapObjectTag);
void TruncateHeapNumberToI(Register result_reg, Register input_reg);
void TruncateDoubleToI(Register result_reg, XMMRegister input_reg);
void DoubleToI(Register result_reg, XMMRegister input_reg,
XMMRegister scratch, MinusZeroMode minus_zero_mode,
Label* conversion_failed, Label::Distance dst = Label::kFar);
void TaggedToI(Register result_reg, Register input_reg, XMMRegister temp,
MinusZeroMode minus_zero_mode, Label* lost_precision,
Label::Distance dst = Label::kFar);
void LoadUint32(XMMRegister dst, Register src, XMMRegister scratch);
void LoadInstanceDescriptors(Register map, Register descriptors);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment