A64: Tidy up register use in TaggedToI

Fix bug where input register was potentially corrupted, tidy up register use in
TruncateDoubleToI and rename TryInlineTruncateDoubleToI.

BUG=
R=ulan@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19527 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent fa63cfaf
...@@ -565,7 +565,7 @@ void DoubleToIStub::Generate(MacroAssembler* masm) { ...@@ -565,7 +565,7 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
__ Ldr(double_scratch, MemOperand(input, double_offset)); __ Ldr(double_scratch, MemOperand(input, double_offset));
// Try to convert with a FPU convert instruction. This handles all // Try to convert with a FPU convert instruction. This handles all
// non-saturating cases. // non-saturating cases.
__ TryInlineTruncateDoubleToI(result, double_scratch, &done); __ TryConvertDoubleToInt64(result, double_scratch, &done);
__ Fmov(result, double_scratch); __ Fmov(result, double_scratch);
} else { } else {
__ Ldr(result, MemOperand(input, double_offset)); __ Ldr(result, MemOperand(input, double_offset));
......
...@@ -5346,17 +5346,11 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) { ...@@ -5346,17 +5346,11 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
Register output = ToRegister(instr->result()); Register output = ToRegister(instr->result());
if (instr->hydrogen()->value()->representation().IsSmi()) { if (instr->hydrogen()->value()->representation().IsSmi()) {
__ SmiUntag(input); __ SmiUntag(output, input);
} else { } else {
DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr);
// TODO(jbramley): We can't use JumpIfNotSmi here because the tbz it uses __ JumpIfNotSmi(input, deferred->entry());
// doesn't always have enough range. Consider making a variant of it, or a
// TestIsSmi helper.
STATIC_ASSERT(kSmiTag == 0);
__ Tst(input, kSmiTagMask);
__ B(ne, deferred->entry());
__ SmiUntag(output, input); __ SmiUntag(output, input);
__ Bind(deferred->exit()); __ Bind(deferred->exit());
} }
......
...@@ -2806,20 +2806,17 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function, ...@@ -2806,20 +2806,17 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
} }
void MacroAssembler::TryInlineTruncateDoubleToI(Register result, void MacroAssembler::TryConvertDoubleToInt64(Register result,
DoubleRegister double_input, DoubleRegister double_input,
Label* done) { Label* done) {
STATIC_ASSERT(kSmiTag == 0); // Try to convert with an FPU convert instruction. It's trivial to compute
STATIC_ASSERT(kSmiValueSize == 32);
// Try to convert with a FPU convert instruction. It's trivial to compute
// the modulo operation on an integer register so we convert to a 64-bit // the modulo operation on an integer register so we convert to a 64-bit
// integer, then find the 32-bit result from that. // integer.
// //
// Fcvtzs will saturate to INT64_MIN (0x800...00) or INT64_MAX (0x7ff...ff) // Fcvtzs will saturate to INT64_MIN (0x800...00) or INT64_MAX (0x7ff...ff)
// when the double is out of range. NaNs and infinities will be converted to 0 // when the double is out of range. NaNs and infinities will be converted to 0
// (as ECMA-262 requires). // (as ECMA-262 requires).
Fcvtzs(result, double_input); Fcvtzs(result.X(), double_input);
// The values INT64_MIN (0x800...00) or INT64_MAX (0x7ff...ff) are not // The values INT64_MIN (0x800...00) or INT64_MAX (0x7ff...ff) are not
// representable using a double, so if the result is one of those then we know // representable using a double, so if the result is one of those then we know
...@@ -2827,8 +2824,8 @@ void MacroAssembler::TryInlineTruncateDoubleToI(Register result, ...@@ -2827,8 +2824,8 @@ void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
// //
// It is easy to detect INT64_MIN and INT64_MAX because adding or subtracting // It is easy to detect INT64_MIN and INT64_MAX because adding or subtracting
// 1 will cause signed overflow. // 1 will cause signed overflow.
Cmp(result, 1); Cmp(result.X(), 1);
Ccmp(result, -1, VFlag, vc); Ccmp(result.X(), -1, VFlag, vc);
B(vc, done); B(vc, done);
} }
...@@ -2839,7 +2836,9 @@ void MacroAssembler::TruncateDoubleToI(Register result, ...@@ -2839,7 +2836,9 @@ void MacroAssembler::TruncateDoubleToI(Register result,
Label done; Label done;
ASSERT(jssp.Is(StackPointer())); ASSERT(jssp.Is(StackPointer()));
TryInlineTruncateDoubleToI(result, double_input, &done); // Try to convert the double to an int64. If successful, the bottom 32 bits
// contain our truncated int32 result.
TryConvertDoubleToInt64(result, double_input, &done);
// If we fell through then inline version didn't succeed - call stub instead. // If we fell through then inline version didn't succeed - call stub instead.
Push(lr); Push(lr);
...@@ -2870,7 +2869,10 @@ void MacroAssembler::TruncateHeapNumberToI(Register result, ...@@ -2870,7 +2869,10 @@ void MacroAssembler::TruncateHeapNumberToI(Register result,
ASSERT(jssp.Is(StackPointer())); ASSERT(jssp.Is(StackPointer()));
Ldr(fp_scratch, FieldMemOperand(object, HeapNumber::kValueOffset)); Ldr(fp_scratch, FieldMemOperand(object, HeapNumber::kValueOffset));
TryInlineTruncateDoubleToI(result, fp_scratch, &done);
// Try to convert the double to an int64. If successful, the bottom 32 bits
// contain our truncated int32 result.
TryConvertDoubleToInt64(result, fp_scratch, &done);
// If we fell through then inline version didn't succeed - call stub instead. // If we fell through then inline version didn't succeed - call stub instead.
Push(lr); Push(lr);
......
...@@ -1179,16 +1179,18 @@ class MacroAssembler : public Assembler { ...@@ -1179,16 +1179,18 @@ class MacroAssembler : public Assembler {
// ---- Floating point helpers ---- // ---- Floating point helpers ----
// Perform a conversion from a double to a signed int64. If the input fits in
// Performs a truncating conversion of a floating point number as used by // range of the 64-bit result, execution branches to done. Otherwise,
// the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it // execution falls through, and the sign of the result can be used to
// succeeds, otherwise falls through if result is saturated. On return // determine if overflow was towards positive or negative infinity.
// 'result' either holds answer, or is clobbered on fall through. //
// On successful conversion, the least significant 32 bits of the result are
// equivalent to the ECMA-262 operation "ToInt32".
// //
// Only public for the test code in test-code-stubs-a64.cc. // Only public for the test code in test-code-stubs-a64.cc.
void TryInlineTruncateDoubleToI(Register result, void TryConvertDoubleToInt64(Register result,
DoubleRegister input, DoubleRegister input,
Label* done); 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.
......
...@@ -87,7 +87,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate, ...@@ -87,7 +87,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
// Call through to the actual stub // Call through to the actual stub
if (inline_fastpath) { if (inline_fastpath) {
__ Ldr(d0, MemOperand(source_reg)); __ Ldr(d0, MemOperand(source_reg));
__ TryInlineTruncateDoubleToI(destination_reg, d0, &done); __ TryConvertDoubleToInt64(destination_reg, d0, &done);
if (destination_reg.is(source_reg)) { if (destination_reg.is(source_reg)) {
// Restore clobbered source_reg. // Restore clobbered source_reg.
__ add(source_reg, jssp, Operand(source_reg_offset)); __ add(source_reg, jssp, Operand(source_reg_offset));
......
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