| 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..31a728879175763da06c42a43440a389c6eeb546 100644
|
| --- a/src/arm/code-stubs-arm.cc
|
| +++ b/src/arm/code-stubs-arm.cc
|
| @@ -397,20 +397,18 @@ class FloatingPointHelper : public AllStatic {
|
| Register scratch2,
|
| Label* not_number);
|
|
|
| - // Loads the number from object into dst as a 32-bit integer if possible. If
|
| - // the object cannot be converted to a 32-bit integer control continues at
|
| - // the label not_int32. If VFP is supported double_scratch is used
|
| - // but not scratch2.
|
| - // Floating point value in the 32-bit integer range will be rounded
|
| - // to an integer.
|
| - static void LoadNumberAsInteger(MacroAssembler* masm,
|
| - Register object,
|
| - Register dst,
|
| - Register heap_number_map,
|
| - Register scratch1,
|
| - Register scratch2,
|
| - DwVfpRegister double_scratch,
|
| - Label* not_int32);
|
| + // Convert the smi or heap number in object to an int32 using the rules
|
| + // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
|
| + // and brought into the range -2^31 .. +2^31 - 1.
|
| + static void ConvertNumberToInt32(MacroAssembler* masm,
|
| + Register object,
|
| + Register dst,
|
| + Register heap_number_map,
|
| + Register scratch1,
|
| + Register scratch2,
|
| + Register scratch3,
|
| + DwVfpRegister double_scratch,
|
| + Label* not_int32);
|
|
|
| // Load the number from object into double_dst in the double format.
|
| // Control will jump to not_int32 if the value cannot be exactly represented
|
| @@ -606,27 +604,97 @@ void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
|
| }
|
|
|
|
|
| -void FloatingPointHelper::LoadNumberAsInteger(MacroAssembler* masm,
|
| - Register object,
|
| - Register dst,
|
| - Register heap_number_map,
|
| - Register scratch1,
|
| - Register scratch2,
|
| - DwVfpRegister double_scratch,
|
| - Label* not_int32) {
|
| +void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm,
|
| + Register object,
|
| + Register dst,
|
| + Register heap_number_map,
|
| + Register scratch1,
|
| + Register scratch2,
|
| + Register scratch3,
|
| + DwVfpRegister double_scratch,
|
| + Label* not_number) {
|
| if (FLAG_debug_code) {
|
| __ AbortIfNotRootValue(heap_number_map,
|
| 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);
|
| + __ b(ne, not_number);
|
| + __ ConvertToInt32(object,
|
| + dst,
|
| + scratch1,
|
| + scratch2,
|
| + double_scratch,
|
| + ¬_in_int32_range);
|
| __ jmp(&done);
|
| +
|
| + __ bind(¬_in_int32_range);
|
| + __ ldr(scratch2, FieldMemOperand(object, HeapNumber::kExponentOffset));
|
| + __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kMantissaOffset));
|
| +
|
| + // Register scratch1 contains mantissa word, scratch2 contains
|
| + // sign, exponent and mantissa. Extract biased exponent into dst.
|
| + __ Ubfx(dst,
|
| + scratch2,
|
| + HeapNumber::kExponentShift,
|
| + HeapNumber::kExponentBits);
|
| +
|
| + // Express exponent as delta to 31.
|
| + __ sub(dst, dst, Operand(HeapNumber::kExponentBias + 31));
|
| +
|
| + Label normal_exponent;
|
| + // If the delta is larger than kMantissaBits plus one, all bits
|
| + // would be shifted away, which means that we can return 0.
|
| + __ cmp(dst, Operand(HeapNumber::kMantissaBits + 1));
|
| + __ 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.
|
| + __ orr(scratch2,
|
| + scratch2,
|
| + Operand(1 << HeapNumber::kMantissaBitsInTopWord));
|
| +
|
| + // Save sign.
|
| + Register sign = dst;
|
| + __ and_(sign, scratch2, Operand(HeapNumber::kSignMask));
|
| +
|
| + // Shift mantisssa bits the correct position in high word.
|
| + __ mov(scratch2, Operand(scratch2, LSL, scratch3));
|
| +
|
| + // Replace the shifted bits with bits from the lower mantissa word.
|
| + Label pos_shift, shift_done;
|
| + __ rsb(scratch3, scratch3, Operand(32), SetCC);
|
| + __ b(&pos_shift, ge);
|
| +
|
| + // Negate scratch3.
|
| + __ rsb(scratch3, scratch3, Operand(0));
|
| + __ mov(scratch1, Operand(scratch1, LSL, scratch3));
|
| + __ jmp(&shift_done);
|
| +
|
| + __ bind(&pos_shift);
|
| + __ mov(scratch1, Operand(scratch1, LSR, scratch3));
|
| +
|
| + __ bind(&shift_done);
|
| + __ orr(scratch2, scratch2, Operand(scratch1));
|
| +
|
| + // Restore sign if necessary.
|
| + __ cmp(sign, Operand(0));
|
| + __ rsb(dst, scratch2, Operand(0), LeaveCC, ne);
|
| + __ mov(dst, scratch2, LeaveCC, eq);
|
| + __ jmp(&done);
|
| +
|
| __ bind(&is_smi);
|
| __ SmiUntag(dst, object);
|
| __ bind(&done);
|
| @@ -3024,6 +3092,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) {
|
| @@ -3111,22 +3180,24 @@ void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
|
| __ SmiUntag(r2, right);
|
| } else {
|
| // Convert operands to 32-bit integers. Right in r2 and left in r3.
|
| - FloatingPointHelper::LoadNumberAsInteger(masm,
|
| - left,
|
| - r3,
|
| - heap_number_map,
|
| - scratch1,
|
| - scratch2,
|
| - d0,
|
| - not_numbers);
|
| - FloatingPointHelper::LoadNumberAsInteger(masm,
|
| - right,
|
| - r2,
|
| - heap_number_map,
|
| - scratch1,
|
| - scratch2,
|
| - d0,
|
| - not_numbers);
|
| + FloatingPointHelper::ConvertNumberToInt32(masm,
|
| + left,
|
| + r3,
|
| + heap_number_map,
|
| + scratch1,
|
| + scratch2,
|
| + scratch3,
|
| + d0,
|
| + not_numbers);
|
| + FloatingPointHelper::ConvertNumberToInt32(masm,
|
| + right,
|
| + r2,
|
| + heap_number_map,
|
| + scratch1,
|
| + scratch2,
|
| + scratch3,
|
| + d0,
|
| + not_numbers);
|
| }
|
|
|
| Label result_not_a_smi;
|
| @@ -3572,13 +3643,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);
|
|
|