Commit 49ff8c1d authored by vabr's avatar vabr Committed by Commit bot

Migrate Math.Min/Max to CodeStubAssembler

BUG=v8:6026

Review-Url: https://codereview.chromium.org/2728463006
Cr-Commit-Position: refs/heads/master@{#43600}
parent fcce4797
......@@ -119,112 +119,6 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e -------------
// -- r0 : number of arguments
// -- r1 : function
// -- cp : context
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
Condition const cc_done = (kind == MathMaxMinKind::kMin) ? mi : gt;
Condition const cc_swap = (kind == MathMaxMinKind::kMin) ? gt : mi;
Heap::RootListIndex const root_index =
(kind == MathMaxMinKind::kMin) ? Heap::kInfinityValueRootIndex
: Heap::kMinusInfinityValueRootIndex;
DoubleRegister const reg = (kind == MathMaxMinKind::kMin) ? d2 : d1;
// Load the accumulator with the default return value (either -Infinity or
// +Infinity), with the tagged value in r5 and the double value in d1.
__ LoadRoot(r5, root_index);
__ vldr(d1, FieldMemOperand(r5, HeapNumber::kValueOffset));
Label done_loop, loop;
__ mov(r4, r0);
__ bind(&loop);
{
// Check if all parameters done.
__ sub(r4, r4, Operand(1), SetCC);
__ b(lt, &done_loop);
// Load the next parameter tagged value into r2.
__ ldr(r2, MemOperand(sp, r4, LSL, kPointerSizeLog2));
// Load the double value of the parameter into d2, maybe converting the
// parameter to a number first using the ToNumber builtin if necessary.
Label convert, convert_smi, convert_number, done_convert;
__ bind(&convert);
__ JumpIfSmi(r2, &convert_smi);
__ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
__ JumpIfRoot(r3, Heap::kHeapNumberMapRootIndex, &convert_number);
{
// Parameter is not a Number, use the ToNumber builtin to convert it.
DCHECK(!FLAG_enable_embedded_constant_pool);
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r0);
__ SmiTag(r4);
__ EnterBuiltinFrame(cp, r1, r0);
__ Push(r4, r5);
__ mov(r0, r2);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ mov(r2, r0);
__ Pop(r4, r5);
__ LeaveBuiltinFrame(cp, r1, r0);
__ SmiUntag(r4);
__ SmiUntag(r0);
{
// Restore the double accumulator value (d1).
Label done_restore;
__ SmiToDouble(d1, r5);
__ JumpIfSmi(r5, &done_restore);
__ vldr(d1, FieldMemOperand(r5, HeapNumber::kValueOffset));
__ bind(&done_restore);
}
}
__ b(&convert);
__ bind(&convert_number);
__ vldr(d2, FieldMemOperand(r2, HeapNumber::kValueOffset));
__ b(&done_convert);
__ bind(&convert_smi);
__ SmiToDouble(d2, r2);
__ bind(&done_convert);
// Perform the actual comparison with the accumulator value on the left hand
// side (d1) and the next parameter value on the right hand side (d2).
Label compare_nan, compare_swap;
__ VFPCompareAndSetFlags(d1, d2);
__ b(cc_done, &loop);
__ b(cc_swap, &compare_swap);
__ b(vs, &compare_nan);
// Left and right hand side are equal, check for -0 vs. +0.
__ VmovHigh(ip, reg);
__ cmp(ip, Operand(0x80000000));
__ b(ne, &loop);
// Result is on the right hand side.
__ bind(&compare_swap);
__ vmov(d1, d2);
__ mov(r5, r2);
__ b(&loop);
// At least one side is NaN, which means that the result will be NaN too.
__ bind(&compare_nan);
__ LoadRoot(r5, Heap::kNanValueRootIndex);
__ vldr(d1, FieldMemOperand(r5, HeapNumber::kValueOffset));
__ b(&loop);
}
__ bind(&done_loop);
// Drop all slots, including the receiver.
__ add(r0, r0, Operand(1));
__ Drop(r0);
__ mov(r0, r5);
__ Ret();
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -117,100 +117,6 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e -------------
// -- x0 : number of arguments
// -- x1 : function
// -- cp : context
// -- lr : return address
// -- sp[(argc - n - 1) * 8] : arg[n] (zero-based)
// -- sp[argc * 8] : receiver
// -----------------------------------
ASM_LOCATION("Builtins::Generate_MathMaxMin");
Heap::RootListIndex const root_index =
(kind == MathMaxMinKind::kMin) ? Heap::kInfinityValueRootIndex
: Heap::kMinusInfinityValueRootIndex;
// Load the accumulator with the default return value (either -Infinity or
// +Infinity), with the tagged value in x5 and the double value in d5.
__ LoadRoot(x5, root_index);
__ Ldr(d5, FieldMemOperand(x5, HeapNumber::kValueOffset));
Label done_loop, loop;
__ mov(x4, x0);
__ Bind(&loop);
{
// Check if all parameters done.
__ Subs(x4, x4, 1);
__ B(lt, &done_loop);
// Load the next parameter tagged value into x2.
__ Peek(x2, Operand(x4, LSL, kPointerSizeLog2));
// Load the double value of the parameter into d2, maybe converting the
// parameter to a number first using the ToNumber builtin if necessary.
Label convert_smi, convert_number, done_convert;
__ JumpIfSmi(x2, &convert_smi);
__ JumpIfHeapNumber(x2, &convert_number);
{
// Parameter is not a Number, use the ToNumber builtin to convert it.
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(x0);
__ SmiTag(x4);
__ EnterBuiltinFrame(cp, x1, x0);
__ Push(x5, x4);
__ Mov(x0, x2);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ Mov(x2, x0);
__ Pop(x4, x5);
__ LeaveBuiltinFrame(cp, x1, x0);
__ SmiUntag(x4);
__ SmiUntag(x0);
{
// Restore the double accumulator value (d5).
Label done_restore;
__ SmiUntagToDouble(d5, x5, kSpeculativeUntag);
__ JumpIfSmi(x5, &done_restore);
__ Ldr(d5, FieldMemOperand(x5, HeapNumber::kValueOffset));
__ Bind(&done_restore);
}
}
__ AssertNumber(x2);
__ JumpIfSmi(x2, &convert_smi);
__ Bind(&convert_number);
__ Ldr(d2, FieldMemOperand(x2, HeapNumber::kValueOffset));
__ B(&done_convert);
__ Bind(&convert_smi);
__ SmiUntagToDouble(d2, x2);
__ Bind(&done_convert);
// We can use a single fmin/fmax for the operation itself, but we then need
// to work out which HeapNumber (or smi) the result came from.
__ Fmov(x11, d5);
if (kind == MathMaxMinKind::kMin) {
__ Fmin(d5, d5, d2);
} else {
DCHECK(kind == MathMaxMinKind::kMax);
__ Fmax(d5, d5, d2);
}
__ Fmov(x10, d5);
__ Cmp(x10, x11);
__ Csel(x5, x5, x2, eq);
__ B(&loop);
}
__ Bind(&done_loop);
// Drop all slots, including the receiver.
__ Add(x0, x0, 1);
__ Drop(x0);
__ Mov(x0, x5);
__ Ret();
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -23,6 +23,8 @@ class MathBuiltinsAssembler : public CodeStubAssembler {
protected:
void MathRoundingOperation(Node* (CodeStubAssembler::*float64op)(Node*));
void MathUnaryOperation(Node* (CodeStubAssembler::*float64op)(Node*));
void MathMaxMin(Node* (CodeStubAssembler::*float64op)(Node*, Node*),
double default_val);
};
// ES6 section - 20.2.2.1 Math.abs ( x )
......@@ -163,6 +165,26 @@ void MathBuiltinsAssembler::MathUnaryOperation(
Return(result);
}
void MathBuiltinsAssembler::MathMaxMin(
Node* (CodeStubAssembler::*float64op)(Node*, Node*), double default_val) {
Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
Node* context = Parameter(BuiltinDescriptor::kContext);
CodeStubArguments arguments(this, ChangeInt32ToIntPtr(argc));
argc = arguments.GetLength();
Variable result(this, MachineRepresentation::kFloat64);
result.Bind(Float64Constant(default_val));
CodeStubAssembler::VariableList vars({&result}, zone());
arguments.ForEach(vars, [this, float64op, context, &result](Node* arg) {
Node* float_value = TruncateTaggedToFloat64(context, arg);
result.Bind((this->*float64op)(result.value(), float_value));
});
arguments.PopAndReturn(ChangeFloat64ToTagged(result.value()));
}
// ES6 section 20.2.2.2 Math.acos ( x )
TF_BUILTIN(MathAcos, MathBuiltinsAssembler) {
MathUnaryOperation(&CodeStubAssembler::Float64Acos);
......@@ -494,12 +516,14 @@ TF_BUILTIN(MathTrunc, MathBuiltinsAssembler) {
MathRoundingOperation(&CodeStubAssembler::Float64Trunc);
}
void Builtins::Generate_MathMax(MacroAssembler* masm) {
Generate_MathMaxMin(masm, MathMaxMinKind::kMax);
// ES6 section 20.2.2.24 Math.max ( value1, value2 , ...values )
TF_BUILTIN(MathMax, MathBuiltinsAssembler) {
MathMaxMin(&CodeStubAssembler::Float64Max, -1.0 * V8_INFINITY);
}
void Builtins::Generate_MathMin(MacroAssembler* masm) {
Generate_MathMaxMin(masm, MathMaxMinKind::kMin);
// ES6 section 20.2.2.25 Math.min ( value1, value2 , ...values )
TF_BUILTIN(MathMin, MathBuiltinsAssembler) {
MathMaxMin(&CodeStubAssembler::Float64Min, V8_INFINITY);
}
} // namespace internal
......
......@@ -538,9 +538,9 @@ class Isolate;
/* ES6 section 20.2.2.23 Math.log2 ( x ) */ \
TFJ(MathLog2, 1) \
/* ES6 section 20.2.2.24 Math.max ( value1, value2 , ...values ) */ \
ASM(MathMax) \
TFJ(MathMax, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 section 20.2.2.25 Math.min ( value1, value2 , ...values ) */ \
ASM(MathMin) \
TFJ(MathMin, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 section 20.2.2.26 Math.pow ( x, y ) */ \
TFJ(MathPow, 2) \
/* ES6 section 20.2.2.27 Math.random */ \
......@@ -972,9 +972,6 @@ class Builtins {
static void Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, InterpreterPushArgsMode mode);
enum class MathMaxMinKind { kMax, kMin };
static void Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind);
#define DECLARE_ASM(Name, ...) \
static void Generate_##Name(MacroAssembler* masm);
#define DECLARE_TF(Name, ...) \
......
......@@ -1718,125 +1718,6 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e -------------
// -- eax : number of arguments
// -- edi : function
// -- esi : context
// -- esp[0] : return address
// -- esp[(argc - n) * 8] : arg[n] (zero-based)
// -- esp[(argc + 1) * 8] : receiver
// -----------------------------------
Condition const cc = (kind == MathMaxMinKind::kMin) ? below : above;
Heap::RootListIndex const root_index =
(kind == MathMaxMinKind::kMin) ? Heap::kInfinityValueRootIndex
: Heap::kMinusInfinityValueRootIndex;
XMMRegister const reg = (kind == MathMaxMinKind::kMin) ? xmm1 : xmm0;
// Load the accumulator with the default return value (either -Infinity or
// +Infinity), with the tagged value in edx and the double value in xmm0.
__ LoadRoot(edx, root_index);
__ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
__ Move(ecx, eax);
Label done_loop, loop;
__ bind(&loop);
{
// Check if all parameters done.
__ test(ecx, ecx);
__ j(zero, &done_loop);
// Load the next parameter tagged value into ebx.
__ mov(ebx, Operand(esp, ecx, times_pointer_size, 0));
// Load the double value of the parameter into xmm1, maybe converting the
// parameter to a number first using the ToNumber builtin if necessary.
Label convert, convert_smi, convert_number, done_convert;
__ bind(&convert);
__ JumpIfSmi(ebx, &convert_smi);
__ JumpIfRoot(FieldOperand(ebx, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex, &convert_number);
{
// Parameter is not a Number, use the ToNumber builtin to convert it.
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(eax);
__ SmiTag(ecx);
__ EnterBuiltinFrame(esi, edi, eax);
__ Push(ecx);
__ Push(edx);
__ mov(eax, ebx);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ mov(ebx, eax);
__ Pop(edx);
__ Pop(ecx);
__ LeaveBuiltinFrame(esi, edi, eax);
__ SmiUntag(ecx);
__ SmiUntag(eax);
{
// Restore the double accumulator value (xmm0).
Label restore_smi, done_restore;
__ JumpIfSmi(edx, &restore_smi, Label::kNear);
__ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
__ jmp(&done_restore, Label::kNear);
__ bind(&restore_smi);
__ SmiUntag(edx);
__ Cvtsi2sd(xmm0, edx);
__ SmiTag(edx);
__ bind(&done_restore);
}
}
__ jmp(&convert);
__ bind(&convert_number);
__ movsd(xmm1, FieldOperand(ebx, HeapNumber::kValueOffset));
__ jmp(&done_convert, Label::kNear);
__ bind(&convert_smi);
__ SmiUntag(ebx);
__ Cvtsi2sd(xmm1, ebx);
__ SmiTag(ebx);
__ bind(&done_convert);
// Perform the actual comparison with the accumulator value on the left hand
// side (xmm0) and the next parameter value on the right hand side (xmm1).
Label compare_equal, compare_nan, compare_swap, done_compare;
__ ucomisd(xmm0, xmm1);
__ j(parity_even, &compare_nan, Label::kNear);
__ j(cc, &done_compare, Label::kNear);
__ j(equal, &compare_equal, Label::kNear);
// Result is on the right hand side.
__ bind(&compare_swap);
__ movaps(xmm0, xmm1);
__ mov(edx, ebx);
__ jmp(&done_compare, Label::kNear);
// At least one side is NaN, which means that the result will be NaN too.
__ bind(&compare_nan);
__ LoadRoot(edx, Heap::kNanValueRootIndex);
__ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
__ jmp(&done_compare, Label::kNear);
// Left and right hand side are equal, check for -0 vs. +0.
__ bind(&compare_equal);
__ Push(edi); // Preserve function in edi.
__ movmskpd(edi, reg);
__ test(edi, Immediate(1));
__ Pop(edi);
__ j(not_zero, &compare_swap);
__ bind(&done_compare);
__ dec(ecx);
__ jmp(&loop);
}
__ bind(&done_loop);
__ PopReturnAddressTo(ecx);
__ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(ecx);
__ mov(eax, edx);
__ Ret();
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -120,123 +120,6 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : function
// -- cp : context
// -- ra : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
// -- sp[argc * 4] : receiver
// -----------------------------------
Heap::RootListIndex const root_index =
(kind == MathMaxMinKind::kMin) ? Heap::kInfinityValueRootIndex
: Heap::kMinusInfinityValueRootIndex;
// Load the accumulator with the default return value (either -Infinity or
// +Infinity), with the tagged value in t2 and the double value in f0.
__ LoadRoot(t2, root_index);
__ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset));
Label done_loop, loop, done;
__ mov(a3, a0);
__ bind(&loop);
{
// Check if all parameters done.
__ Subu(a3, a3, Operand(1));
__ Branch(&done_loop, lt, a3, Operand(zero_reg));
// Load the next parameter tagged value into a2.
__ Lsa(at, sp, a3, kPointerSizeLog2);
__ lw(a2, MemOperand(at));
// Load the double value of the parameter into f2, maybe converting the
// parameter to a number first using the ToNumber builtin if necessary.
Label convert, convert_smi, convert_number, done_convert;
__ bind(&convert);
__ JumpIfSmi(a2, &convert_smi);
__ lw(t0, FieldMemOperand(a2, HeapObject::kMapOffset));
__ JumpIfRoot(t0, Heap::kHeapNumberMapRootIndex, &convert_number);
{
// Parameter is not a Number, use the ToNumber builtin to convert it.
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(a0);
__ SmiTag(a3);
__ EnterBuiltinFrame(cp, a1, a0);
__ Push(t2, a3);
__ mov(a0, a2);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ mov(a2, v0);
__ Pop(t2, a3);
__ LeaveBuiltinFrame(cp, a1, a0);
__ SmiUntag(a3);
__ SmiUntag(a0);
{
// Restore the double accumulator value (f0).
Label restore_smi, done_restore;
__ JumpIfSmi(t2, &restore_smi);
__ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset));
__ jmp(&done_restore);
__ bind(&restore_smi);
__ SmiToDoubleFPURegister(t2, f0, t0);
__ bind(&done_restore);
}
}
__ jmp(&convert);
__ bind(&convert_number);
__ ldc1(f2, FieldMemOperand(a2, HeapNumber::kValueOffset));
__ jmp(&done_convert);
__ bind(&convert_smi);
__ SmiToDoubleFPURegister(a2, f2, t0);
__ bind(&done_convert);
// Perform the actual comparison with using Min/Max macro instructions the
// accumulator value on the left hand side (f0) and the next parameter value
// on the right hand side (f2).
// We need to work out which HeapNumber (or smi) the result came from.
Label compare_nan, set_value, ool_min, ool_max;
__ BranchF(nullptr, &compare_nan, eq, f0, f2);
__ Move(t0, t1, f0);
if (kind == MathMaxMinKind::kMin) {
__ Float64Min(f0, f0, f2, &ool_min);
} else {
DCHECK(kind == MathMaxMinKind::kMax);
__ Float64Max(f0, f0, f2, &ool_max);
}
__ jmp(&done);
__ bind(&ool_min);
__ Float64MinOutOfLine(f0, f0, f2);
__ jmp(&done);
__ bind(&ool_max);
__ Float64MaxOutOfLine(f0, f0, f2);
__ bind(&done);
__ Move(at, t8, f0);
__ Branch(&set_value, ne, t0, Operand(at));
__ Branch(&set_value, ne, t1, Operand(t8));
__ jmp(&loop);
__ bind(&set_value);
__ mov(t2, a2);
__ jmp(&loop);
// At least one side is NaN, which means that the result will be NaN too.
__ bind(&compare_nan);
__ LoadRoot(t2, Heap::kNanValueRootIndex);
__ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset));
__ jmp(&loop);
}
__ bind(&done_loop);
// Drop all slots, including the receiver.
__ Addu(a0, a0, Operand(1));
__ Lsa(sp, sp, a0, kPointerSizeLog2);
__ Ret(USE_DELAY_SLOT);
__ mov(v0, t2); // In delay slot.
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -120,120 +120,6 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e -------------
// -- a0 : number of arguments
// -- a1 : function
// -- cp : context
// -- ra : return address
// -- sp[(argc - n - 1) * 8] : arg[n] (zero-based)
// -- sp[argc * 8] : receiver
// -----------------------------------
Heap::RootListIndex const root_index =
(kind == MathMaxMinKind::kMin) ? Heap::kInfinityValueRootIndex
: Heap::kMinusInfinityValueRootIndex;
// Load the accumulator with the default return value (either -Infinity or
// +Infinity), with the tagged value in t1 and the double value in f0.
__ LoadRoot(t1, root_index);
__ ldc1(f0, FieldMemOperand(t1, HeapNumber::kValueOffset));
Label done_loop, loop, done;
__ mov(a3, a0);
__ bind(&loop);
{
// Check if all parameters done.
__ Dsubu(a3, a3, Operand(1));
__ Branch(&done_loop, lt, a3, Operand(zero_reg));
// Load the next parameter tagged value into a2.
__ Dlsa(at, sp, a3, kPointerSizeLog2);
__ ld(a2, MemOperand(at));
// Load the double value of the parameter into f2, maybe converting the
// parameter to a number first using the ToNumber builtin if necessary.
Label convert, convert_smi, convert_number, done_convert;
__ bind(&convert);
__ JumpIfSmi(a2, &convert_smi);
__ ld(a4, FieldMemOperand(a2, HeapObject::kMapOffset));
__ JumpIfRoot(a4, Heap::kHeapNumberMapRootIndex, &convert_number);
{
// Parameter is not a Number, use the ToNumber builtin to convert it.
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(a0);
__ SmiTag(a3);
__ EnterBuiltinFrame(cp, a1, a0);
__ Push(t1, a3);
__ mov(a0, a2);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ mov(a2, v0);
__ Pop(t1, a3);
__ LeaveBuiltinFrame(cp, a1, a0);
__ SmiUntag(a3);
__ SmiUntag(a0);
{
// Restore the double accumulator value (f0).
Label restore_smi, done_restore;
__ JumpIfSmi(t1, &restore_smi);
__ ldc1(f0, FieldMemOperand(t1, HeapNumber::kValueOffset));
__ jmp(&done_restore);
__ bind(&restore_smi);
__ SmiToDoubleFPURegister(t1, f0, a4);
__ bind(&done_restore);
}
}
__ jmp(&convert);
__ bind(&convert_number);
__ ldc1(f2, FieldMemOperand(a2, HeapNumber::kValueOffset));
__ jmp(&done_convert);
__ bind(&convert_smi);
__ SmiToDoubleFPURegister(a2, f2, a4);
__ bind(&done_convert);
// Perform the actual comparison with using Min/Max macro instructions the
// accumulator value on the left hand side (f0) and the next parameter value
// on the right hand side (f2).
// We need to work out which HeapNumber (or smi) the result came from.
Label compare_nan, ool_min, ool_max;
__ BranchF(nullptr, &compare_nan, eq, f0, f2);
__ Move(a4, f0);
if (kind == MathMaxMinKind::kMin) {
__ Float64Min(f0, f0, f2, &ool_min);
} else {
DCHECK(kind == MathMaxMinKind::kMax);
__ Float64Max(f0, f0, f2, &ool_max);
}
__ jmp(&done);
__ bind(&ool_min);
__ Float64MinOutOfLine(f0, f0, f2);
__ jmp(&done);
__ bind(&ool_max);
__ Float64MaxOutOfLine(f0, f0, f2);
__ bind(&done);
__ Move(at, f0);
__ Branch(&loop, eq, a4, Operand(at));
__ mov(t1, a2);
__ jmp(&loop);
// At least one side is NaN, which means that the result will be NaN too.
__ bind(&compare_nan);
__ LoadRoot(t1, Heap::kNanValueRootIndex);
__ ldc1(f0, FieldMemOperand(t1, HeapNumber::kValueOffset));
__ jmp(&loop);
}
__ bind(&done_loop);
// Drop all slots, including the receiver.
__ Daddu(a0, a0, Operand(1));
__ Dlsa(sp, sp, a0, kPointerSizeLog2);
__ Ret(USE_DELAY_SLOT);
__ mov(v0, t1); // In delay slot.
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -116,117 +116,6 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e -------------
// -- r3 : number of arguments
// -- r4 : function
// -- cp : context
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
Condition const cond_done = (kind == MathMaxMinKind::kMin) ? lt : gt;
Heap::RootListIndex const root_index =
(kind == MathMaxMinKind::kMin) ? Heap::kInfinityValueRootIndex
: Heap::kMinusInfinityValueRootIndex;
DoubleRegister const reg = (kind == MathMaxMinKind::kMin) ? d2 : d1;
// Load the accumulator with the default return value (either -Infinity or
// +Infinity), with the tagged value in r8 and the double value in d1.
__ LoadRoot(r8, root_index);
__ lfd(d1, FieldMemOperand(r8, HeapNumber::kValueOffset));
// Setup state for loop
// r5: address of arg[0] + kPointerSize
// r6: number of slots to drop at exit (arguments + receiver)
__ addi(r7, r3, Operand(1));
Label done_loop, loop;
__ mr(r7, r3);
__ bind(&loop);
{
// Check if all parameters done.
__ subi(r7, r7, Operand(1));
__ cmpi(r7, Operand::Zero());
__ blt(&done_loop);
// Load the next parameter tagged value into r5.
__ ShiftLeftImm(r5, r7, Operand(kPointerSizeLog2));
__ LoadPX(r5, MemOperand(sp, r5));
// Load the double value of the parameter into d2, maybe converting the
// parameter to a number first using the ToNumber builtin if necessary.
Label convert, convert_smi, convert_number, done_convert;
__ bind(&convert);
__ JumpIfSmi(r5, &convert_smi);
__ LoadP(r6, FieldMemOperand(r5, HeapObject::kMapOffset));
__ JumpIfRoot(r6, Heap::kHeapNumberMapRootIndex, &convert_number);
{
// Parameter is not a Number, use the ToNumber builtin to convert it.
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r3);
__ SmiTag(r7);
__ EnterBuiltinFrame(cp, r4, r3);
__ Push(r7, r8);
__ mr(r3, r5);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ mr(r5, r3);
__ Pop(r7, r8);
__ LeaveBuiltinFrame(cp, r4, r3);
__ SmiUntag(r7);
__ SmiUntag(r3);
{
// Restore the double accumulator value (d1).
Label done_restore;
__ SmiToDouble(d1, r8);
__ JumpIfSmi(r8, &done_restore);
__ lfd(d1, FieldMemOperand(r8, HeapNumber::kValueOffset));
__ bind(&done_restore);
}
}
__ b(&convert);
__ bind(&convert_number);
__ lfd(d2, FieldMemOperand(r5, HeapNumber::kValueOffset));
__ b(&done_convert);
__ bind(&convert_smi);
__ SmiToDouble(d2, r5);
__ bind(&done_convert);
// Perform the actual comparison with the accumulator value on the left hand
// side (d1) and the next parameter value on the right hand side (d2).
Label compare_nan, compare_swap;
__ fcmpu(d1, d2);
__ bunordered(&compare_nan);
__ b(cond_done, &loop);
__ b(CommuteCondition(cond_done), &compare_swap);
// Left and right hand side are equal, check for -0 vs. +0.
__ TestDoubleIsMinusZero(reg, r9, r0);
__ bne(&loop);
// Update accumulator. Result is on the right hand side.
__ bind(&compare_swap);
__ fmr(d1, d2);
__ mr(r8, r5);
__ b(&loop);
// At least one side is NaN, which means that the result will be NaN too.
// We still need to visit the rest of the arguments.
__ bind(&compare_nan);
__ LoadRoot(r8, Heap::kNanValueRootIndex);
__ lfd(d1, FieldMemOperand(r8, HeapNumber::kValueOffset));
__ b(&loop);
}
__ bind(&done_loop);
// Drop all slots, including the receiver.
__ addi(r3, r3, Operand(1));
__ Drop(r3);
__ mr(r3, r8);
__ Ret();
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -116,117 +116,6 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e -------------
// -- r2 : number of arguments
// -- r3 : function
// -- cp : context
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
Condition const cond_done = (kind == MathMaxMinKind::kMin) ? lt : gt;
Heap::RootListIndex const root_index =
(kind == MathMaxMinKind::kMin) ? Heap::kInfinityValueRootIndex
: Heap::kMinusInfinityValueRootIndex;
DoubleRegister const reg = (kind == MathMaxMinKind::kMin) ? d2 : d1;
// Load the accumulator with the default return value (either -Infinity or
// +Infinity), with the tagged value in r7 and the double value in d1.
__ LoadRoot(r7, root_index);
__ LoadDouble(d1, FieldMemOperand(r7, HeapNumber::kValueOffset));
// Setup state for loop
// r4: address of arg[0] + kPointerSize
// r5: number of slots to drop at exit (arguments + receiver)
__ AddP(r6, r2, Operand(1));
Label done_loop, loop;
__ LoadRR(r6, r2);
__ bind(&loop);
{
// Check if all parameters done.
__ SubP(r6, Operand(1));
__ blt(&done_loop);
// Load the next parameter tagged value into r2.
__ ShiftLeftP(r1, r6, Operand(kPointerSizeLog2));
__ LoadP(r4, MemOperand(sp, r1));
// Load the double value of the parameter into d2, maybe converting the
// parameter to a number first using the ToNumber builtin if necessary.
Label convert, convert_smi, convert_number, done_convert;
__ bind(&convert);
__ JumpIfSmi(r4, &convert_smi);
__ LoadP(r5, FieldMemOperand(r4, HeapObject::kMapOffset));
__ JumpIfRoot(r5, Heap::kHeapNumberMapRootIndex, &convert_number);
{
// Parameter is not a Number, use the ToNumber builtin to convert it.
DCHECK(!FLAG_enable_embedded_constant_pool);
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(r2);
__ SmiTag(r6);
__ EnterBuiltinFrame(cp, r3, r2);
__ Push(r6, r7);
__ LoadRR(r2, r4);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ LoadRR(r4, r2);
__ Pop(r6, r7);
__ LeaveBuiltinFrame(cp, r3, r2);
__ SmiUntag(r6);
__ SmiUntag(r2);
{
// Restore the double accumulator value (d1).
Label done_restore;
__ SmiToDouble(d1, r7);
__ JumpIfSmi(r7, &done_restore);
__ LoadDouble(d1, FieldMemOperand(r7, HeapNumber::kValueOffset));
__ bind(&done_restore);
}
}
__ b(&convert);
__ bind(&convert_number);
__ LoadDouble(d2, FieldMemOperand(r4, HeapNumber::kValueOffset));
__ b(&done_convert);
__ bind(&convert_smi);
__ SmiToDouble(d2, r4);
__ bind(&done_convert);
// Perform the actual comparison with the accumulator value on the left hand
// side (d1) and the next parameter value on the right hand side (d2).
Label compare_nan, compare_swap;
__ cdbr(d1, d2);
__ bunordered(&compare_nan);
__ b(cond_done, &loop);
__ b(CommuteCondition(cond_done), &compare_swap);
// Left and right hand side are equal, check for -0 vs. +0.
__ TestDoubleIsMinusZero(reg, r1, r0);
__ bne(&loop);
// Update accumulator. Result is on the right hand side.
__ bind(&compare_swap);
__ ldr(d1, d2);
__ LoadRR(r7, r4);
__ b(&loop);
// At least one side is NaN, which means that the result will be NaN too.
// We still need to visit the rest of the arguments.
__ bind(&compare_nan);
__ LoadRoot(r7, Heap::kNanValueRootIndex);
__ LoadDouble(d1, FieldMemOperand(r7, HeapNumber::kValueOffset));
__ b(&loop);
}
__ bind(&done_loop);
// Drop all slots, including the receiver.
__ AddP(r2, Operand(1));
__ Drop(r2);
__ LoadRR(r2, r7);
__ Ret();
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -1683,119 +1683,6 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e -------------
// -- rax : number of arguments
// -- rdi : function
// -- rsi : context
// -- rsp[0] : return address
// -- rsp[(argc - n) * 8] : arg[n] (zero-based)
// -- rsp[(argc + 1) * 8] : receiver
// -----------------------------------
Condition const cc = (kind == MathMaxMinKind::kMin) ? below : above;
Heap::RootListIndex const root_index =
(kind == MathMaxMinKind::kMin) ? Heap::kInfinityValueRootIndex
: Heap::kMinusInfinityValueRootIndex;
XMMRegister const reg = (kind == MathMaxMinKind::kMin) ? xmm1 : xmm0;
// Load the accumulator with the default return value (either -Infinity or
// +Infinity), with the tagged value in rdx and the double value in xmm0.
__ LoadRoot(rdx, root_index);
__ Movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
__ Move(rcx, rax);
Label done_loop, loop;
__ bind(&loop);
{
// Check if all parameters done.
__ testp(rcx, rcx);
__ j(zero, &done_loop);
// Load the next parameter tagged value into rbx.
__ movp(rbx, Operand(rsp, rcx, times_pointer_size, 0));
// Load the double value of the parameter into xmm1, maybe converting the
// parameter to a number first using the ToNumber builtin if necessary.
Label convert, convert_smi, convert_number, done_convert;
__ bind(&convert);
__ JumpIfSmi(rbx, &convert_smi);
__ JumpIfRoot(FieldOperand(rbx, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex, &convert_number);
{
// Parameter is not a Number, use the ToNumber builtin to convert it.
FrameScope scope(masm, StackFrame::MANUAL);
__ Integer32ToSmi(rax, rax);
__ Integer32ToSmi(rcx, rcx);
__ EnterBuiltinFrame(rsi, rdi, rax);
__ Push(rcx);
__ Push(rdx);
__ movp(rax, rbx);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ movp(rbx, rax);
__ Pop(rdx);
__ Pop(rcx);
__ LeaveBuiltinFrame(rsi, rdi, rax);
__ SmiToInteger32(rcx, rcx);
__ SmiToInteger32(rax, rax);
{
// Restore the double accumulator value (xmm0).
Label restore_smi, done_restore;
__ JumpIfSmi(rdx, &restore_smi, Label::kNear);
__ Movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
__ jmp(&done_restore, Label::kNear);
__ bind(&restore_smi);
__ SmiToDouble(xmm0, rdx);
__ bind(&done_restore);
}
}
__ jmp(&convert);
__ bind(&convert_number);
__ Movsd(xmm1, FieldOperand(rbx, HeapNumber::kValueOffset));
__ jmp(&done_convert, Label::kNear);
__ bind(&convert_smi);
__ SmiToDouble(xmm1, rbx);
__ bind(&done_convert);
// Perform the actual comparison with the accumulator value on the left hand
// side (xmm0) and the next parameter value on the right hand side (xmm1).
Label compare_equal, compare_nan, compare_swap, done_compare;
__ Ucomisd(xmm0, xmm1);
__ j(parity_even, &compare_nan, Label::kNear);
__ j(cc, &done_compare, Label::kNear);
__ j(equal, &compare_equal, Label::kNear);
// Result is on the right hand side.
__ bind(&compare_swap);
__ Movaps(xmm0, xmm1);
__ Move(rdx, rbx);
__ jmp(&done_compare, Label::kNear);
// At least one side is NaN, which means that the result will be NaN too.
__ bind(&compare_nan);
__ LoadRoot(rdx, Heap::kNanValueRootIndex);
__ Movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
__ jmp(&done_compare, Label::kNear);
// Left and right hand side are equal, check for -0 vs. +0.
__ bind(&compare_equal);
__ Movmskpd(kScratchRegister, reg);
__ testl(kScratchRegister, Immediate(1));
__ j(not_zero, &compare_swap);
__ bind(&done_compare);
__ decp(rcx);
__ jmp(&loop);
}
__ bind(&done_loop);
__ PopReturnAddressTo(rcx);
__ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(rcx);
__ movp(rax, rdx);
__ Ret();
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -1685,141 +1685,6 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
__ TailCallStub(&stub);
}
// static
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e -------------
// -- eax : number of arguments
// -- edi : function
// -- esi : context
// -- esp[0] : return address
// -- esp[(argc - n) * 8] : arg[n] (zero-based)
// -- esp[(argc + 1) * 8] : receiver
// -----------------------------------
Condition const cc = (kind == MathMaxMinKind::kMin) ? below : above;
Heap::RootListIndex const root_index =
(kind == MathMaxMinKind::kMin) ? Heap::kInfinityValueRootIndex
: Heap::kMinusInfinityValueRootIndex;
const int reg_sel = (kind == MathMaxMinKind::kMin) ? 1 : 0;
// Load the accumulator with the default return value (either -Infinity or
// +Infinity), with the tagged value in edx and the double value in stx_0.
__ LoadRoot(edx, root_index);
__ fld_d(FieldOperand(edx, HeapNumber::kValueOffset));
__ Move(ecx, eax);
Label done_loop, loop;
__ bind(&loop);
{
// Check if all parameters done.
__ test(ecx, ecx);
__ j(zero, &done_loop);
// Load the next parameter tagged value into ebx.
__ mov(ebx, Operand(esp, ecx, times_pointer_size, 0));
// Load the double value of the parameter into stx_1, maybe converting the
// parameter to a number first using the ToNumber builtin if necessary.
Label convert, convert_smi, convert_number, done_convert;
__ bind(&convert);
__ JumpIfSmi(ebx, &convert_smi);
__ JumpIfRoot(FieldOperand(ebx, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex, &convert_number);
{
// Parameter is not a Number, use the ToNumber builtin to convert it.
FrameScope scope(masm, StackFrame::MANUAL);
__ SmiTag(eax);
__ SmiTag(ecx);
__ EnterBuiltinFrame(esi, edi, eax);
__ Push(ecx);
__ Push(edx);
__ mov(eax, ebx);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ mov(ebx, eax);
__ Pop(edx);
__ Pop(ecx);
__ LeaveBuiltinFrame(esi, edi, eax);
__ SmiUntag(ecx);
__ SmiUntag(eax);
{
// Restore the double accumulator value (stX_0).
Label restore_smi, done_restore;
__ JumpIfSmi(edx, &restore_smi, Label::kNear);
__ fld_d(FieldOperand(edx, HeapNumber::kValueOffset));
__ jmp(&done_restore, Label::kNear);
__ bind(&restore_smi);
__ SmiUntag(edx);
__ push(edx);
__ fild_s(Operand(esp, 0));
__ pop(edx);
__ SmiTag(edx);
__ bind(&done_restore);
}
}
__ jmp(&convert);
__ bind(&convert_number);
// Load another value into stx_1
__ fld_d(FieldOperand(ebx, HeapNumber::kValueOffset));
__ fxch();
__ jmp(&done_convert, Label::kNear);
__ bind(&convert_smi);
__ SmiUntag(ebx);
__ push(ebx);
__ fild_s(Operand(esp, 0));
__ pop(ebx);
__ fxch();
__ SmiTag(ebx);
__ bind(&done_convert);
// Perform the actual comparison with the accumulator value on the left hand
// side (stx_0) and the next parameter value on the right hand side (stx_1).
Label compare_equal, compare_nan, compare_swap, done_compare;
// Duplicates the 2 float data for FCmp
__ fld(1);
__ fld(1);
__ FCmp();
__ j(parity_even, &compare_nan, Label::kNear);
__ j(cc, &done_compare, Label::kNear);
__ j(equal, &compare_equal, Label::kNear);
// Result is on the right hand side(stx_0).
__ bind(&compare_swap);
__ fxch();
__ mov(edx, ebx);
__ jmp(&done_compare, Label::kNear);
// At least one side is NaN, which means that the result will be NaN too.
__ bind(&compare_nan);
// Set the result on the right hand side (stx_0) to nan
__ fstp(0);
__ LoadRoot(edx, Heap::kNanValueRootIndex);
__ fld_d(FieldOperand(edx, HeapNumber::kValueOffset));
__ jmp(&done_compare, Label::kNear);
// Left and right hand side are equal, check for -0 vs. +0.
__ bind(&compare_equal);
// Check the sign of the value in reg_sel
__ fld(reg_sel);
__ FXamSign();
__ j(not_zero, &compare_swap);
__ bind(&done_compare);
// The right result is on the right hand side(stx_0)
// and can remove the useless stx_1 now.
__ fxch();
__ fstp(0);
__ dec(ecx);
__ jmp(&loop);
}
__ bind(&done_loop);
__ PopReturnAddressTo(ecx);
__ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
__ PushReturnAddressFrom(ecx);
__ mov(eax, edx);
__ Ret();
}
// static
void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
// ----------- S t a t e -------------
......
......@@ -85,6 +85,8 @@ typedef std::function<void()> CodeAssemblerCallback;
V(Float64Mod) \
V(Float64Atan2) \
V(Float64Pow) \
V(Float64Max) \
V(Float64Min) \
V(Float64InsertLowWord32) \
V(Float64InsertHighWord32) \
V(IntPtrAddWithOverflow) \
......
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