Commit 2b8f5545 authored by bjaideep's avatar bjaideep Committed by Commit bot

PPC/s390: [builtins] Introduce a proper BUILTIN frame type.

Port f47b9e98

Original commit message:

    This adds a new BUILTIN frame type, which supports variable number of
    arguments for builtins implemented in hand-written native code (we will
    extend this mechanism to TurboFan builtins at some point). Convert the
    Math.max and Math.min builtins to construct a BUILTIN frame if required.

    This does not yet work for C++ builtins, but that'll be the next step.

R=jgruber@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com, mbrandy@us.ibm.com

BUG=v8:4815
LOG=N

Review-Url: https://codereview.chromium.org/2087433003
Cr-Commit-Position: refs/heads/master@{#37157}
parent d8147eb9
......@@ -38,6 +38,7 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
// Insert extra arguments.
const int num_extra_args = 2;
__ Push(r4, r6);
// JumpToExternalReference expects r3 to contain the number of arguments
// including the receiver and the extra arguments.
__ addi(r3, r3, Operand(num_extra_args + 1));
......@@ -122,6 +123,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
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) * 8] : arg[n] (zero-based)
// -- sp[(argc + 1) * 8] : receiver
......@@ -133,57 +136,69 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
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 r4 and the double value in d1.
__ LoadRoot(r4, root_index);
__ lfd(d1, FieldMemOperand(r4, HeapNumber::kValueOffset));
// +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)
__ ShiftLeftImm(r5, r3, Operand(kPointerSizeLog2));
__ add(r5, sp, r5);
__ addi(r6, r3, Operand(1));
__ addi(r7, r3, Operand(1));
Label done_loop, loop;
__ bind(&loop);
{
// Check if all parameters done.
__ cmpl(r5, sp);
__ ble(&done_loop);
__ subi(r3, r3, Operand(1));
__ cmpi(r3, Operand::Zero());
__ blt(&done_loop);
// Load the next parameter tagged value into r3.
__ LoadPU(r3, MemOperand(r5, -kPointerSize));
// Load the next parameter tagged value into r5.
__ ShiftLeftImm(r5, r3, 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(r3, &convert_smi);
__ LoadP(r7, FieldMemOperand(r3, HeapObject::kMapOffset));
__ JumpIfRoot(r7, Heap::kHeapNumberMapRootIndex, &convert_number);
__ 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.
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ SmiTag(r6);
__ Push(r4, r5, r6);
FrameScope scope(masm, StackFrame::MANUAL);
__ PushStandardFrame(r4);
__ SmiTag(r3);
__ SmiTag(r7);
__ Push(r3, r7, r8);
__ mr(r3, r5);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ Pop(r4, r5, r6);
__ SmiUntag(r6);
__ mr(r5, r3);
__ Pop(r3, r7, r8);
{
// Restore the double accumulator value (d1).
Label done_restore;
__ SmiToDouble(d1, r4);
__ JumpIfSmi(r4, &done_restore);
__ lfd(d1, FieldMemOperand(r4, HeapNumber::kValueOffset));
__ SmiToDouble(d1, r8);
__ JumpIfSmi(r8, &done_restore);
__ lfd(d1, FieldMemOperand(r8, HeapNumber::kValueOffset));
__ bind(&done_restore);
}
__ SmiUntag(r7);
__ SmiUntag(r3);
// TODO(Jaideep): Add macro furtion for PopStandardFrame
if (FLAG_enable_embedded_constant_pool) {
__ Pop(r0, fp, kConstantPoolRegister, cp, r4);
} else {
__ Pop(r0, fp, cp, r4);
}
__ mtlr(r0);
}
__ b(&convert);
__ bind(&convert_number);
__ lfd(d2, FieldMemOperand(r3, HeapNumber::kValueOffset));
__ lfd(d2, FieldMemOperand(r5, HeapNumber::kValueOffset));
__ b(&done_convert);
__ bind(&convert_smi);
__ SmiToDouble(d2, r3);
__ SmiToDouble(d2, r5);
__ bind(&done_convert);
// Perform the actual comparison with the accumulator value on the left hand
......@@ -195,26 +210,26 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
__ b(CommuteCondition(cond_done), &compare_swap);
// Left and right hand side are equal, check for -0 vs. +0.
__ TestDoubleIsMinusZero(reg, r7, r8);
__ TestDoubleIsMinusZero(reg, r9, r0);
__ bne(&loop);
// Update accumulator. Result is on the right hand side.
__ bind(&compare_swap);
__ fmr(d1, d2);
__ mr(r4, r3);
__ 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(r4, Heap::kNanValueRootIndex);
__ lfd(d1, FieldMemOperand(r4, HeapNumber::kValueOffset));
__ LoadRoot(r8, Heap::kNanValueRootIndex);
__ lfd(d1, FieldMemOperand(r8, HeapNumber::kValueOffset));
__ b(&loop);
}
__ bind(&done_loop);
__ mr(r3, r4);
__ Drop(r6);
__ mr(r3, r8);
__ Drop(r7);
__ Ret();
}
......
......@@ -115,6 +115,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
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) * 8] : arg[n] (zero-based)
// -- sp[(argc + 1) * 8] : receiver
......@@ -126,58 +128,64 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
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 r3 and the double value in d1.
__ LoadRoot(r3, root_index);
__ LoadDouble(d1, FieldMemOperand(r3, HeapNumber::kValueOffset));
// +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)
__ ShiftLeftP(r4, r2, Operand(kPointerSizeLog2));
__ AddP(r4, sp, r4);
__ AddP(r5, r2, Operand(1));
__ AddP(r6, r2, Operand(1));
Label done_loop, loop;
__ bind(&loop);
{
// Check if all parameters done.
__ CmpLogicalP(r4, sp);
__ ble(&done_loop);
__ SubP(r2, Operand(1));
__ blt(&done_loop);
// Load the next parameter tagged value into r2.
__ lay(r4, MemOperand(r4, -kPointerSize));
__ LoadP(r2, MemOperand(r4));
__ ShiftLeftP(r1, r2, 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(r2, &convert_smi);
__ LoadP(r6, FieldMemOperand(r2, HeapObject::kMapOffset));
__ JumpIfRoot(r6, Heap::kHeapNumberMapRootIndex, &convert_number);
__ 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.
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ SmiTag(r5);
__ Push(r3, r4, r5);
DCHECK(!FLAG_enable_embedded_constant_pool);
FrameScope scope(masm, StackFrame::MANUAL);
__ Push(r14, fp, cp, r3);
__ la(fp, MemOperand(sp, 2 * kPointerSize));
__ SmiTag(r2);
__ SmiTag(r6);
__ Push(r2, r6, r7);
__ LoadRR(r2, r4);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ Pop(r3, r4, r5);
__ SmiUntag(r5);
__ LoadRR(r4, r2);
__ Pop(r2, r6, r7);
{
// Restore the double accumulator value (d1).
Label done_restore;
__ SmiToDouble(d1, r3);
__ JumpIfSmi(r3, &done_restore);
__ LoadDouble(d1, FieldMemOperand(r3, HeapNumber::kValueOffset));
__ SmiToDouble(d1, r7);
__ JumpIfSmi(r7, &done_restore);
__ LoadDouble(d1, FieldMemOperand(r7, HeapNumber::kValueOffset));
__ bind(&done_restore);
}
__ SmiUntag(r6);
__ SmiUntag(r2);
__ Pop(r14, fp, cp, r3);
}
__ b(&convert);
__ bind(&convert_number);
__ LoadDouble(d2, FieldMemOperand(r2, HeapNumber::kValueOffset));
__ LoadDouble(d2, FieldMemOperand(r4, HeapNumber::kValueOffset));
__ b(&done_convert);
__ bind(&convert_smi);
__ SmiToDouble(d2, r2);
__ SmiToDouble(d2, r4);
__ bind(&done_convert);
// Perform the actual comparison with the accumulator value on the left hand
......@@ -189,26 +197,26 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
__ b(CommuteCondition(cond_done), &compare_swap);
// Left and right hand side are equal, check for -0 vs. +0.
__ TestDoubleIsMinusZero(reg, r6, r7);
__ TestDoubleIsMinusZero(reg, r1, r0);
__ bne(&loop);
// Update accumulator. Result is on the right hand side.
__ bind(&compare_swap);
__ ldr(d1, d2);
__ LoadRR(r3, r2);
__ 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(r3, Heap::kNanValueRootIndex);
__ LoadDouble(d1, FieldMemOperand(r3, HeapNumber::kValueOffset));
__ LoadRoot(r7, Heap::kNanValueRootIndex);
__ LoadDouble(d1, FieldMemOperand(r7, HeapNumber::kValueOffset));
__ b(&loop);
}
__ bind(&done_loop);
__ LoadRR(r2, r3);
__ Drop(r5);
__ LoadRR(r2, r7);
__ Drop(r6);
__ Ret();
}
......
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