ARM: Optimsisation of ECMA ToInt32.

BUG=none
TEST=none

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13912 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1a2454d7
......@@ -745,34 +745,21 @@ void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm,
Register scratch1,
Register scratch2,
Register scratch3,
DwVfpRegister double_scratch,
DwVfpRegister double_scratch1,
DwVfpRegister double_scratch2,
Label* not_number) {
Label done;
__ AssertRootValue(heap_number_map,
Heap::kHeapNumberMapRootIndex,
"HeapNumberMap register clobbered.");
Label done;
Label not_in_int32_range;
__ UntagAndJumpIfSmi(dst, object, &done);
__ ldr(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset));
__ cmp(scratch1, heap_number_map);
__ b(ne, not_number);
__ ConvertToInt32(object,
dst,
scratch1,
scratch2,
double_scratch,
&not_in_int32_range);
__ jmp(&done);
__ bind(&not_in_int32_range);
__ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
__ ldr(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
__ EmitOutOfInt32RangeTruncate(dst,
scratch1,
scratch2,
scratch3);
__ ECMAConvertNumberToInt32(object, dst,
scratch1, scratch2, scratch3,
double_scratch1, double_scratch2);
__ bind(&done);
}
......@@ -2290,18 +2277,16 @@ void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
}
void UnaryOpStub::GenerateHeapNumberCodeBitNot(
MacroAssembler* masm, Label* slow) {
Label impossible;
void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm,
Label* slow) {
EmitCheckForHeapNumber(masm, r0, r1, r6, slow);
// Convert the heap number is r0 to an untagged integer in r1.
__ ConvertToInt32(r0, r1, r2, r3, d0, slow);
// Convert the heap number in r0 to an untagged integer in r1.
__ ECMAConvertNumberToInt32(r0, r1, r2, r3, r4, d0, d1);
// Do the bitwise operation and check if the result fits in a smi.
Label try_float;
__ mvn(r1, Operand(r1));
__ add(r2, r1, Operand(0x40000000), SetCC);
__ cmn(r1, Operand(0x40000000));
__ b(mi, &try_float);
// Tag the result as a smi and we're done.
......@@ -2312,28 +2297,22 @@ void UnaryOpStub::GenerateHeapNumberCodeBitNot(
__ bind(&try_float);
if (mode_ == UNARY_NO_OVERWRITE) {
Label slow_allocate_heapnumber, heapnumber_allocated;
// Allocate a new heap number without zapping r0, which we need if it fails.
__ AllocateHeapNumber(r2, r3, r4, r6, &slow_allocate_heapnumber);
__ AllocateHeapNumber(r0, r3, r4, r6, &slow_allocate_heapnumber);
__ jmp(&heapnumber_allocated);
__ bind(&slow_allocate_heapnumber);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ push(r0); // Push the heap number, not the untagged int32.
// Push the lower bit of the result (left shifted to look like a smi).
__ mov(r2, Operand(r1, LSL, 31));
// Push the 31 high bits (bit 0 cleared to look like a smi).
__ bic(r1, r1, Operand(1));
__ Push(r2, r1);
__ CallRuntime(Runtime::kNumberAlloc, 0);
__ mov(r2, r0); // Move the new heap number into r2.
// Get the heap number into r0, now that the new heap number is in r2.
__ pop(r0);
__ Pop(r2, r1); // Restore the result.
__ orr(r1, r1, Operand(r2, LSR, 31));
}
// Convert the heap number in r0 to an untagged integer in r1.
// This can't go slow-case because it's the same number we already
// converted once again.
__ ConvertToInt32(r0, r1, r3, r4, d0, &impossible);
__ mvn(r1, Operand(r1));
__ bind(&heapnumber_allocated);
__ mov(r0, r2); // Move newly allocated heap number to r0.
}
if (CpuFeatures::IsSupported(VFP2)) {
......@@ -2341,8 +2320,7 @@ void UnaryOpStub::GenerateHeapNumberCodeBitNot(
CpuFeatureScope scope(masm, VFP2);
__ vmov(s0, r1);
__ vcvt_f64_s32(d0, s0);
__ sub(r2, r0, Operand(kHeapObjectTag));
__ vstr(d0, r2, HeapNumber::kValueOffset);
__ vstr(d0, FieldMemOperand(r0, HeapNumber::kValueOffset));
__ Ret();
} else {
// WriteInt32ToHeapNumberStub does not trigger GC, so we do not
......@@ -2350,11 +2328,6 @@ void UnaryOpStub::GenerateHeapNumberCodeBitNot(
WriteInt32ToHeapNumberStub stub(r1, r0, r2);
__ Jump(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
}
__ bind(&impossible);
if (FLAG_debug_code) {
__ stop("Incorrect assumption in bit-not stub");
}
}
......@@ -2786,6 +2759,7 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
scratch2,
scratch3,
d0,
d1,
not_numbers);
FloatingPointHelper::ConvertNumberToInt32(masm,
right,
......@@ -2795,6 +2769,7 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
scratch2,
scratch3,
d0,
d1,
not_numbers);
}
......
......@@ -638,7 +638,8 @@ class FloatingPointHelper : public AllStatic {
Register scratch1,
Register scratch2,
Register scratch3,
DwVfpRegister double_scratch,
DwVfpRegister double_scratch1,
DwVfpRegister double_scratch2,
Label* not_int32);
// Converts the integer (untagged smi) in |int_scratch| to a double, storing
......
......@@ -5254,12 +5254,8 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
__ sub(scratch1, input_reg, Operand(kHeapObjectTag));
__ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset);
__ EmitECMATruncate(input_reg,
double_scratch2,
double_scratch,
scratch1,
scratch2,
scratch3);
__ ECMAToInt32VFP(input_reg, double_scratch2, double_scratch,
scratch1, scratch2, scratch3);
} else {
CpuFeatureScope scope(masm(), VFP3);
......@@ -5357,12 +5353,8 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
if (instr->truncating()) {
Register scratch3 = ToRegister(instr->temp2());
__ EmitECMATruncate(result_reg,
double_input,
double_scratch,
scratch1,
scratch2,
scratch3);
__ ECMAToInt32VFP(result_reg, double_input, double_scratch,
scratch1, scratch2, scratch3);
} else {
__ TryDoubleToInt32Exact(result_reg, double_input, double_scratch);
// Deoptimize if the input wasn't a int32 (inside a double).
......
This diff is collapsed.
......@@ -933,17 +933,6 @@ class MacroAssembler: public Assembler {
Register scratch1,
SwVfpRegister scratch2);
// Convert the HeapNumber pointed to by source to a 32bits signed integer
// dest. If the HeapNumber does not fit into a 32bits signed integer branch
// to not_int32 label. If VFP3 is available double_scratch is used but not
// scratch2.
void ConvertToInt32(Register source,
Register dest,
Register scratch,
Register scratch2,
DwVfpRegister double_scratch,
Label *not_int32);
// Check if a double can be exactly represented as a signed 32-bit integer.
// Z flag set to one if true.
void TestDoubleIsInt32(DwVfpRegister double_input,
......@@ -965,26 +954,34 @@ class MacroAssembler: public Assembler {
Label* done,
Label* exact);
// Helper for EmitECMATruncate.
// This will truncate a floating-point value outside of the signed 32bit
// integer range to a 32bit signed integer.
// Expects the double value loaded in input_high and input_low.
// Exits with the answer in 'result'.
// Note that this code does not work for values in the 32bit range!
void EmitOutOfInt32RangeTruncate(Register result,
Register input_high,
Register input_low,
Register scratch);
// Performs a truncating conversion of a heap floating point number as used by
// the JS bitwise operations. See ECMA-262 9.5: ToInt32.
// Exits with 'result' holding the answer.
void ECMAConvertNumberToInt32(Register source,
Register result,
Register scratch,
Register input_high,
Register input_low,
DwVfpRegister double_scratch1,
DwVfpRegister double_scratch2);
// Performs a truncating conversion of a floating point number as used by
// the JS bitwise operations. See ECMA-262 9.5: ToInt32.
// Exits with 'result' holding the answer and all other registers clobbered.
void EmitECMATruncate(Register result,
DwVfpRegister double_input,
DwVfpRegister double_scratch,
void ECMAToInt32VFP(Register result,
DwVfpRegister double_input,
DwVfpRegister double_scratch,
Register scratch,
Register input_high,
Register input_low);
// Performs a truncating conversion of a floating point number as used by
// the JS bitwise operations. See ECMA-262 9.5: ToInt32.
// Exits with 'result' holding the answer.
void ECMAToInt32NoVFP(Register result,
Register scratch,
Register scratch2,
Register scratch3);
Register input_high,
Register input_low);
// Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz
// instruction. On pre-ARM5 hardware this routine gives the wrong answer
......@@ -1365,6 +1362,16 @@ class MacroAssembler: public Assembler {
// it. See the implementation for register usage.
void JumpToHandlerEntry();
// Helper for ECMAToInt32VFP and ECMAToInt32NoVFP.
// It is expected that 31 <= exponent <= 83, and scratch is exponent - 1.
void ECMAToInt32Tail(Register result,
Register scratch,
Register input_high,
Register input_low,
Label* out_of_range,
Label* negate,
Label* done);
// Compute memory operands for safepoint stack slots.
static int SafepointRegisterStackIndex(int reg_code);
MemOperand SafepointRegisterSlot(Register reg);
......
......@@ -3512,7 +3512,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
// not include -kHeapObjectTag into it.
__ sub(r5, value, Operand(kHeapObjectTag));
__ vldr(d0, r5, HeapNumber::kValueOffset);
__ EmitECMATruncate(r5, d0, d1, r6, r7, r9);
__ ECMAToInt32VFP(r5, d0, d1, r6, r7, r9);
switch (elements_kind) {
case EXTERNAL_BYTE_ELEMENTS:
......
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