Commit e0428617 authored by plind44@gmail.com's avatar plind44@gmail.com

MIPS: Sync structure to r14382.

Port r14382 (5ef0d87)

Original commit message:
ARM: VFP cleanup now that VFP2 is the baseline

BUG=none
TEST=none
R=plind44@gmail.com

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

Patch from Balazs Kilvady <kilvadyb@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16408 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 22b70b05
...@@ -521,290 +521,6 @@ void ConvertToDoubleStub::Generate(MacroAssembler* masm) { ...@@ -521,290 +521,6 @@ void ConvertToDoubleStub::Generate(MacroAssembler* masm) {
} }
void FloatingPointHelper::LoadSmis(MacroAssembler* masm,
FloatingPointHelper::Destination destination,
Register scratch1,
Register scratch2) {
__ sra(scratch1, a0, kSmiTagSize);
__ mtc1(scratch1, f14);
__ cvt_d_w(f14, f14);
__ sra(scratch1, a1, kSmiTagSize);
__ mtc1(scratch1, f12);
__ cvt_d_w(f12, f12);
if (destination == kCoreRegisters) {
__ Move(a2, a3, f14);
__ Move(a0, a1, f12);
}
}
void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
Destination destination,
Register object,
FPURegister dst,
Register dst1,
Register dst2,
Register heap_number_map,
Register scratch1,
Register scratch2,
Label* not_number) {
__ AssertRootValue(heap_number_map,
Heap::kHeapNumberMapRootIndex,
kHeapNumberMapRegisterClobbered);
Label is_smi, done;
// Smi-check
__ UntagAndJumpIfSmi(scratch1, object, &is_smi);
// Heap number check
__ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
// Handle loading a double from a heap number.
if (destination == kFPURegisters) {
// Load the double from tagged HeapNumber to double register.
// ARM uses a workaround here because of the unaligned HeapNumber
// kValueOffset. On MIPS this workaround is built into ldc1 so there's no
// point in generating even more instructions.
__ ldc1(dst, FieldMemOperand(object, HeapNumber::kValueOffset));
} else {
ASSERT(destination == kCoreRegisters);
// Load the double from heap number to dst1 and dst2 in double format.
__ lw(dst1, FieldMemOperand(object, HeapNumber::kValueOffset));
__ lw(dst2, FieldMemOperand(object,
HeapNumber::kValueOffset + kPointerSize));
}
__ Branch(&done);
// Handle loading a double from a smi.
__ bind(&is_smi);
// Convert smi to double using FPU instructions.
__ mtc1(scratch1, dst);
__ cvt_d_w(dst, dst);
if (destination == kCoreRegisters) {
// Load the converted smi to dst1 and dst2 in double format.
__ Move(dst1, dst2, dst);
}
__ bind(&done);
}
void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm,
Register object,
Register dst,
Register heap_number_map,
Register scratch1,
Register scratch2,
Register scratch3,
FPURegister double_scratch,
Label* not_number) {
__ AssertRootValue(heap_number_map,
Heap::kHeapNumberMapRootIndex,
kHeapNumberMapRegisterClobbered);
Label done;
Label not_in_int32_range;
__ UntagAndJumpIfSmi(dst, object, &done);
__ lw(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset));
__ Branch(not_number, ne, scratch1, Operand(heap_number_map));
__ ConvertToInt32(object,
dst,
scratch1,
scratch2,
double_scratch,
&not_in_int32_range);
__ jmp(&done);
__ bind(&not_in_int32_range);
__ lw(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
__ lw(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
__ EmitOutOfInt32RangeTruncate(dst,
scratch1,
scratch2,
scratch3);
__ bind(&done);
}
void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm,
Register int_scratch,
Destination destination,
FPURegister double_dst,
Register dst_mantissa,
Register dst_exponent,
Register scratch2,
FPURegister single_scratch) {
ASSERT(!int_scratch.is(scratch2));
ASSERT(!int_scratch.is(dst_mantissa));
ASSERT(!int_scratch.is(dst_exponent));
__ mtc1(int_scratch, single_scratch);
__ cvt_d_w(double_dst, single_scratch);
if (destination == kCoreRegisters) {
__ Move(dst_mantissa, dst_exponent, double_dst);
}
}
void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
Register object,
Destination destination,
DoubleRegister double_dst,
DoubleRegister double_scratch,
Register dst_mantissa,
Register dst_exponent,
Register heap_number_map,
Register scratch1,
Register scratch2,
FPURegister single_scratch,
Label* not_int32) {
ASSERT(!scratch1.is(object) && !scratch2.is(object));
ASSERT(!scratch1.is(scratch2));
ASSERT(!heap_number_map.is(object) &&
!heap_number_map.is(scratch1) &&
!heap_number_map.is(scratch2));
Label done, obj_is_not_smi;
__ JumpIfNotSmi(object, &obj_is_not_smi);
__ SmiUntag(scratch1, object);
ConvertIntToDouble(masm, scratch1, destination, double_dst, dst_mantissa,
dst_exponent, scratch2, single_scratch);
__ Branch(&done);
__ bind(&obj_is_not_smi);
__ AssertRootValue(heap_number_map,
Heap::kHeapNumberMapRootIndex,
kHeapNumberMapRegisterClobbered);
__ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
// Load the number.
// Load the double value.
__ ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset));
Register except_flag = scratch2;
__ EmitFPUTruncate(kRoundToZero,
scratch1,
double_dst,
at,
double_scratch,
except_flag,
kCheckForInexactConversion);
// Jump to not_int32 if the operation did not succeed.
__ Branch(not_int32, ne, except_flag, Operand(zero_reg));
if (destination == kCoreRegisters) {
__ Move(dst_mantissa, dst_exponent, double_dst);
}
__ bind(&done);
}
void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
Register object,
Register dst,
Register heap_number_map,
Register scratch1,
Register scratch2,
Register scratch3,
DoubleRegister double_scratch0,
DoubleRegister double_scratch1,
Label* not_int32) {
ASSERT(!dst.is(object));
ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object));
ASSERT(!scratch1.is(scratch2) &&
!scratch1.is(scratch3) &&
!scratch2.is(scratch3));
Label done, maybe_undefined;
__ UntagAndJumpIfSmi(dst, object, &done);
__ AssertRootValue(heap_number_map,
Heap::kHeapNumberMapRootIndex,
kHeapNumberMapRegisterClobbered);
__ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined);
// Object is a heap number.
// Convert the floating point value to a 32-bit integer.
// Load the double value.
__ ldc1(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset));
Register except_flag = scratch2;
__ EmitFPUTruncate(kRoundToZero,
dst,
double_scratch0,
scratch1,
double_scratch1,
except_flag,
kCheckForInexactConversion);
// Jump to not_int32 if the operation did not succeed.
__ Branch(not_int32, ne, except_flag, Operand(zero_reg));
__ Branch(&done);
__ bind(&maybe_undefined);
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(not_int32, ne, object, Operand(at));
// |undefined| is truncated to 0.
__ li(dst, Operand(Smi::FromInt(0)));
// Fall through.
__ bind(&done);
}
void FloatingPointHelper::CallCCodeForDoubleOperation(
MacroAssembler* masm,
Token::Value op,
Register heap_number_result,
Register scratch) {
// Using core registers:
// a0: Left value (least significant part of mantissa).
// a1: Left value (sign, exponent, top of mantissa).
// a2: Right value (least significant part of mantissa).
// a3: Right value (sign, exponent, top of mantissa).
// Assert that heap_number_result is saved.
// We currently always use s0 to pass it.
ASSERT(heap_number_result.is(s0));
// Push the current return address before the C call.
__ push(ra);
__ PrepareCallCFunction(4, scratch); // Two doubles are 4 arguments.
if (!IsMipsSoftFloatABI) {
// We are not using MIPS FPU instructions, and parameters for the runtime
// function call are prepaired in a0-a3 registers, but function we are
// calling is compiled with hard-float flag and expecting hard float ABI
// (parameters in f12/f14 registers). We need to copy parameters from
// a0-a3 registers to f12/f14 register pairs.
__ Move(f12, a0, a1);
__ Move(f14, a2, a3);
}
{
AllowExternalCallThatCantCauseGC scope(masm);
__ CallCFunction(
ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2);
}
// Store answer in the overwritable heap number.
if (!IsMipsSoftFloatABI) {
// Double returned in register f0.
__ sdc1(f0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
} else {
// Double returned in registers v0 and v1.
__ sw(v1, FieldMemOperand(heap_number_result, HeapNumber::kExponentOffset));
__ sw(v0, FieldMemOperand(heap_number_result, HeapNumber::kMantissaOffset));
}
// Place heap_number_result in v0 and return to the pushed return address.
__ pop(ra);
__ Ret(USE_DELAY_SLOT);
__ mov(v0, heap_number_result);
}
bool WriteInt32ToHeapNumberStub::IsPregenerated() { bool WriteInt32ToHeapNumberStub::IsPregenerated() {
// These variants are compiled ahead of time. See next method. // These variants are compiled ahead of time. See next method.
if (the_int_.is(a1) && if (the_int_.is(a1) &&
...@@ -1472,6 +1188,42 @@ void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { ...@@ -1472,6 +1188,42 @@ void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
} }
// Generates code to call a C function to do a double operation.
// This code never falls through, but returns with a heap number containing
// the result in v0.
// Register heap_number_result must be a heap number in which the
// result of the operation will be stored.
// Requires the following layout on entry:
// a0: Left value (least significant part of mantissa).
// a1: Left value (sign, exponent, top of mantissa).
// a2: Right value (least significant part of mantissa).
// a3: Right value (sign, exponent, top of mantissa).
static void CallCCodeForDoubleOperation(MacroAssembler* masm,
Token::Value op,
Register heap_number_result,
Register scratch) {
// Assert that heap_number_result is saved.
// We currently always use s0 to pass it.
ASSERT(heap_number_result.is(s0));
// Push the current return address before the C call.
__ push(ra);
__ PrepareCallCFunction(4, scratch); // Two doubles are 4 arguments.
{
AllowExternalCallThatCantCauseGC scope(masm);
__ CallCFunction(
ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2);
}
// Store answer in the overwritable heap number.
// Double returned in register f0.
__ sdc1(f0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
// Place heap_number_result in v0 and return to the pushed return address.
__ pop(ra);
__ Ret(USE_DELAY_SLOT);
__ mov(v0, heap_number_result);
}
void BinaryOpStub::Initialize() { void BinaryOpStub::Initialize() {
platform_specific_bit_ = true; // FPU is a base requirement for V8. platform_specific_bit_ = true; // FPU is a base requirement for V8.
} }
...@@ -1699,49 +1451,41 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm, ...@@ -1699,49 +1451,41 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
case Token::MUL: case Token::MUL:
case Token::DIV: case Token::DIV:
case Token::MOD: { case Token::MOD: {
// Load left and right operands into f12 and f14 or a0/a1 and a2/a3
// depending on operation.
FloatingPointHelper::Destination destination =
op != Token::MOD ?
FloatingPointHelper::kFPURegisters :
FloatingPointHelper::kCoreRegisters;
// Allocate new heap number for result. // Allocate new heap number for result.
Register result = s0; Register result = s0;
BinaryOpStub_GenerateHeapResultAllocation( BinaryOpStub_GenerateHeapResultAllocation(
masm, result, heap_number_map, scratch1, scratch2, gc_required, mode); masm, result, heap_number_map, scratch1, scratch2, gc_required, mode);
// Load the operands. // Load left and right operands into f12 and f14.
if (smi_operands) { if (smi_operands) {
FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2); __ SmiUntag(scratch1, a0);
__ mtc1(scratch1, f14);
__ cvt_d_w(f14, f14);
__ SmiUntag(scratch1, a1);
__ mtc1(scratch1, f12);
__ cvt_d_w(f12, f12);
} else { } else {
// Load right operand to f14 or a2/a3. // Load right operand to f14.
if (right_type == BinaryOpIC::INT32) { if (right_type == BinaryOpIC::INT32) {
FloatingPointHelper::LoadNumberAsInt32Double( __ LoadNumberAsInt32Double(
masm, right, destination, f14, f16, a2, a3, heap_number_map, right, f14, heap_number_map, scratch1, scratch2, f2, miss);
scratch1, scratch2, f2, miss);
} else { } else {
Label* fail = (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers; Label* fail = (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers;
FloatingPointHelper::LoadNumber( __ LoadNumber(right, f14, heap_number_map, scratch1, fail);
masm, destination, right, f14, a2, a3, heap_number_map,
scratch1, scratch2, fail);
} }
// Load left operand to f12 or a0/a1. This keeps a0/a1 intact if it // Load left operand to f12 or a0/a1. This keeps a0/a1 intact if it
// jumps to |miss|. // jumps to |miss|.
if (left_type == BinaryOpIC::INT32) { if (left_type == BinaryOpIC::INT32) {
FloatingPointHelper::LoadNumberAsInt32Double( __ LoadNumberAsInt32Double(
masm, left, destination, f12, f16, a0, a1, heap_number_map, left, f12, heap_number_map, scratch1, scratch2, f2, miss);
scratch1, scratch2, f2, miss);
} else { } else {
Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers; Label* fail = (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers;
FloatingPointHelper::LoadNumber( __ LoadNumber(left, f12, heap_number_map, scratch1, fail);
masm, destination, left, f12, a0, a1, heap_number_map,
scratch1, scratch2, fail);
} }
} }
// Calculate the result. // Calculate the result.
if (destination == FloatingPointHelper::kFPURegisters) { if (op != Token::MOD) {
// Using FPU registers: // Using FPU registers:
// f12: Left value. // f12: Left value.
// f14: Right value. // f14: Right value.
...@@ -1770,10 +1514,7 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm, ...@@ -1770,10 +1514,7 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
__ mov(v0, result); __ mov(v0, result);
} else { } else {
// Call the C function to handle the double operation. // Call the C function to handle the double operation.
FloatingPointHelper::CallCCodeForDoubleOperation(masm, CallCCodeForDoubleOperation(masm, op, result, scratch1);
op,
result,
scratch1);
if (FLAG_debug_code) { if (FLAG_debug_code) {
__ stop("Unreachable code."); __ stop("Unreachable code.");
} }
...@@ -1791,24 +1532,12 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm, ...@@ -1791,24 +1532,12 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
__ SmiUntag(a2, right); __ SmiUntag(a2, right);
} else { } else {
// Convert operands to 32-bit integers. Right in a2 and left in a3. // Convert operands to 32-bit integers. Right in a2 and left in a3.
FloatingPointHelper::ConvertNumberToInt32(masm, __ ConvertNumberToInt32(
left, left, a3, heap_number_map,
a3, scratch1, scratch2, scratch3, f0, not_numbers);
heap_number_map, __ ConvertNumberToInt32(
scratch1, right, a2, heap_number_map,
scratch2, scratch1, scratch2, scratch3, f0, not_numbers);
scratch3,
f0,
not_numbers);
FloatingPointHelper::ConvertNumberToInt32(masm,
right,
a2,
heap_number_map,
scratch1,
scratch2,
scratch3,
f0,
not_numbers);
} }
Label result_not_a_smi; Label result_not_a_smi;
switch (op) { switch (op) {
...@@ -2042,36 +1771,13 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { ...@@ -2042,36 +1771,13 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
// Load both operands and check that they are 32-bit integer. // Load both operands and check that they are 32-bit integer.
// Jump to type transition if they are not. The registers a0 and a1 (right // Jump to type transition if they are not. The registers a0 and a1 (right
// and left) are preserved for the runtime call. // and left) are preserved for the runtime call.
FloatingPointHelper::Destination destination = (op_ != Token::MOD)
? FloatingPointHelper::kFPURegisters __ LoadNumberAsInt32Double(
: FloatingPointHelper::kCoreRegisters; right, f14, heap_number_map, scratch1, scratch2, f2, &transition);
__ LoadNumberAsInt32Double(
FloatingPointHelper::LoadNumberAsInt32Double(masm, left, f12, heap_number_map, scratch1, scratch2, f2, &transition);
right,
destination, if (op_ != Token::MOD) {
f14,
f16,
a2,
a3,
heap_number_map,
scratch1,
scratch2,
f2,
&transition);
FloatingPointHelper::LoadNumberAsInt32Double(masm,
left,
destination,
f12,
f16,
t0,
t1,
heap_number_map,
scratch1,
scratch2,
f2,
&transition);
if (destination == FloatingPointHelper::kFPURegisters) {
Label return_heap_number; Label return_heap_number;
switch (op_) { switch (op_) {
case Token::ADD: case Token::ADD:
...@@ -2148,10 +1854,6 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { ...@@ -2148,10 +1854,6 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
__ BranchF(&transition, NULL, ne, f14, f16); __ BranchF(&transition, NULL, ne, f14, f16);
} }
// We preserved a0 and a1 to be able to call runtime.
// Save the left value on the stack.
__ Push(t1, t0);
Label pop_and_call_runtime; Label pop_and_call_runtime;
// Allocate a heap number to store the result. // Allocate a heap number to store the result.
...@@ -2164,12 +1866,8 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { ...@@ -2164,12 +1866,8 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
&pop_and_call_runtime, &pop_and_call_runtime,
mode_); mode_);
// Load the left value from the value saved on the stack.
__ Pop(a1, a0);
// Call the C function to handle the double operation. // Call the C function to handle the double operation.
FloatingPointHelper::CallCCodeForDoubleOperation( CallCCodeForDoubleOperation(masm, op_, heap_number_result, scratch1);
masm, op_, heap_number_result, scratch1);
if (FLAG_debug_code) { if (FLAG_debug_code) {
__ stop("Unreachable code."); __ stop("Unreachable code.");
} }
...@@ -2189,30 +1887,13 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { ...@@ -2189,30 +1887,13 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
case Token::SHR: case Token::SHR:
case Token::SHL: { case Token::SHL: {
Label return_heap_number; Label return_heap_number;
Register scratch3 = t1;
// Convert operands to 32-bit integers. Right in a2 and left in a3. The // Convert operands to 32-bit integers. Right in a2 and left in a3. The
// registers a0 and a1 (right and left) are preserved for the runtime // registers a0 and a1 (right and left) are preserved for the runtime
// call. // call.
FloatingPointHelper::LoadNumberAsInt32(masm, __ LoadNumberAsInt32(
left, left, a3, heap_number_map, scratch1, scratch2, f0, f2, &transition);
a3, __ LoadNumberAsInt32(
heap_number_map, right, a2, heap_number_map, scratch1, scratch2, f0, f2, &transition);
scratch1,
scratch2,
scratch3,
f0,
f2,
&transition);
FloatingPointHelper::LoadNumberAsInt32(masm,
right,
a2,
heap_number_map,
scratch1,
scratch2,
scratch3,
f0,
f2,
&transition);
// The ECMA-262 standard specifies that, for shift operations, only the // The ECMA-262 standard specifies that, for shift operations, only the
// 5 least significant bits of the shift value should be used. // 5 least significant bits of the shift value should be used.
...@@ -7097,10 +6778,7 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { ...@@ -7097,10 +6778,7 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
// Array literal has ElementsKind of FAST_*_DOUBLE_ELEMENTS. // Array literal has ElementsKind of FAST_*_DOUBLE_ELEMENTS.
__ bind(&double_elements); __ bind(&double_elements);
__ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset)); __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset));
__ StoreNumberToDoubleElements(a0, a3, __ StoreNumberToDoubleElements(a0, a3, t1, t3, t5, a2, &slow_elements);
// Overwrites all regs after this.
t1, t2, t3, t5, a2,
&slow_elements);
__ Ret(USE_DELAY_SLOT); __ Ret(USE_DELAY_SLOT);
__ mov(v0, a0); __ mov(v0, a0);
} }
......
...@@ -527,119 +527,6 @@ class DirectCEntryStub: public PlatformCodeStub { ...@@ -527,119 +527,6 @@ class DirectCEntryStub: public PlatformCodeStub {
bool NeedsImmovableCode() { return true; } bool NeedsImmovableCode() { return true; }
}; };
class FloatingPointHelper : public AllStatic {
public:
enum Destination {
kFPURegisters,
kCoreRegisters
};
// Loads smis from a0 and a1 (right and left in binary operations) into
// floating point registers. Depending on the destination the values ends up
// either f14 and f12 or in a2/a3 and a0/a1 respectively. If the destination
// is floating point registers FPU must be supported. If core registers are
// requested when FPU is supported f12 and f14 will be scratched.
static void LoadSmis(MacroAssembler* masm,
Destination destination,
Register scratch1,
Register scratch2);
// 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,
FPURegister double_scratch,
Label* not_int32);
// Converts the integer (untagged smi) in |int_scratch| to a double, storing
// the result either in |double_dst| or |dst2:dst1|, depending on
// |destination|.
// Warning: The value in |int_scratch| will be changed in the process!
static void ConvertIntToDouble(MacroAssembler* masm,
Register int_scratch,
Destination destination,
FPURegister double_dst,
Register dst1,
Register dst2,
Register scratch2,
FPURegister single_scratch);
// 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
// by a 32-bit integer.
// Floating point value in the 32-bit integer range that are not exact integer
// won't be loaded.
static void LoadNumberAsInt32Double(MacroAssembler* masm,
Register object,
Destination destination,
FPURegister double_dst,
FPURegister double_scratch,
Register dst1,
Register dst2,
Register heap_number_map,
Register scratch1,
Register scratch2,
FPURegister single_scratch,
Label* not_int32);
// Loads the number from object into dst as a 32-bit integer.
// Control will jump to not_int32 if the object cannot be exactly represented
// by a 32-bit integer.
// Floating point value in the 32-bit integer range that are not exact integer
// won't be converted.
// scratch3 is not used when FPU is supported.
static void LoadNumberAsInt32(MacroAssembler* masm,
Register object,
Register dst,
Register heap_number_map,
Register scratch1,
Register scratch2,
Register scratch3,
FPURegister double_scratch0,
FPURegister double_scratch1,
Label* not_int32);
// Generates code to call a C function to do a double operation using core
// registers. (Used when FPU is not supported.)
// This code never falls through, but returns with a heap number containing
// the result in v0.
// Register heapnumber_result must be a heap number in which the
// result of the operation will be stored.
// Requires the following layout on entry:
// a0: Left value (least significant part of mantissa).
// a1: Left value (sign, exponent, top of mantissa).
// a2: Right value (least significant part of mantissa).
// a3: Right value (sign, exponent, top of mantissa).
static void CallCCodeForDoubleOperation(MacroAssembler* masm,
Token::Value op,
Register heap_number_result,
Register scratch);
// Loads the objects from |object| into floating point registers.
// Depending on |destination| the value ends up either in |dst| or
// in |dst1|/|dst2|. If |destination| is kFPURegisters, then FPU
// must be supported. If kCoreRegisters are requested and FPU is
// supported, |dst| will be scratched. If |object| is neither smi nor
// heap number, |not_number| is jumped to with |object| still intact.
static void LoadNumber(MacroAssembler* masm,
FloatingPointHelper::Destination destination,
Register object,
FPURegister dst,
Register dst1,
Register dst2,
Register heap_number_map,
Register scratch1,
Register scratch2,
Label* not_number);
};
class NameDictionaryLookupStub: public PlatformCodeStub { class NameDictionaryLookupStub: public PlatformCodeStub {
public: public:
......
...@@ -1238,7 +1238,6 @@ static void KeyedStoreGenerateGenericHelper( ...@@ -1238,7 +1238,6 @@ static void KeyedStoreGenerateGenericHelper(
a3, // Scratch regs... a3, // Scratch regs...
t0, t0,
t1, t1,
t2,
&transition_double_elements); &transition_double_elements);
if (increment_length == kIncrementLength) { if (increment_length == kIncrementLength) {
// Add 1 to receiver->length. // Add 1 to receiver->length.
......
...@@ -3266,7 +3266,7 @@ void MacroAssembler::AllocateHeapNumber(Register result, ...@@ -3266,7 +3266,7 @@ void MacroAssembler::AllocateHeapNumber(Register result,
tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS); tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS);
// Store heap number map in the allocated object. // Store heap number map in the allocated object.
AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
if (tagging_mode == TAG_RESULT) { if (tagging_mode == TAG_RESULT) {
sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset)); sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
} else { } else {
...@@ -3428,7 +3428,6 @@ void MacroAssembler::StoreNumberToDoubleElements(Register value_reg, ...@@ -3428,7 +3428,6 @@ void MacroAssembler::StoreNumberToDoubleElements(Register value_reg,
Register scratch1, Register scratch1,
Register scratch2, Register scratch2,
Register scratch3, Register scratch3,
Register scratch4,
Label* fail, Label* fail,
int elements_offset) { int elements_offset) {
Label smi_value, maybe_nan, have_double_value, is_nan, done; Label smi_value, maybe_nan, have_double_value, is_nan, done;
...@@ -3485,25 +3484,11 @@ void MacroAssembler::StoreNumberToDoubleElements(Register value_reg, ...@@ -3485,25 +3484,11 @@ void MacroAssembler::StoreNumberToDoubleElements(Register value_reg,
Addu(scratch1, scratch1, scratch2); Addu(scratch1, scratch1, scratch2);
// scratch1 is now effective address of the double element // scratch1 is now effective address of the double element
FloatingPointHelper::Destination destination;
destination = FloatingPointHelper::kFPURegisters;
Register untagged_value = elements_reg; Register untagged_value = elements_reg;
SmiUntag(untagged_value, value_reg); SmiUntag(untagged_value, value_reg);
FloatingPointHelper::ConvertIntToDouble(this, mtc1(untagged_value, f2);
untagged_value, cvt_d_w(f0, f2);
destination, sdc1(f0, MemOperand(scratch1, 0));
f0,
mantissa_reg,
exponent_reg,
scratch4,
f2);
if (destination == FloatingPointHelper::kFPURegisters) {
sdc1(f0, MemOperand(scratch1, 0));
} else {
sw(mantissa_reg, MemOperand(scratch1, 0));
sw(exponent_reg, MemOperand(scratch1, Register::kSizeInBytes));
}
bind(&done); bind(&done);
} }
...@@ -4400,15 +4385,6 @@ void MacroAssembler::Assert(Condition cc, BailoutReason reason, ...@@ -4400,15 +4385,6 @@ void MacroAssembler::Assert(Condition cc, BailoutReason reason,
} }
void MacroAssembler::AssertRegisterIsRoot(Register reg,
Heap::RootListIndex index) {
if (emit_debug_code()) {
LoadRoot(at, index);
Check(eq, kRegisterDidNotMatchExpectedRoot, reg, Operand(at));
}
}
void MacroAssembler::AssertFastElements(Register elements) { void MacroAssembler::AssertFastElements(Register elements) {
if (emit_debug_code()) { if (emit_debug_code()) {
ASSERT(!elements.is(at)); ASSERT(!elements.is(at));
...@@ -4601,6 +4577,150 @@ void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, ...@@ -4601,6 +4577,150 @@ void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
} }
void MacroAssembler::ConvertNumberToInt32(Register object,
Register dst,
Register heap_number_map,
Register scratch1,
Register scratch2,
Register scratch3,
FPURegister double_scratch,
Label* not_number) {
Label done;
Label not_in_int32_range;
UntagAndJumpIfSmi(dst, object, &done);
JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
ConvertToInt32(object,
dst,
scratch1,
scratch2,
double_scratch,
&not_in_int32_range);
jmp(&done);
bind(&not_in_int32_range);
lw(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
lw(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
EmitOutOfInt32RangeTruncate(dst,
scratch1,
scratch2,
scratch3);
bind(&done);
}
void MacroAssembler::LoadNumber(Register object,
FPURegister dst,
Register heap_number_map,
Register scratch,
Label* not_number) {
Label is_smi, done;
UntagAndJumpIfSmi(scratch, object, &is_smi);
JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number);
ldc1(dst, FieldMemOperand(object, HeapNumber::kValueOffset));
Branch(&done);
bind(&is_smi);
mtc1(scratch, dst);
cvt_d_w(dst, dst);
bind(&done);
}
void MacroAssembler::LoadNumberAsInt32Double(Register object,
DoubleRegister double_dst,
Register heap_number_map,
Register scratch1,
Register scratch2,
FPURegister double_scratch,
Label* not_int32) {
ASSERT(!scratch1.is(object) && !scratch2.is(object));
ASSERT(!scratch1.is(scratch2));
ASSERT(!heap_number_map.is(object) &&
!heap_number_map.is(scratch1) &&
!heap_number_map.is(scratch2));
Label done, obj_is_not_smi;
UntagAndJumpIfNotSmi(scratch1, object, &obj_is_not_smi);
mtc1(scratch1, double_scratch);
cvt_d_w(double_dst, double_scratch);
Branch(&done);
bind(&obj_is_not_smi);
JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
// Load the number.
// Load the double value.
ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset));
Register except_flag = scratch2;
EmitFPUTruncate(kRoundToZero,
scratch1,
double_dst,
at,
double_scratch,
except_flag,
kCheckForInexactConversion);
// Jump to not_int32 if the operation did not succeed.
Branch(not_int32, ne, except_flag, Operand(zero_reg));
bind(&done);
}
void MacroAssembler::LoadNumberAsInt32(Register object,
Register dst,
Register heap_number_map,
Register scratch1,
Register scratch2,
FPURegister double_scratch0,
FPURegister double_scratch1,
Label* not_int32) {
ASSERT(!dst.is(object));
ASSERT(!scratch1.is(object) && !scratch2.is(object));
ASSERT(!scratch1.is(scratch2));
Label done, maybe_undefined;
UntagAndJumpIfSmi(dst, object, &done);
JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined);
// Object is a heap number.
// Convert the floating point value to a 32-bit integer.
// Load the double value.
ldc1(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset));
Register except_flag = scratch2;
EmitFPUTruncate(kRoundToZero,
dst,
double_scratch0,
scratch1,
double_scratch1,
except_flag,
kCheckForInexactConversion);
// Jump to not_int32 if the operation did not succeed.
Branch(not_int32, ne, except_flag, Operand(zero_reg));
Branch(&done);
bind(&maybe_undefined);
LoadRoot(at, Heap::kUndefinedValueRootIndex);
Branch(not_int32, ne, object, Operand(at));
// |undefined| is truncated to 0.
li(dst, Operand(Smi::FromInt(0)));
// Fall through.
bind(&done);
}
void MacroAssembler::EnterFrame(StackFrame::Type type) { void MacroAssembler::EnterFrame(StackFrame::Type type) {
addiu(sp, sp, -5 * kPointerSize); addiu(sp, sp, -5 * kPointerSize);
li(t8, Operand(Smi::FromInt(type))); li(t8, Operand(Smi::FromInt(type)));
...@@ -4920,13 +5040,11 @@ void MacroAssembler::AssertName(Register object) { ...@@ -4920,13 +5040,11 @@ void MacroAssembler::AssertName(Register object) {
} }
void MacroAssembler::AssertRootValue(Register src, void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) {
Heap::RootListIndex root_value_index,
BailoutReason reason) {
if (emit_debug_code()) { if (emit_debug_code()) {
ASSERT(!src.is(at)); ASSERT(!reg.is(at));
LoadRoot(at, root_value_index); LoadRoot(at, index);
Check(eq, reason, src, Operand(at)); Check(eq, kHeapNumberMapRegisterClobbered, reg, Operand(at));
} }
} }
...@@ -4936,7 +5054,7 @@ void MacroAssembler::JumpIfNotHeapNumber(Register object, ...@@ -4936,7 +5054,7 @@ void MacroAssembler::JumpIfNotHeapNumber(Register object,
Register scratch, Register scratch,
Label* on_not_heap_number) { Label* on_not_heap_number) {
lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
Branch(on_not_heap_number, ne, scratch, Operand(heap_number_map)); Branch(on_not_heap_number, ne, scratch, Operand(heap_number_map));
} }
......
...@@ -797,6 +797,54 @@ class MacroAssembler: public Assembler { ...@@ -797,6 +797,54 @@ class MacroAssembler: public Assembler {
Register scratch2, Register scratch2,
Register scratch3); Register scratch3);
// Converts 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.
void ConvertNumberToInt32(Register object,
Register dst,
Register heap_number_map,
Register scratch1,
Register scratch2,
Register scratch3,
FPURegister double_scratch,
Label* not_int32);
// Loads the number from object into dst register.
// If |object| is neither smi nor heap number, |not_number| is jumped to
// with |object| still intact.
void LoadNumber(Register object,
FPURegister dst,
Register heap_number_map,
Register scratch,
Label* not_number);
// Loads the number from object into double_dst in the double format.
// Control will jump to not_int32 if the value cannot be exactly represented
// by a 32-bit integer.
// Floating point value in the 32-bit integer range that are not exact integer
// won't be loaded.
void LoadNumberAsInt32Double(Register object,
DoubleRegister double_dst,
Register heap_number_map,
Register scratch1,
Register scratch2,
FPURegister double_scratch,
Label* not_int32);
// Loads the number from object into dst as a 32-bit integer.
// Control will jump to not_int32 if the object cannot be exactly represented
// by a 32-bit integer.
// Floating point value in the 32-bit integer range that are not exact integer
// won't be converted.
void LoadNumberAsInt32(Register object,
Register dst,
Register heap_number_map,
Register scratch1,
Register scratch2,
FPURegister double_scratch0,
FPURegister double_scratch1,
Label* not_int32);
// Enter exit frame. // Enter exit frame.
// argc - argument count to be dropped by LeaveExitFrame. // argc - argument count to be dropped by LeaveExitFrame.
// save_doubles - saves FPU registers on stack, currently disabled. // save_doubles - saves FPU registers on stack, currently disabled.
...@@ -986,16 +1034,13 @@ class MacroAssembler: public Assembler { ...@@ -986,16 +1034,13 @@ class MacroAssembler: public Assembler {
// Check to see if maybe_number can be stored as a double in // Check to see if maybe_number can be stored as a double in
// FastDoubleElements. If it can, store it at the index specified by key in // FastDoubleElements. If it can, store it at the index specified by key in
// the FastDoubleElements array elements. Otherwise jump to fail, in which // the FastDoubleElements array elements. Otherwise jump to fail.
// case scratch2, scratch3 and scratch4 are unmodified.
void StoreNumberToDoubleElements(Register value_reg, void StoreNumberToDoubleElements(Register value_reg,
Register key_reg, Register key_reg,
// All regs below here overwritten.
Register elements_reg, Register elements_reg,
Register scratch1, Register scratch1,
Register scratch2, Register scratch2,
Register scratch3, Register scratch3,
Register scratch4,
Label* fail, Label* fail,
int elements_offset = 0); int elements_offset = 0);
...@@ -1280,7 +1325,6 @@ class MacroAssembler: public Assembler { ...@@ -1280,7 +1325,6 @@ class MacroAssembler: public Assembler {
// Calls Abort(msg) if the condition cc is not satisfied. // Calls Abort(msg) if the condition cc is not satisfied.
// Use --debug_code to enable. // Use --debug_code to enable.
void Assert(Condition cc, BailoutReason reason, Register rs, Operand rt); void Assert(Condition cc, BailoutReason reason, Register rs, Operand rt);
void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index);
void AssertFastElements(Register elements); void AssertFastElements(Register elements);
// Like Assert(), but always enabled. // Like Assert(), but always enabled.
...@@ -1367,11 +1411,9 @@ class MacroAssembler: public Assembler { ...@@ -1367,11 +1411,9 @@ class MacroAssembler: public Assembler {
// Abort execution if argument is not a name, enabled via --debug-code. // Abort execution if argument is not a name, enabled via --debug-code.
void AssertName(Register object); void AssertName(Register object);
// Abort execution if argument is not the root value with the given index, // Abort execution if reg is not the root value with the given index,
// enabled via --debug-code. // enabled via --debug-code.
void AssertRootValue(Register src, void AssertIsRoot(Register reg, Heap::RootListIndex index);
Heap::RootListIndex root_value_index,
BailoutReason reason);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// HeapNumber utilities. // HeapNumber utilities.
......
...@@ -1775,7 +1775,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall( ...@@ -1775,7 +1775,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
__ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize));
__ StoreNumberToDoubleElements( __ StoreNumberToDoubleElements(
t0, v0, elements, a3, t1, a2, t5, t0, v0, elements, a3, t1, a2,
&call_builtin, argc * kDoubleSize); &call_builtin, argc * kDoubleSize);
// Save new length. // Save new length.
......
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