Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(255)

Unified Diff: src/ia32/lithium-codegen-ia32.cc

Issue 22290005: Move ToI conversions to the MacroAssembler (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: address review Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ia32/lithium-codegen-ia32.cc
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 10115b1ac4744b14b0043293e0fc783b862502f5..d988ff0ee23590a17a7505210598267cc0f85255 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -446,6 +446,7 @@ bool LCodeGen::GenerateDeferredCode() {
Comment(";;; Deferred code");
}
code->Generate();
+ __ bind(code->done());
if (NeedsDeferredFrame()) {
Comment(";;; Destroy frame");
ASSERT(frame_is_built_);
@@ -5273,94 +5274,39 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
}
-void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
- Label done, heap_number;
+void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
Register input_reg = ToRegister(instr->value());
- // Heap number map check.
- __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
- factory()->heap_number_map());
if (instr->truncating()) {
+ Label heap_number, slow_case;
+
+ // Heap number map check.
+ __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
+ factory()->heap_number_map());
__ j(equal, &heap_number, Label::kNear);
+
// Check for undefined. Undefined is converted to zero for truncating
// conversions.
__ cmp(input_reg, factory()->undefined_value());
__ RecordComment("Deferred TaggedToI: cannot truncate");
DeoptimizeIf(not_equal, instr->environment());
__ mov(input_reg, 0);
- __ jmp(&done, Label::kNear);
+ __ jmp(done);
__ bind(&heap_number);
- if (CpuFeatures::IsSupported(SSE3)) {
- CpuFeatureScope scope(masm(), SSE3);
- Label convert;
- // Use more powerful conversion when sse3 is available.
- // Load x87 register with heap number.
- __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
- // Get exponent alone and check for too-big exponent.
- __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
- __ and_(input_reg, HeapNumber::kExponentMask);
- const uint32_t kTooBigExponent =
- (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
- __ cmp(Operand(input_reg), Immediate(kTooBigExponent));
- __ j(less, &convert, Label::kNear);
- // Pop FPU stack before deoptimizing.
- __ fstp(0);
- __ RecordComment("Deferred TaggedToI: exponent too big");
- DeoptimizeIf(no_condition, instr->environment());
-
- // Reserve space for 64 bit answer.
- __ bind(&convert);
- __ sub(Operand(esp), Immediate(kDoubleSize));
- // Do conversion, which cannot fail because we checked the exponent.
- __ fisttp_d(Operand(esp, 0));
- __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result.
- __ add(Operand(esp), Immediate(kDoubleSize));
- } else if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatureScope scope(masm(), SSE2);
- XMMRegister xmm_temp = ToDoubleRegister(instr->temp());
- __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
- __ cvttsd2si(input_reg, Operand(xmm0));
- __ cmp(input_reg, 0x80000000u);
- __ j(not_equal, &done);
- // Check if the input was 0x8000000 (kMinInt).
- // If no, then we got an overflow and we deoptimize.
- ExternalReference min_int = ExternalReference::address_of_min_int();
- __ movdbl(xmm_temp, Operand::StaticVariable(min_int));
- __ ucomisd(xmm_temp, xmm0);
- DeoptimizeIf(not_equal, instr->environment());
- DeoptimizeIf(parity_even, instr->environment()); // NaN.
- } else {
- UNREACHABLE();
- }
- } else if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatureScope scope(masm(), SSE2);
- // Deoptimize if we don't have a heap number.
- __ RecordComment("Deferred TaggedToI: not a heap number");
- DeoptimizeIf(not_equal, instr->environment());
-
- XMMRegister xmm_temp = ToDoubleRegister(instr->temp());
- __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
- __ cvttsd2si(input_reg, Operand(xmm0));
- __ cvtsi2sd(xmm_temp, Operand(input_reg));
- __ ucomisd(xmm0, xmm_temp);
- __ RecordComment("Deferred TaggedToI: lost precision");
- DeoptimizeIf(not_equal, instr->environment());
- __ RecordComment("Deferred TaggedToI: NaN");
- DeoptimizeIf(parity_even, instr->environment()); // NaN.
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- __ test(input_reg, Operand(input_reg));
- __ j(not_zero, &done);
- __ movmskpd(input_reg, xmm0);
- __ and_(input_reg, 1);
- __ RecordComment("Deferred TaggedToI: minus zero");
- DeoptimizeIf(not_zero, instr->environment());
- }
+ __ TruncateHeapNumberToI(input_reg, input_reg);
} else {
- UNREACHABLE();
+ Label bailout;
+ XMMRegister scratch = (instr->temp() != NULL)
+ ? ToDoubleRegister(instr->temp())
+ : no_xmm_reg;
+ __ TaggedToI(input_reg, input_reg, scratch,
+ instr->hydrogen()->GetMinusZeroMode(), &bailout);
+ __ jmp(done);
+ __ bind(&bailout);
+ DeoptimizeIf(no_condition, instr->environment());
}
- __ bind(&done);
}
@@ -5370,7 +5316,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:
@@ -5390,169 +5336,6 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
}
-void LCodeGen::DoDeferredTaggedToINoSSE2(LTaggedToINoSSE2* instr) {
- Label done, heap_number;
- Register result_reg = ToRegister(instr->result());
- Register input_reg = ToRegister(instr->value());
-
- // Heap number map check.
- __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
- factory()->heap_number_map());
- if (instr->truncating()) {
- __ j(equal, &heap_number, Label::kNear);
- // Check for undefined. Undefined is converted to zero for truncating
- // conversions.
- __ cmp(input_reg, factory()->undefined_value());
- __ RecordComment("Deferred TaggedToI: cannot truncate");
- DeoptimizeIf(not_equal, instr->environment());
- __ xor_(result_reg, result_reg);
- __ jmp(&done, Label::kFar);
- __ bind(&heap_number);
- } else {
- // Deoptimize if we don't have a heap number.
- DeoptimizeIf(not_equal, instr->environment());
- }
-
- // Surprisingly, all of this crazy bit manipulation is considerably
- // faster than using the built-in x86 CPU conversion functions (about 6x).
- Label right_exponent, adjust_bias, zero_result;
- Register scratch = ToRegister(instr->scratch());
- Register scratch2 = ToRegister(instr->scratch2());
- // Get exponent word.
- __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset));
- // Get exponent alone in scratch2.
- __ mov(scratch2, scratch);
- __ and_(scratch2, HeapNumber::kExponentMask);
- __ shr(scratch2, HeapNumber::kExponentShift);
- if (instr->truncating()) {
- __ j(zero, &zero_result);
- } else {
- __ j(not_zero, &adjust_bias);
- __ test(scratch, Immediate(HeapNumber::kMantissaMask));
- DeoptimizeIf(not_zero, instr->environment());
- __ cmp(FieldOperand(input_reg, HeapNumber::kMantissaOffset), Immediate(0));
- DeoptimizeIf(not_equal, instr->environment());
- __ bind(&adjust_bias);
- }
- __ sub(scratch2, Immediate(HeapNumber::kExponentBias));
- if (!instr->truncating()) {
- DeoptimizeIf(negative, instr->environment());
- } else {
- __ j(negative, &zero_result);
- }
-
- // Get the second half of the double. For some exponents we don't
- // actually need this because the bits get shifted out again, but
- // it's probably slower to test than just to do it.
- Register scratch3 = ToRegister(instr->scratch3());
- __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
- __ xor_(result_reg, result_reg);
-
- const uint32_t non_int32_exponent = 31;
- __ cmp(scratch2, Immediate(non_int32_exponent));
- // If we have a match of the int32 exponent then skip some logic.
- __ j(equal, &right_exponent, Label::kNear);
- // If the number doesn't find in an int32, deopt.
- DeoptimizeIf(greater, instr->environment());
-
- // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent
- // < 31.
- __ mov(result_reg, Immediate(31));
- __ sub(result_reg, scratch2);
-
- __ bind(&right_exponent);
-
- // Save off exponent for negative check later.
- __ mov(scratch2, scratch);
-
- // Here result_reg is the shift, scratch is the exponent word.
- // Get the top bits of the mantissa.
- __ and_(scratch, HeapNumber::kMantissaMask);
- // Put back the implicit 1.
- __ or_(scratch, 1 << HeapNumber::kExponentShift);
- // Shift up the mantissa bits to take up the space the exponent used to
- // take. We have kExponentShift + 1 significant bits int he low end of the
- // word. Shift them to the top bits.
- const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 1;
- __ shl(scratch, shift_distance);
- if (!instr->truncating()) {
- // If not truncating, a non-zero value in the bottom 22 bits means a
- // non-integral value --> trigger a deopt.
- __ test(scratch3, Immediate((1 << (32 - shift_distance)) - 1));
- DeoptimizeIf(not_equal, instr->environment());
- }
- // Shift down 22 bits to get the most significant 10 bits or the low
- // mantissa word.
- __ shr(scratch3, 32 - shift_distance);
- __ or_(scratch3, scratch);
- if (!instr->truncating()) {
- // If truncating, a non-zero value in the bits that will be shifted away
- // when adjusting the exponent means rounding --> deopt.
- __ mov(scratch, 0x1);
- ASSERT(result_reg.is(ecx));
- __ shl_cl(scratch);
- __ dec(scratch);
- __ test(scratch3, scratch);
- DeoptimizeIf(not_equal, instr->environment());
- }
- // Move down according to the exponent.
- ASSERT(result_reg.is(ecx));
- __ shr_cl(scratch3);
- // Now the unsigned 32-bit answer is in scratch3. We need to move it to
- // result_reg and we may need to fix the sign.
- Label negative_result;
- __ xor_(result_reg, result_reg);
- __ cmp(scratch2, result_reg);
- __ j(less, &negative_result, Label::kNear);
- __ cmp(scratch3, result_reg);
- __ mov(result_reg, scratch3);
- // If the result is > MAX_INT, result doesn't fit in signed 32-bit --> deopt.
- DeoptimizeIf(less, instr->environment());
- __ jmp(&done, Label::kNear);
- __ bind(&zero_result);
- __ xor_(result_reg, result_reg);
- __ jmp(&done, Label::kNear);
- __ bind(&negative_result);
- __ sub(result_reg, scratch3);
- if (!instr->truncating()) {
- // -0.0 triggers a deopt.
- DeoptimizeIf(zero, instr->environment());
- }
- // If the negative subtraction overflows into a positive number, there was an
- // overflow --> deopt.
- DeoptimizeIf(positive, instr->environment());
- __ bind(&done);
-}
-
-
-void LCodeGen::DoTaggedToINoSSE2(LTaggedToINoSSE2* instr) {
- class DeferredTaggedToINoSSE2 V8_FINAL : public LDeferredCode {
- public:
- DeferredTaggedToINoSSE2(LCodeGen* codegen, LTaggedToINoSSE2* instr)
- : LDeferredCode(codegen), instr_(instr) { }
- virtual void Generate() V8_OVERRIDE {
- codegen()->DoDeferredTaggedToINoSSE2(instr_);
- }
- virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
- private:
- LTaggedToINoSSE2* instr_;
- };
-
- LOperand* input = instr->value();
- ASSERT(input->IsRegister());
- Register input_reg = ToRegister(input);
- ASSERT(input_reg.is(ToRegister(instr->result())));
-
- DeferredTaggedToINoSSE2* deferred =
- new(zone()) DeferredTaggedToINoSSE2(this, instr);
-
- // Smi check.
- __ JumpIfNotSmi(input_reg, deferred->entry());
- __ SmiUntag(input_reg); // Untag smi.
- __ bind(deferred->exit());
-}
-
-
void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
LOperand* input = instr->value();
ASSERT(input->IsRegister());
@@ -5599,73 +5382,33 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
ASSERT(result->IsRegister());
Register result_reg = ToRegister(result);
- Label done;
- if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
- CpuFeatureScope scope(masm(), SSE2);
-
- XMMRegister input_reg = ToDoubleRegister(input);
-
- __ cvttsd2si(result_reg, Operand(input_reg));
-
- if (instr->truncating()) {
- // Performs a truncating conversion of a floating point number as used by
- // the JS bitwise operations.
- Label fast_case_succeeded;
- __ cmp(result_reg, 0x80000000u);
- __ j(not_equal, &fast_case_succeeded);
- __ sub(esp, Immediate(kDoubleSize));
- __ movdbl(MemOperand(esp, 0), input_reg);
- DoubleToIStub stub(esp, result_reg, 0, true);
- __ call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
- __ add(esp, Immediate(kDoubleSize));
- __ bind(&fast_case_succeeded);
+ if (instr->truncating()) {
+ if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
+ CpuFeatureScope scope(masm(), SSE2);
+ XMMRegister input_reg = ToDoubleRegister(input);
+ __ TruncateDoubleToI(result_reg, input_reg);
} else {
- __ cvtsi2sd(xmm0, Operand(result_reg));
- __ ucomisd(xmm0, input_reg);
- DeoptimizeIf(not_equal, instr->environment());
- DeoptimizeIf(parity_even, instr->environment()); // NaN.
- 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.
- __ 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
- // deoptimize.
- __ and_(result_reg, 1);
- DeoptimizeIf(not_zero, instr->environment());
- }
- __ bind(&done);
+ X87Register input_reg = ToX87Register(input);
+ X87Fxch(input_reg);
+ __ TruncateX87TOSToI(result_reg);
}
} else {
- X87Register input_reg = ToX87Register(input);
- __ push(result_reg);
- X87Mov(Operand(esp, 0), input_reg, kX87IntOperand);
- if (instr->truncating()) {
- __ pop(result_reg);
+ Label bailout, done;
+ if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
+ CpuFeatureScope scope(masm(), SSE2);
+ XMMRegister input_reg = ToDoubleRegister(input);
+ __ DoubleToI(result_reg, input_reg, xmm0,
+ instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear);
} else {
+ X87Register input_reg = ToX87Register(input);
X87Fxch(input_reg);
- __ fld(0);
- __ fild_s(Operand(esp, 0));
- __ pop(result_reg);
- __ FCmp();
- DeoptimizeIf(not_equal, instr->environment());
- DeoptimizeIf(parity_even, instr->environment()); // NaN.
- }
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- __ test(result_reg, Operand(result_reg));
- __ j(not_zero, &done, Label::kNear);
- // To check for minus zero, we load the value again as float, and check
- // if that is still 0.
- X87Fxch(input_reg);
- __ push(result_reg);
- __ fst_s(Operand(esp, 0));
- __ pop(result_reg);
- __ test(result_reg, Operand(result_reg));
- DeoptimizeIf(not_zero, instr->environment());
- __ bind(&done);
+ __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
+ &bailout, Label::kNear);
}
+ __ jmp(&done, Label::kNear);
+ __ bind(&bailout);
+ DeoptimizeIf(no_condition, instr->environment());
+ __ bind(&done);
}
}
@@ -5677,55 +5420,23 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
ASSERT(result->IsRegister());
Register result_reg = ToRegister(result);
- Label done;
+ Label bailout, done;
if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
CpuFeatureScope scope(masm(), SSE2);
-
XMMRegister input_reg = ToDoubleRegister(input);
-
- __ cvttsd2si(result_reg, Operand(input_reg));
- __ cvtsi2sd(xmm0, Operand(result_reg));
- __ ucomisd(xmm0, input_reg);
- DeoptimizeIf(not_equal, instr->environment());
- DeoptimizeIf(parity_even, instr->environment()); // NaN.
- 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.
- __ 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
- // deoptimize.
- __ and_(result_reg, 1);
- DeoptimizeIf(not_zero, instr->environment());
- __ bind(&done);
- }
+ __ DoubleToI(result_reg, input_reg, xmm0,
+ instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear);
} else {
X87Register input_reg = ToX87Register(input);
X87Fxch(input_reg);
- __ push(result_reg);
- X87Mov(Operand(esp, 0), input_reg, kX87IntOperand);
- __ fld(0);
- __ fild_s(Operand(esp, 0));
- __ pop(result_reg);
- __ FCmp();
- DeoptimizeIf(not_equal, instr->environment());
- DeoptimizeIf(parity_even, instr->environment()); // NaN.
-
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- __ test(result_reg, Operand(result_reg));
- __ j(not_zero, &done, Label::kNear);
- // To check for minus zero, we load the value again as float, and check
- // if that is still 0.
- __ push(result_reg);
- __ fst_s(Operand(esp, 0));
- __ pop(result_reg);
- __ test(result_reg, Operand(result_reg));
- DeoptimizeIf(not_zero, instr->environment());
- __ bind(&done);
- }
+ __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
+ &bailout, Label::kNear);
}
+ __ jmp(&done, Label::kNear);
+ __ bind(&bailout);
+ DeoptimizeIf(no_condition, instr->environment());
+ __ bind(&done);
+
__ SmiTag(result_reg);
DeoptimizeIf(overflow, instr->environment());
}
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698