Commit a8e5dd51 authored by gergely@homejinni.com's avatar gergely@homejinni.com

MIPS: Support for DoubleToIStub (truncating).

Port r16322 (8a03070)

Original commit message:
Added support for truncating DoubleToIStub and reorganize the macro-assembler
dToI operations to do the fast-path inline and the slow path by calling the
stub.

BUG=
R=gergely@homejinni.com

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

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16461 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9615b8c4
...@@ -521,6 +521,64 @@ void ConvertToDoubleStub::Generate(MacroAssembler* masm) { ...@@ -521,6 +521,64 @@ void ConvertToDoubleStub::Generate(MacroAssembler* masm) {
} }
void DoubleToIStub::Generate(MacroAssembler* masm) {
Label out_of_range, only_low, negate, done;
Register input_reg = source();
Register result_reg = destination();
int double_offset = offset();
// Account for saved regs if input is sp.
if (input_reg.is(sp)) double_offset += 3 * kPointerSize;
Register scratch =
GetRegisterThatIsNotOneOf(input_reg, result_reg);
Register scratch2 =
GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch);
Register scratch3 =
GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch2);
DoubleRegister double_scratch = kLithiumScratchDouble.low();
DoubleRegister double_input = f12;
__ Push(scratch, scratch2, scratch3);
__ ldc1(double_input, MemOperand(input_reg, double_offset));
if (!skip_fastpath()) {
// Clear cumulative exception flags and save the FCSR.
__ cfc1(scratch2, FCSR);
__ ctc1(zero_reg, FCSR);
// Try a conversion to a signed integer.
__ trunc_w_d(double_scratch, double_input);
__ mfc1(result_reg, double_scratch);
// Retrieve and restore the FCSR.
__ cfc1(scratch, FCSR);
__ ctc1(scratch2, FCSR);
// Check for overflow and NaNs.
__ And(
scratch, scratch,
kFCSROverflowFlagMask | kFCSRUnderflowFlagMask
| kFCSRInvalidOpFlagMask);
// If we had no exceptions we are done.
__ Branch(&done, eq, scratch, Operand(zero_reg));
}
// Load the double value and perform a manual truncation.
Register input_high = scratch2;
Register input_low = scratch3;
__ Move(input_low, input_high, double_input);
__ EmitOutOfInt32RangeTruncate(result_reg,
input_high,
input_low,
scratch);
__ bind(&done);
__ Pop(scratch, scratch2, scratch3);
__ Ret();
}
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) &&
...@@ -1532,12 +1590,12 @@ void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm, ...@@ -1532,12 +1590,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.
__ ConvertNumberToInt32( __ TruncateNumberToI(
left, a3, heap_number_map, left, a3, heap_number_map,
scratch1, scratch2, scratch3, f0, not_numbers); scratch1, scratch2, scratch3, not_numbers);
__ ConvertNumberToInt32( __ TruncateNumberToI(
right, a2, heap_number_map, right, a2, heap_number_map,
scratch1, scratch2, scratch3, f0, not_numbers); scratch1, scratch2, scratch3, not_numbers);
} }
Label result_not_a_smi; Label result_not_a_smi;
switch (op) { switch (op) {
......
...@@ -391,7 +391,7 @@ class RecordWriteStub: public PlatformCodeStub { ...@@ -391,7 +391,7 @@ class RecordWriteStub: public PlatformCodeStub {
address_(address), address_(address),
scratch0_(scratch0) { scratch0_(scratch0) {
ASSERT(!AreAliased(scratch0, object, address, no_reg)); ASSERT(!AreAliased(scratch0, object, address, no_reg));
scratch1_ = GetRegThatIsNotOneOf(object_, address_, scratch0_); scratch1_ = GetRegisterThatIsNotOneOf(object_, address_, scratch0_);
} }
void Save(MacroAssembler* masm) { void Save(MacroAssembler* masm) {
...@@ -434,19 +434,6 @@ class RecordWriteStub: public PlatformCodeStub { ...@@ -434,19 +434,6 @@ class RecordWriteStub: public PlatformCodeStub {
Register scratch0_; Register scratch0_;
Register scratch1_; Register scratch1_;
Register GetRegThatIsNotOneOf(Register r1,
Register r2,
Register r3) {
for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
Register candidate = Register::FromAllocationIndex(i);
if (candidate.is(r1)) continue;
if (candidate.is(r2)) continue;
if (candidate.is(r3)) continue;
return candidate;
}
UNREACHABLE();
return no_reg;
}
friend class RecordWriteStub; friend class RecordWriteStub;
}; };
......
...@@ -4853,7 +4853,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { ...@@ -4853,7 +4853,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
Register scratch1 = scratch0(); Register scratch1 = scratch0();
Register scratch2 = ToRegister(instr->temp()); Register scratch2 = ToRegister(instr->temp());
DoubleRegister double_scratch = double_scratch0(); DoubleRegister double_scratch = double_scratch0();
DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp3()); DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp2());
ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
...@@ -4868,11 +4868,6 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { ...@@ -4868,11 +4868,6 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
// of the if. // of the if.
if (instr->truncating()) { if (instr->truncating()) {
Register scratch3 = ToRegister(instr->temp2());
FPURegister single_scratch = double_scratch.low();
ASSERT(!scratch3.is(input_reg) &&
!scratch3.is(scratch1) &&
!scratch3.is(scratch2));
// Performs a truncating conversion of a floating point number as used by // Performs a truncating conversion of a floating point number as used by
// the JS bitwise operations. // the JS bitwise operations.
Label heap_number; Label heap_number;
...@@ -4886,14 +4881,8 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { ...@@ -4886,14 +4881,8 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
__ Branch(&done); __ Branch(&done);
__ bind(&heap_number); __ bind(&heap_number);
__ ldc1(double_scratch2, __ mov(scratch2, input_reg);
FieldMemOperand(input_reg, HeapNumber::kValueOffset)); __ TruncateHeapNumberToI(input_reg, scratch2);
__ EmitECMATruncate(input_reg,
double_scratch2,
single_scratch,
scratch1,
scratch2,
scratch3);
} else { } else {
// Deoptimize if we don't have a heap number. // Deoptimize if we don't have a heap number.
DeoptimizeIf(ne, instr->environment(), scratch1, Operand(at)); DeoptimizeIf(ne, instr->environment(), scratch1, Operand(at));
...@@ -4980,20 +4969,12 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { ...@@ -4980,20 +4969,12 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
void LCodeGen::DoDoubleToI(LDoubleToI* instr) { void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
Register result_reg = ToRegister(instr->result()); Register result_reg = ToRegister(instr->result());
Register scratch1 = scratch0(); Register scratch1 = scratch0();
Register scratch2 = ToRegister(instr->temp());
DoubleRegister double_input = ToDoubleRegister(instr->value()); DoubleRegister double_input = ToDoubleRegister(instr->value());
if (instr->truncating()) { if (instr->truncating()) {
Register scratch3 = ToRegister(instr->temp2()); __ TruncateDoubleToI(result_reg, double_input);
FPURegister single_scratch = double_scratch0().low();
__ EmitECMATruncate(result_reg,
double_input,
single_scratch,
scratch1,
scratch2,
scratch3);
} else { } else {
Register except_flag = scratch2; Register except_flag = LCodeGen::scratch1();
__ EmitFPUTruncate(kRoundToMinusInf, __ EmitFPUTruncate(kRoundToMinusInf,
result_reg, result_reg,
...@@ -5020,21 +5001,13 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { ...@@ -5020,21 +5001,13 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
Register result_reg = ToRegister(instr->result()); Register result_reg = ToRegister(instr->result());
Register scratch1 = scratch0(); Register scratch1 = LCodeGen::scratch0();
Register scratch2 = ToRegister(instr->temp());
DoubleRegister double_input = ToDoubleRegister(instr->value()); DoubleRegister double_input = ToDoubleRegister(instr->value());
if (instr->truncating()) { if (instr->truncating()) {
Register scratch3 = ToRegister(instr->temp2()); __ TruncateDoubleToI(result_reg, double_input);
FPURegister single_scratch = double_scratch0().low();
__ EmitECMATruncate(result_reg,
double_input,
single_scratch,
scratch1,
scratch2,
scratch3);
} else { } else {
Register except_flag = scratch2; Register except_flag = LCodeGen::scratch1();
__ EmitFPUTruncate(kRoundToMinusInf, __ EmitFPUTruncate(kRoundToMinusInf,
result_reg, result_reg,
......
...@@ -1844,13 +1844,10 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { ...@@ -1844,13 +1844,10 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
} else { } else {
value = UseRegister(val); value = UseRegister(val);
LOperand* temp1 = TempRegister(); LOperand* temp1 = TempRegister();
LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() LOperand* temp2 = FixedTemp(f22);
: NULL;
LOperand* temp3 = FixedTemp(f22);
res = DefineSameAsFirst(new(zone()) LTaggedToI(value, res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
temp1, temp1,
temp2, temp2));
temp3));
res = AssignEnvironment(res); res = AssignEnvironment(res);
} }
return res; return res;
...@@ -1870,14 +1867,12 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { ...@@ -1870,14 +1867,12 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
return AssignPointerMap(result); return AssignPointerMap(result);
} else if (to.IsSmi()) { } else if (to.IsSmi()) {
LOperand* value = UseRegister(instr->value()); LOperand* value = UseRegister(instr->value());
return AssignEnvironment(DefineAsRegister(new(zone()) LDoubleToSmi(value, return AssignEnvironment(
TempRegister(), TempRegister()))); DefineAsRegister(new(zone()) LDoubleToSmi(value)));
} else { } else {
ASSERT(to.IsInteger32()); ASSERT(to.IsInteger32());
LOperand* value = UseRegister(instr->value()); LOperand* value = UseRegister(instr->value());
LOperand* temp1 = TempRegister(); LDoubleToI* res = new(zone()) LDoubleToI(value);
LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL;
LDoubleToI* res = new(zone()) LDoubleToI(value, temp1, temp2);
return AssignEnvironment(DefineAsRegister(res)); return AssignEnvironment(DefineAsRegister(res));
} }
} else if (from.IsInteger32()) { } else if (from.IsInteger32()) {
......
...@@ -2041,17 +2041,13 @@ class LNumberTagD V8_FINAL : public LTemplateInstruction<1, 1, 2> { ...@@ -2041,17 +2041,13 @@ class LNumberTagD V8_FINAL : public LTemplateInstruction<1, 1, 2> {
}; };
class LDoubleToSmi V8_FINAL : public LTemplateInstruction<1, 1, 2> { class LDoubleToSmi V8_FINAL : public LTemplateInstruction<1, 1, 0> {
public: public:
LDoubleToSmi(LOperand* value, LOperand* temp, LOperand* temp2) { explicit LDoubleToSmi(LOperand* value) {
inputs_[0] = value; inputs_[0] = value;
temps_[0] = temp;
temps_[1] = temp2;
} }
LOperand* value() { return inputs_[0]; } LOperand* value() { return inputs_[0]; }
LOperand* temp() { return temps_[0]; }
LOperand* temp2() { return temps_[1]; }
DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi") DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi")
DECLARE_HYDROGEN_ACCESSOR(UnaryOperation) DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
...@@ -2061,17 +2057,13 @@ class LDoubleToSmi V8_FINAL : public LTemplateInstruction<1, 1, 2> { ...@@ -2061,17 +2057,13 @@ class LDoubleToSmi V8_FINAL : public LTemplateInstruction<1, 1, 2> {
// Sometimes truncating conversion from a tagged value to an int32. // Sometimes truncating conversion from a tagged value to an int32.
class LDoubleToI V8_FINAL : public LTemplateInstruction<1, 1, 2> { class LDoubleToI V8_FINAL : public LTemplateInstruction<1, 1, 0> {
public: public:
LDoubleToI(LOperand* value, LOperand* temp, LOperand* temp2) { explicit LDoubleToI(LOperand* value) {
inputs_[0] = value; inputs_[0] = value;
temps_[0] = temp;
temps_[1] = temp2;
} }
LOperand* value() { return inputs_[0]; } LOperand* value() { return inputs_[0]; }
LOperand* temp() { return temps_[0]; }
LOperand* temp2() { return temps_[1]; }
DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i") DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
DECLARE_HYDROGEN_ACCESSOR(UnaryOperation) DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
...@@ -2081,22 +2073,19 @@ class LDoubleToI V8_FINAL : public LTemplateInstruction<1, 1, 2> { ...@@ -2081,22 +2073,19 @@ class LDoubleToI V8_FINAL : public LTemplateInstruction<1, 1, 2> {
// Truncating conversion from a tagged value to an int32. // Truncating conversion from a tagged value to an int32.
class LTaggedToI V8_FINAL : public LTemplateInstruction<1, 1, 3> { class LTaggedToI V8_FINAL : public LTemplateInstruction<1, 1, 2> {
public: public:
LTaggedToI(LOperand* value, LTaggedToI(LOperand* value,
LOperand* temp, LOperand* temp,
LOperand* temp2, LOperand* temp2) {
LOperand* temp3) {
inputs_[0] = value; inputs_[0] = value;
temps_[0] = temp; temps_[0] = temp;
temps_[1] = temp2; temps_[1] = temp2;
temps_[2] = temp3;
} }
LOperand* value() { return inputs_[0]; } LOperand* value() { return inputs_[0]; }
LOperand* temp() { return temps_[0]; } LOperand* temp() { return temps_[0]; }
LOperand* temp2() { return temps_[1]; } LOperand* temp2() { return temps_[1]; }
LOperand* temp3() { return temps_[2]; }
DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i") DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
DECLARE_HYDROGEN_ACCESSOR(UnaryOperation) DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
......
...@@ -1498,22 +1498,12 @@ void MacroAssembler::EmitOutOfInt32RangeTruncate(Register result, ...@@ -1498,22 +1498,12 @@ void MacroAssembler::EmitOutOfInt32RangeTruncate(Register result,
} }
void MacroAssembler::EmitECMATruncate(Register result, void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
FPURegister double_input, DoubleRegister double_input,
FPURegister single_scratch, Label* done) {
Register scratch, DoubleRegister single_scratch = kLithiumScratchDouble.low();
Register scratch2, Register scratch = at;
Register scratch3) { Register scratch2 = t9;
ASSERT(!scratch2.is(result));
ASSERT(!scratch3.is(result));
ASSERT(!scratch3.is(scratch2));
ASSERT(!scratch.is(result) &&
!scratch.is(scratch2) &&
!scratch.is(scratch3));
ASSERT(!single_scratch.is(double_input));
Label done;
Label manual;
// Clear cumulative exception flags and save the FCSR. // Clear cumulative exception flags and save the FCSR.
cfc1(scratch2, FCSR); cfc1(scratch2, FCSR);
...@@ -1529,16 +1519,83 @@ void MacroAssembler::EmitECMATruncate(Register result, ...@@ -1529,16 +1519,83 @@ void MacroAssembler::EmitECMATruncate(Register result,
scratch, scratch,
kFCSROverflowFlagMask | kFCSRUnderflowFlagMask | kFCSRInvalidOpFlagMask); kFCSROverflowFlagMask | kFCSRUnderflowFlagMask | kFCSRInvalidOpFlagMask);
// If we had no exceptions we are done. // If we had no exceptions we are done.
Branch(&done, eq, scratch, Operand(zero_reg)); Branch(done, eq, scratch, Operand(zero_reg));
}
void MacroAssembler::TruncateDoubleToI(Register result,
DoubleRegister double_input) {
Label done;
TryInlineTruncateDoubleToI(result, double_input, &done);
// If we fell through then inline version didn't succeed - call stub instead.
push(ra);
Subu(sp, sp, Operand(kDoubleSize)); // Put input on stack.
sdc1(double_input, MemOperand(sp, 0));
DoubleToIStub stub(sp, result, 0, true, true);
CallStub(&stub);
Addu(sp, sp, Operand(kDoubleSize));
pop(ra);
bind(&done);
}
// Load the double value and perform a manual truncation. void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) {
Register input_high = scratch2; Label done;
Register input_low = scratch3; DoubleRegister double_scratch = f12;
Move(input_low, input_high, double_input); ASSERT(!result.is(object));
ldc1(double_scratch,
MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag));
TryInlineTruncateDoubleToI(result, double_scratch, &done);
// If we fell through then inline version didn't succeed - call stub instead.
push(ra);
DoubleToIStub stub(object,
result,
HeapNumber::kValueOffset - kHeapObjectTag,
true,
true);
CallStub(&stub);
pop(ra);
bind(&done);
}
void MacroAssembler::TruncateNumberToI(Register object,
Register result,
Register heap_number_map,
Register scratch1,
Register scratch2,
Register scratch3,
Label* not_number) {
Label done;
Label not_in_int32_range;
DoubleRegister double_scratch = f12;
UntagAndJumpIfSmi(result, object, &done);
JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
ConvertToInt32(object,
result,
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(result, EmitOutOfInt32RangeTruncate(result,
input_high, scratch1,
input_low, scratch2,
scratch); scratch3);
bind(&done); bind(&done);
} }
...@@ -4577,40 +4634,6 @@ void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, ...@@ -4577,40 +4634,6 @@ 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, void MacroAssembler::LoadNumber(Register object,
FPURegister dst, FPURegister dst,
Register heap_number_map, Register heap_number_map,
...@@ -5642,6 +5665,30 @@ void MacroAssembler::TestJSArrayForAllocationMemento( ...@@ -5642,6 +5665,30 @@ void MacroAssembler::TestJSArrayForAllocationMemento(
} }
Register GetRegisterThatIsNotOneOf(Register reg1,
Register reg2,
Register reg3,
Register reg4,
Register reg5,
Register reg6) {
RegList regs = 0;
if (reg1.is_valid()) regs |= reg1.bit();
if (reg2.is_valid()) regs |= reg2.bit();
if (reg3.is_valid()) regs |= reg3.bit();
if (reg4.is_valid()) regs |= reg4.bit();
if (reg5.is_valid()) regs |= reg5.bit();
if (reg6.is_valid()) regs |= reg6.bit();
for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
Register candidate = Register::FromAllocationIndex(i);
if (regs & candidate.bit()) continue;
return candidate;
}
UNREACHABLE();
return no_reg;
}
bool AreAliased(Register r1, Register r2, Register r3, Register r4) { bool AreAliased(Register r1, Register r2, Register r3, Register r4) {
if (r1.is(r2)) return true; if (r1.is(r2)) return true;
if (r1.is(r3)) return true; if (r1.is(r3)) return true;
......
...@@ -90,6 +90,13 @@ enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; ...@@ -90,6 +90,13 @@ enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK }; enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
enum RAStatus { kRAHasNotBeenSaved, kRAHasBeenSaved }; enum RAStatus { kRAHasNotBeenSaved, kRAHasBeenSaved };
Register GetRegisterThatIsNotOneOf(Register reg1,
Register reg2 = no_reg,
Register reg3 = no_reg,
Register reg4 = no_reg,
Register reg5 = no_reg,
Register reg6 = no_reg);
bool AreAliased(Register r1, Register r2, Register r3, Register r4); bool AreAliased(Register r1, Register r2, Register r3, Register r4);
...@@ -787,27 +794,37 @@ class MacroAssembler: public Assembler { ...@@ -787,27 +794,37 @@ class MacroAssembler: public Assembler {
Register input_low, Register input_low,
Register scratch); Register scratch);
// Performs a truncating conversion of a floating point number as used by
// the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
// succeeds, otherwise falls through if result is saturated. On return
// 'result' either holds answer, or is clobbered on fall through.
//
// Only public for the test code in test-code-stubs-arm.cc.
void TryInlineTruncateDoubleToI(Register result,
DoubleRegister input,
Label* done);
// Performs a truncating conversion of a floating point number as used by // Performs a truncating conversion of a floating point number as used by
// the JS bitwise operations. See ECMA-262 9.5: ToInt32. // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
// Exits with 'result' holding the answer and all other registers clobbered. // Exits with 'result' holding the answer.
void EmitECMATruncate(Register result, void TruncateDoubleToI(Register result, DoubleRegister double_input);
FPURegister double_input,
FPURegister single_scratch, // Performs a truncating conversion of a heap number as used by
Register scratch, // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input'
Register scratch2, // must be different registers. Exits with 'result' holding the answer.
Register scratch3); void TruncateHeapNumberToI(Register result, Register object);
// Converts the smi or heap number in object to an int32 using the rules // 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 // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
// and brought into the range -2^31 .. +2^31 - 1. // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be
void ConvertNumberToInt32(Register object, // different registers.
Register dst, void TruncateNumberToI(Register object,
Register heap_number_map, Register result,
Register scratch1, Register heap_number_map,
Register scratch2, Register scratch1,
Register scratch3, Register scratch2,
FPURegister double_scratch, Register scratch3,
Label* not_int32); Label* not_int32);
// Loads the number from object into dst register. // Loads the number from object into dst register.
// If |object| is neither smi nor heap number, |not_number| is jumped to // If |object| is neither smi nor heap number, |not_number| is jumped to
......
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