Index: src/arm/code-stubs-arm.cc |
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc |
index bce0c518ab5c690baf1d11a3653b3abbd18eb073..1d429c8fc2650b82f8bc84c20119e416f88c2edb 100644 |
--- a/src/arm/code-stubs-arm.cc |
+++ b/src/arm/code-stubs-arm.cc |
@@ -409,6 +409,7 @@ class FloatingPointHelper : public AllStatic { |
Register heap_number_map, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
DwVfpRegister double_scratch, |
Label* not_int32); |
@@ -612,6 +613,7 @@ void FloatingPointHelper::LoadNumberAsInteger(MacroAssembler* masm, |
Register heap_number_map, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
DwVfpRegister double_scratch, |
Label* not_int32) { |
if (FLAG_debug_code) { |
@@ -619,14 +621,88 @@ void FloatingPointHelper::LoadNumberAsInteger(MacroAssembler* masm, |
Heap::kHeapNumberMapRootIndex, |
"HeapNumberMap register clobbered."); |
} |
- Label is_smi, done; |
+ Label is_smi; |
+ Label done; |
+ Label not_in_int32_range; |
+ |
__ JumpIfSmi(object, &is_smi); |
__ ldr(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset)); |
__ cmp(scratch1, heap_number_map); |
__ b(ne, not_int32); |
__ ConvertToInt32( |
- object, dst, scratch1, scratch2, double_scratch, not_int32); |
+ object, dst, scratch1, scratch2, double_scratch, ¬_in_int32_range); |
__ jmp(&done); |
+ |
+ __ bind(¬_in_int32_range); |
+ if (CpuFeatures::IsSupported(VFP3)) { |
+ CpuFeatures::Scope scope(VFP3); |
Søren Thygesen Gjesse
2011/03/10 14:20:30
Should we not support non-vfp here? VFP instructio
Karl Klose
2011/03/11 09:27:39
Done, see comment below.
|
+ __ vldr(double_scratch, FieldMemOperand(object, HeapNumber::kValueOffset)); |
Rodolph Perfetta
2011/03/10 14:36:44
Use Ldrd, it will be faster (no transfer VFP-ARM)
Karl Klose
2011/03/11 09:27:39
I decided to use two ldr instructions to avoid put
|
+ __ vmov(scratch1, scratch2, double_scratch); |
+ |
+ // Register scratch1 contains mantissa word, scratch2 contains |
+ // sign, exponent and mantissa. |
Rodolph Perfetta
2011/03/10 14:36:44
the and and mov could be rewritten as a Ubfx
Karl Klose
2011/03/11 09:27:39
Done.
|
+ __ and_(dst, scratch2, Operand(HeapNumber::kExponentMask)); |
+ __ mov(dst, Operand(dst, LSR, HeapNumber::kExponentShift)); |
+ __ sub(dst, dst, Operand(1023)); |
Søren Thygesen Gjesse
2011/03/10 14:20:30
1023 -> HeapNumber::kExponentBias
Karl Klose
2011/03/11 09:27:39
Done.
|
+ |
+ Label normal_exponent; |
+ // Express exponent as delta to 31. |
+ // If the delta is larger than 53, all bits would be shifted |
+ // away, which means that we can return 0. |
+ __ sub(dst, dst, Operand(31)); |
Søren Thygesen Gjesse
2011/03/10 14:20:30
You could combine this sub with the one before sub
Karl Klose
2011/03/11 09:27:39
Done.
|
+ __ cmp(dst, Operand(53)); |
Søren Thygesen Gjesse
2011/03/10 14:20:30
We have HeapNumber::kMantissaBits which is 52.
Karl Klose
2011/03/11 09:27:39
Done.
|
+ __ b(&normal_exponent, lt); |
+ __ mov(dst, Operand(0)); |
+ __ jmp(&done); |
+ |
+ __ bind(&normal_exponent); |
+ const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1; |
+ // Calculate shift. |
+ __ add(scratch3, dst, Operand(kShiftBase)); |
+ |
+ // Put implicit 1 before the mantissa part in scratch2 and |
+ // shift the mantissa bits to the correct position. |
+ __ orr(scratch2, |
+ scratch2, |
+ Operand(1 << HeapNumber::kMantissaBitsInTopWord)); |
+ |
+ // Save sign. |
+ Register sign = dst; |
+ __ and_(sign, scratch2, Operand(HeapNumber::kSignMask)); |
+ |
+ // Shift mantisssa bits in high word. |
+ __ mov(scratch2, Operand(scratch2, LSL, scratch3)); |
+ |
+ // Replace the shifted bits with bits from the lower mantissa word. |
+ Label pos_shift, neg_shift; |
+ // scratch3 = 32 - scratch3. |
Rodolph Perfetta
2011/03/10 14:36:44
__ rsb(scratch3, scratch3, Operand(32), SetCC) can
Karl Klose
2011/03/11 09:27:39
Done.
|
+ __ mvn(scratch3, Operand(scratch3)); |
+ __ add(scratch3, scratch3, Operand(33)); |
+ __ cmp(scratch3, Operand(0)); |
+ __ b(&pos_shift, ge); |
+ |
+ // Negate scratch3. |
Rodolph Perfetta
2011/03/10 14:36:44
__ rsb(scratch3, scratch3, Operand(0)) will neaget
Karl Klose
2011/03/11 09:27:39
Done.
|
+ __ mvn(scratch3, Operand(scratch3)); |
+ __ add(scratch3, scratch3, Operand(1)); |
+ __ mov(scratch1, Operand(scratch1, LSL, scratch3)); |
+ __ jmp(&neg_shift); |
+ |
+ __ bind(&pos_shift); |
+ __ mov(scratch1, Operand(scratch1, LSR, scratch3)); |
+ |
+ __ bind(&neg_shift); |
Søren Thygesen Gjesse
2011/03/10 14:20:30
neg_shift -> shift_done?
Karl Klose
2011/03/11 09:27:39
Done.
|
+ __ orr(scratch2, scratch2, Operand(scratch1)); |
+ |
+ // Restore sign if necessary. |
Rodolph Perfetta
2011/03/10 14:36:44
__ cmp(sign, Operand(0));
Karl Klose
2011/03/11 09:27:39
Done.
|
+ __ tst(sign, sign); |
Rodolph Perfetta
2011/03/10 14:36:44
rsb again here.
Karl Klose
2011/03/11 09:27:39
Done.
|
+ __ mvn(scratch2, Operand(scratch2), LeaveCC, ne); |
+ __ add(scratch2, scratch2, Operand(1), LeaveCC, ne); |
+ __ mov(dst, scratch2); |
+ __ jmp(&done); |
+ } else { |
+ __ jmp(not_int32); |
+ } |
+ |
__ bind(&is_smi); |
__ SmiUntag(dst, object); |
__ bind(&done); |
@@ -3024,6 +3100,7 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm, |
Register right = r0; |
Register scratch1 = r7; |
Register scratch2 = r9; |
+ Register scratch3 = r4; |
ASSERT(smi_operands || (not_numbers != NULL)); |
if (smi_operands && FLAG_debug_code) { |
@@ -3117,6 +3194,7 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm, |
heap_number_map, |
scratch1, |
scratch2, |
+ scratch3, |
d0, |
not_numbers); |
FloatingPointHelper::LoadNumberAsInteger(masm, |
@@ -3125,6 +3203,7 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm, |
heap_number_map, |
scratch1, |
scratch2, |
+ scratch3, |
d0, |
not_numbers); |
} |
@@ -3572,13 +3651,10 @@ void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { |
- Label not_numbers, call_runtime; |
+ Label call_runtime; |
ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER); |
- GenerateFPOperation(masm, false, ¬_numbers, &call_runtime); |
- |
- __ bind(¬_numbers); |
- GenerateTypeTransition(masm); |
+ GenerateFPOperation(masm, false, &call_runtime, &call_runtime); |
__ bind(&call_runtime); |
GenerateCallRuntime(masm); |