Commit f47b9e98 authored by jgruber's avatar jgruber Committed by Commit bot

[builtins] Introduce a proper BUILTIN frame type.

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=bmeurer@chromium.org, jarin@chromium.org
BUG=v8:4815
LOG=n

Review-Url: https://codereview.chromium.org/2069423002
Cr-Commit-Position: refs/heads/master@{#37051}
parent 9347cae9
...@@ -140,6 +140,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) { ...@@ -140,6 +140,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : number of arguments // -- r0 : number of arguments
// -- r1 : function
// -- cp : context
// -- lr : return address // -- lr : return address
// -- sp[(argc - n) * 8] : arg[n] (zero-based) // -- sp[(argc - n) * 8] : arg[n] (zero-based)
// -- sp[(argc + 1) * 8] : receiver // -- sp[(argc + 1) * 8] : receiver
...@@ -152,9 +154,9 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -152,9 +154,9 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
DoubleRegister const reg = (kind == MathMaxMinKind::kMin) ? d2 : d1; DoubleRegister const reg = (kind == MathMaxMinKind::kMin) ? d2 : d1;
// Load the accumulator with the default return value (either -Infinity or // Load the accumulator with the default return value (either -Infinity or
// +Infinity), with the tagged value in r1 and the double value in d1. // +Infinity), with the tagged value in r5 and the double value in d1.
__ LoadRoot(r1, root_index); __ LoadRoot(r5, root_index);
__ vldr(d1, FieldMemOperand(r1, HeapNumber::kValueOffset)); __ vldr(d1, FieldMemOperand(r5, HeapNumber::kValueOffset));
// Remember how many slots to drop (including the receiver). // Remember how many slots to drop (including the receiver).
__ add(r4, r0, Operand(1)); __ add(r4, r0, Operand(1));
...@@ -178,24 +180,28 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -178,24 +180,28 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
__ JumpIfRoot(r3, Heap::kHeapNumberMapRootIndex, &convert_number); __ JumpIfRoot(r3, Heap::kHeapNumberMapRootIndex, &convert_number);
{ {
// Parameter is not a Number, use the ToNumber builtin to convert it. // Parameter is not a Number, use the ToNumber builtin to convert it.
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); DCHECK(!FLAG_enable_embedded_constant_pool);
FrameScope scope(masm, StackFrame::MANUAL);
__ Push(lr, fp, cp, r1);
__ add(fp, sp, Operand(2 * kPointerSize));
__ SmiTag(r0); __ SmiTag(r0);
__ SmiTag(r4); __ SmiTag(r4);
__ Push(r0, r1, r4); __ Push(r0, r4, r5);
__ mov(r0, r2); __ mov(r0, r2);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ mov(r2, r0); __ mov(r2, r0);
__ Pop(r0, r1, r4); __ Pop(r0, r4, r5);
{ {
// Restore the double accumulator value (d1). // Restore the double accumulator value (d1).
Label done_restore; Label done_restore;
__ SmiToDouble(d1, r1); __ SmiToDouble(d1, r5);
__ JumpIfSmi(r1, &done_restore); __ JumpIfSmi(r5, &done_restore);
__ vldr(d1, FieldMemOperand(r1, HeapNumber::kValueOffset)); __ vldr(d1, FieldMemOperand(r5, HeapNumber::kValueOffset));
__ bind(&done_restore); __ bind(&done_restore);
} }
__ SmiUntag(r4); __ SmiUntag(r4);
__ SmiUntag(r0); __ SmiUntag(r0);
__ Pop(lr, fp, cp, r1);
} }
__ b(&convert); __ b(&convert);
__ bind(&convert_number); __ bind(&convert_number);
...@@ -221,18 +227,18 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -221,18 +227,18 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// Result is on the right hand side. // Result is on the right hand side.
__ bind(&compare_swap); __ bind(&compare_swap);
__ vmov(d1, d2); __ vmov(d1, d2);
__ mov(r1, r2); __ mov(r5, r2);
__ b(&loop); __ b(&loop);
// At least one side is NaN, which means that the result will be NaN too. // At least one side is NaN, which means that the result will be NaN too.
__ bind(&compare_nan); __ bind(&compare_nan);
__ LoadRoot(r1, Heap::kNanValueRootIndex); __ LoadRoot(r5, Heap::kNanValueRootIndex);
__ vldr(d1, FieldMemOperand(r1, HeapNumber::kValueOffset)); __ vldr(d1, FieldMemOperand(r5, HeapNumber::kValueOffset));
__ b(&loop); __ b(&loop);
} }
__ bind(&done_loop); __ bind(&done_loop);
__ mov(r0, r1); __ mov(r0, r5);
__ Drop(r4); __ Drop(r4);
__ Ret(); __ Ret();
} }
......
...@@ -141,6 +141,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) { ...@@ -141,6 +141,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- x0 : number of arguments // -- x0 : number of arguments
// -- x1 : function
// -- cp : context
// -- lr : return address // -- lr : return address
// -- sp[(argc - n) * 8] : arg[n] (zero-based) // -- sp[(argc - n) * 8] : arg[n] (zero-based)
// -- sp[(argc + 1) * 8] : receiver // -- sp[(argc + 1) * 8] : receiver
...@@ -152,9 +154,9 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -152,9 +154,9 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
: Heap::kMinusInfinityValueRootIndex; : Heap::kMinusInfinityValueRootIndex;
// Load the accumulator with the default return value (either -Infinity or // Load the accumulator with the default return value (either -Infinity or
// +Infinity), with the tagged value in x1 and the double value in d1. // +Infinity), with the tagged value in x5 and the double value in d5.
__ LoadRoot(x1, root_index); __ LoadRoot(x5, root_index);
__ Ldr(d1, FieldMemOperand(x1, HeapNumber::kValueOffset)); __ Ldr(d5, FieldMemOperand(x5, HeapNumber::kValueOffset));
// Remember how many slots to drop (including the receiver). // Remember how many slots to drop (including the receiver).
__ Add(x4, x0, 1); __ Add(x4, x0, 1);
...@@ -176,24 +178,28 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -176,24 +178,28 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
__ JumpIfHeapNumber(x2, &convert_number); __ JumpIfHeapNumber(x2, &convert_number);
{ {
// Parameter is not a Number, use the ToNumber builtin to convert it. // Parameter is not a Number, use the ToNumber builtin to convert it.
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::MANUAL);
__ Push(lr, fp);
__ Move(fp, jssp);
__ Push(cp, x1);
__ SmiTag(x0); __ SmiTag(x0);
__ SmiTag(x4); __ SmiTag(x4);
__ Push(x0, x1, x4); __ Push(x0, x5, x4);
__ Mov(x0, x2); __ Mov(x0, x2);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ Mov(x2, x0); __ Mov(x2, x0);
__ Pop(x4, x1, x0); __ Pop(x4, x5, x0);
{ {
// Restore the double accumulator value (d1). // Restore the double accumulator value (d5).
Label done_restore; Label done_restore;
__ SmiUntagToDouble(d1, x1, kSpeculativeUntag); __ SmiUntagToDouble(d5, x5, kSpeculativeUntag);
__ JumpIfSmi(x1, &done_restore); __ JumpIfSmi(x5, &done_restore);
__ Ldr(d1, FieldMemOperand(x1, HeapNumber::kValueOffset)); __ Ldr(d5, FieldMemOperand(x5, HeapNumber::kValueOffset));
__ Bind(&done_restore); __ Bind(&done_restore);
} }
__ SmiUntag(x4); __ SmiUntag(x4);
__ SmiUntag(x0); __ SmiUntag(x0);
__ Pop(x1, cp, fp, lr);
} }
__ AssertNumber(x2); __ AssertNumber(x2);
__ JumpIfSmi(x2, &convert_smi); __ JumpIfSmi(x2, &convert_smi);
...@@ -208,22 +214,22 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -208,22 +214,22 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// We can use a single fmin/fmax for the operation itself, but we then need // 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. // to work out which HeapNumber (or smi) the result came from.
__ Fmov(x11, d1); __ Fmov(x11, d5);
if (kind == MathMaxMinKind::kMin) { if (kind == MathMaxMinKind::kMin) {
__ Fmin(d1, d1, d2); __ Fmin(d5, d5, d2);
} else { } else {
DCHECK(kind == MathMaxMinKind::kMax); DCHECK(kind == MathMaxMinKind::kMax);
__ Fmax(d1, d1, d2); __ Fmax(d5, d5, d2);
} }
__ Fmov(x10, d1); __ Fmov(x10, d5);
__ Cmp(x10, x11); __ Cmp(x10, x11);
__ Csel(x1, x1, x2, eq); __ Csel(x5, x5, x2, eq);
__ B(&loop); __ B(&loop);
} }
__ Bind(&done_loop); __ Bind(&done_loop);
__ Mov(x0, x1);
__ Drop(x4); __ Drop(x4);
__ Mov(x0, x5);
__ Ret(); __ Ret();
} }
......
...@@ -233,6 +233,9 @@ inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame( ...@@ -233,6 +233,9 @@ inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame(
StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) { StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) {
} }
inline BuiltinFrame::BuiltinFrame(StackFrameIteratorBase* iterator)
: JavaScriptFrame(iterator) {}
inline WasmFrame::WasmFrame(StackFrameIteratorBase* iterator) inline WasmFrame::WasmFrame(StackFrameIteratorBase* iterator)
: StandardFrame(iterator) {} : StandardFrame(iterator) {}
......
...@@ -454,10 +454,14 @@ StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, ...@@ -454,10 +454,14 @@ StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
if (code_obj->is_interpreter_trampoline_builtin()) { if (code_obj->is_interpreter_trampoline_builtin()) {
return INTERPRETED; return INTERPRETED;
} }
// We treat frames for BUILTIN Code objects as OptimizedFrame for now if (code_obj->is_turbofanned()) {
// (all the builtins with JavaScript linkage are actually generated // TODO(bmeurer): We treat frames for BUILTIN Code objects as
// with TurboFan currently, so this is sound). // OptimizedFrame for now (all the builtins with JavaScript
return OPTIMIZED; // linkage are actually generated with TurboFan currently, so
// this is sound).
return OPTIMIZED;
}
return BUILTIN;
case Code::FUNCTION: case Code::FUNCTION:
return JAVA_SCRIPT; return JAVA_SCRIPT;
case Code::OPTIMIZED_FUNCTION: case Code::OPTIMIZED_FUNCTION:
...@@ -692,6 +696,7 @@ void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { ...@@ -692,6 +696,7 @@ void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
case JAVA_SCRIPT: case JAVA_SCRIPT:
case OPTIMIZED: case OPTIMIZED:
case INTERPRETED: case INTERPRETED:
case BUILTIN:
// These frame types have a context, but they are actually stored // These frame types have a context, but they are actually stored
// in the place on the stack that one finds the frame type. // in the place on the stack that one finds the frame type.
UNREACHABLE(); UNREACHABLE();
...@@ -1289,11 +1294,6 @@ int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const { ...@@ -1289,11 +1294,6 @@ int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
return Smi::cast(GetExpression(0))->value(); return Smi::cast(GetExpression(0))->value();
} }
Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
return fp() + StandardFrameConstants::kCallerSPOffset;
}
int ArgumentsAdaptorFrame::GetLength(Address fp) { int ArgumentsAdaptorFrame::GetLength(Address fp) {
const int offset = ArgumentsAdaptorFrameConstants::kLengthOffset; const int offset = ArgumentsAdaptorFrameConstants::kLengthOffset;
return Smi::cast(Memory::Object_at(fp + offset))->value(); return Smi::cast(Memory::Object_at(fp + offset))->value();
...@@ -1304,6 +1304,15 @@ Code* ArgumentsAdaptorFrame::unchecked_code() const { ...@@ -1304,6 +1304,15 @@ Code* ArgumentsAdaptorFrame::unchecked_code() const {
Builtins::kArgumentsAdaptorTrampoline); Builtins::kArgumentsAdaptorTrampoline);
} }
void BuiltinFrame::Print(StringStream* accumulator, PrintMode mode,
int index) const {
// TODO(bmeurer)
}
int BuiltinFrame::GetNumberOfIncomingArguments() const {
return Smi::cast(GetExpression(0))->value();
}
Address InternalFrame::GetCallerStackPointer() const { Address InternalFrame::GetCallerStackPointer() const {
// Internal frames have no arguments. The stack pointer of the // Internal frames have no arguments. The stack pointer of the
// caller is at a fixed offset from the frame pointer. // caller is at a fixed offset from the frame pointer.
......
...@@ -111,7 +111,8 @@ class StackHandler BASE_EMBEDDED { ...@@ -111,7 +111,8 @@ class StackHandler BASE_EMBEDDED {
V(STUB_FAILURE_TRAMPOLINE, StubFailureTrampolineFrame) \ V(STUB_FAILURE_TRAMPOLINE, StubFailureTrampolineFrame) \
V(INTERNAL, InternalFrame) \ V(INTERNAL, InternalFrame) \
V(CONSTRUCT, ConstructFrame) \ V(CONSTRUCT, ConstructFrame) \
V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame) V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame) \
V(BUILTIN, BuiltinFrame)
// Every pointer in a frame has a slot id. On 32-bit platforms, doubles consume // Every pointer in a frame has a slot id. On 32-bit platforms, doubles consume
// two slots. // two slots.
...@@ -280,6 +281,14 @@ class ArgumentsAdaptorFrameConstants : public TypedFrameConstants { ...@@ -280,6 +281,14 @@ class ArgumentsAdaptorFrameConstants : public TypedFrameConstants {
DEFINE_TYPED_FRAME_SIZES(2); DEFINE_TYPED_FRAME_SIZES(2);
}; };
class BuiltinFrameConstants : public TypedFrameConstants {
public:
// FP-relative.
static const int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
static const int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
DEFINE_TYPED_FRAME_SIZES(2);
};
class InternalFrameConstants : public TypedFrameConstants { class InternalFrameConstants : public TypedFrameConstants {
public: public:
// FP-relative. // FP-relative.
...@@ -411,6 +420,7 @@ class StackFrame BASE_EMBEDDED { ...@@ -411,6 +420,7 @@ class StackFrame BASE_EMBEDDED {
bool is_wasm_to_js() const { return type() == WASM_TO_JS; } bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
bool is_js_to_wasm() const { return type() == JS_TO_WASM; } bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; } bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
bool is_builtin() const { return type() == BUILTIN; }
bool is_internal() const { return type() == INTERNAL; } bool is_internal() const { return type() == INTERNAL; }
bool is_stub_failure_trampoline() const { bool is_stub_failure_trampoline() const {
return type() == STUB_FAILURE_TRAMPOLINE; return type() == STUB_FAILURE_TRAMPOLINE;
...@@ -421,7 +431,7 @@ class StackFrame BASE_EMBEDDED { ...@@ -421,7 +431,7 @@ class StackFrame BASE_EMBEDDED {
bool is_java_script() const { bool is_java_script() const {
Type type = this->type(); Type type = this->type();
return (type == JAVA_SCRIPT) || (type == OPTIMIZED) || return (type == JAVA_SCRIPT) || (type == OPTIMIZED) ||
(type == INTERPRETED); (type == INTERPRETED) || (type == BUILTIN);
} }
// Accessors. // Accessors.
...@@ -950,7 +960,28 @@ class ArgumentsAdaptorFrame: public JavaScriptFrame { ...@@ -950,7 +960,28 @@ class ArgumentsAdaptorFrame: public JavaScriptFrame {
int GetNumberOfIncomingArguments() const override; int GetNumberOfIncomingArguments() const override;
Address GetCallerStackPointer() const override; private:
friend class StackFrameIteratorBase;
};
// Builtin frames are built for builtins with JavaScript linkage, such as
// various standard library functions (i.e. Math.asin, Math.floor, etc.).
class BuiltinFrame final : public JavaScriptFrame {
public:
Type type() const final { return BUILTIN; }
static BuiltinFrame* cast(StackFrame* frame) {
DCHECK(frame->is_builtin());
return static_cast<BuiltinFrame*>(frame);
}
// Printing support.
void Print(StringStream* accumulator, PrintMode mode, int index) const final;
protected:
inline explicit BuiltinFrame(StackFrameIteratorBase* iterator);
int GetNumberOfIncomingArguments() const final;
private: private:
friend class StackFrameIteratorBase; friend class StackFrameIteratorBase;
......
...@@ -1569,6 +1569,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) { ...@@ -1569,6 +1569,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : number of arguments // -- eax : number of arguments
// -- edi : function
// -- esi : context
// -- esp[0] : return address // -- esp[0] : return address
// -- esp[(argc - n) * 8] : arg[n] (zero-based) // -- esp[(argc - n) * 8] : arg[n] (zero-based)
// -- esp[(argc + 1) * 8] : receiver // -- esp[(argc + 1) * 8] : receiver
...@@ -1604,7 +1606,11 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -1604,7 +1606,11 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
Heap::kHeapNumberMapRootIndex, &convert_number); Heap::kHeapNumberMapRootIndex, &convert_number);
{ {
// Parameter is not a Number, use the ToNumber builtin to convert it. // Parameter is not a Number, use the ToNumber builtin to convert it.
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::MANUAL);
__ Push(ebp);
__ Move(ebp, esp);
__ Push(esi);
__ Push(edi);
__ SmiTag(eax); __ SmiTag(eax);
__ SmiTag(ecx); __ SmiTag(ecx);
__ Push(eax); __ Push(eax);
...@@ -1616,6 +1622,8 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -1616,6 +1622,8 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
__ Pop(edx); __ Pop(edx);
__ Pop(ecx); __ Pop(ecx);
__ Pop(eax); __ Pop(eax);
__ Pop(edi);
__ Pop(esi);
{ {
// Restore the double accumulator value (xmm0). // Restore the double accumulator value (xmm0).
Label restore_smi, done_restore; Label restore_smi, done_restore;
...@@ -1630,6 +1638,7 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -1630,6 +1638,7 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
} }
__ SmiUntag(ecx); __ SmiUntag(ecx);
__ SmiUntag(eax); __ SmiUntag(eax);
__ leave();
} }
__ jmp(&convert); __ jmp(&convert);
__ bind(&convert_number); __ bind(&convert_number);
......
...@@ -386,7 +386,8 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object, ...@@ -386,7 +386,8 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
switch (frame->type()) { switch (frame->type()) {
case StackFrame::JAVA_SCRIPT: case StackFrame::JAVA_SCRIPT:
case StackFrame::OPTIMIZED: case StackFrame::OPTIMIZED:
case StackFrame::INTERPRETED: { case StackFrame::INTERPRETED:
case StackFrame::BUILTIN: {
JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
// Set initial size to the maximum inlining level + 1 for the outermost // Set initial size to the maximum inlining level + 1 for the outermost
// function. // function.
......
...@@ -145,6 +145,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) { ...@@ -145,6 +145,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a0 : number of arguments // -- a0 : number of arguments
// -- a1 : function
// -- cp : context
// -- ra : return address // -- ra : return address
// -- sp[(argc - n) * 8] : arg[n] (zero-based) // -- sp[(argc - n) * 8] : arg[n] (zero-based)
// -- sp[(argc + 1) * 8] : receiver // -- sp[(argc + 1) * 8] : receiver
...@@ -154,9 +156,9 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -154,9 +156,9 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
: Heap::kMinusInfinityValueRootIndex; : Heap::kMinusInfinityValueRootIndex;
// Load the accumulator with the default return value (either -Infinity or // Load the accumulator with the default return value (either -Infinity or
// +Infinity), with the tagged value in a1 and the double value in f0. // +Infinity), with the tagged value in t2 and the double value in f0.
__ LoadRoot(a1, root_index); __ LoadRoot(t2, root_index);
__ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset)); __ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset));
__ Addu(a3, a0, Operand(1)); __ Addu(a3, a0, Operand(1));
Label done_loop, loop; Label done_loop, loop;
...@@ -179,26 +181,31 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -179,26 +181,31 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
__ JumpIfRoot(t0, Heap::kHeapNumberMapRootIndex, &convert_number); __ JumpIfRoot(t0, Heap::kHeapNumberMapRootIndex, &convert_number);
{ {
// Parameter is not a Number, use the ToNumber builtin to convert it. // Parameter is not a Number, use the ToNumber builtin to convert it.
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::MANUAL);
__ Push(ra, fp);
__ Move(fp, sp);
__ Push(cp, a1);
__ SmiTag(a0); __ SmiTag(a0);
__ SmiTag(a3); __ SmiTag(a3);
__ Push(a0, a1, a3); __ Push(a0, t2, a3);
__ mov(a0, a2); __ mov(a0, a2);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ mov(a2, v0); __ mov(a2, v0);
__ Pop(a0, a1, a3); __ Pop(a0, t2, a3);
{ {
// Restore the double accumulator value (f0). // Restore the double accumulator value (f0).
Label restore_smi, done_restore; Label restore_smi, done_restore;
__ JumpIfSmi(a1, &restore_smi); __ JumpIfSmi(t2, &restore_smi);
__ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset)); __ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset));
__ jmp(&done_restore); __ jmp(&done_restore);
__ bind(&restore_smi); __ bind(&restore_smi);
__ SmiToDoubleFPURegister(a1, f0, t0); __ SmiToDoubleFPURegister(t2, f0, t0);
__ bind(&done_restore); __ bind(&done_restore);
} }
__ SmiUntag(a3); __ SmiUntag(a3);
__ SmiUntag(a0); __ SmiUntag(a0);
__ Pop(cp, a1);
__ Pop(ra, fp);
} }
__ jmp(&convert); __ jmp(&convert);
__ bind(&convert_number); __ bind(&convert_number);
...@@ -226,20 +233,20 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -226,20 +233,20 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
__ Branch(&set_value, ne, t1, Operand(t8)); __ Branch(&set_value, ne, t1, Operand(t8));
__ jmp(&loop); __ jmp(&loop);
__ bind(&set_value); __ bind(&set_value);
__ mov(a1, a2); __ mov(t2, a2);
__ jmp(&loop); __ jmp(&loop);
// At least one side is NaN, which means that the result will be NaN too. // At least one side is NaN, which means that the result will be NaN too.
__ bind(&compare_nan); __ bind(&compare_nan);
__ LoadRoot(a1, Heap::kNanValueRootIndex); __ LoadRoot(t2, Heap::kNanValueRootIndex);
__ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset)); __ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset));
__ jmp(&loop); __ jmp(&loop);
} }
__ bind(&done_loop); __ bind(&done_loop);
__ Lsa(sp, sp, a3, kPointerSizeLog2); __ Lsa(sp, sp, a3, kPointerSizeLog2);
__ Ret(USE_DELAY_SLOT); __ Ret(USE_DELAY_SLOT);
__ mov(v0, a1); // In delay slot. __ mov(v0, t2); // In delay slot.
} }
// static // static
......
...@@ -144,6 +144,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) { ...@@ -144,6 +144,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a0 : number of arguments // -- a0 : number of arguments
// -- a1 : function
// -- cp : context
// -- ra : return address // -- ra : return address
// -- sp[(argc - n) * 8] : arg[n] (zero-based) // -- sp[(argc - n) * 8] : arg[n] (zero-based)
// -- sp[(argc + 1) * 8] : receiver // -- sp[(argc + 1) * 8] : receiver
...@@ -153,9 +155,9 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -153,9 +155,9 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
: Heap::kMinusInfinityValueRootIndex; : Heap::kMinusInfinityValueRootIndex;
// Load the accumulator with the default return value (either -Infinity or // Load the accumulator with the default return value (either -Infinity or
// +Infinity), with the tagged value in a1 and the double value in f0. // +Infinity), with the tagged value in t1 and the double value in f0.
__ LoadRoot(a1, root_index); __ LoadRoot(t1, root_index);
__ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset)); __ ldc1(f0, FieldMemOperand(t1, HeapNumber::kValueOffset));
__ Addu(a3, a0, 1); __ Addu(a3, a0, 1);
Label done_loop, loop; Label done_loop, loop;
...@@ -178,26 +180,31 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -178,26 +180,31 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
__ JumpIfRoot(a4, Heap::kHeapNumberMapRootIndex, &convert_number); __ JumpIfRoot(a4, Heap::kHeapNumberMapRootIndex, &convert_number);
{ {
// Parameter is not a Number, use the ToNumber builtin to convert it. // Parameter is not a Number, use the ToNumber builtin to convert it.
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::MANUAL);
__ Push(ra, fp);
__ Move(fp, sp);
__ Push(cp, a1);
__ SmiTag(a0); __ SmiTag(a0);
__ SmiTag(a3); __ SmiTag(a3);
__ Push(a0, a1, a3); __ Push(a0, t1, a3);
__ mov(a0, a2); __ mov(a0, a2);
__ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
__ mov(a2, v0); __ mov(a2, v0);
__ Pop(a0, a1, a3); __ Pop(a0, t1, a3);
{ {
// Restore the double accumulator value (f0). // Restore the double accumulator value (f0).
Label restore_smi, done_restore; Label restore_smi, done_restore;
__ JumpIfSmi(a1, &restore_smi); __ JumpIfSmi(t1, &restore_smi);
__ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset)); __ ldc1(f0, FieldMemOperand(t1, HeapNumber::kValueOffset));
__ jmp(&done_restore); __ jmp(&done_restore);
__ bind(&restore_smi); __ bind(&restore_smi);
__ SmiToDoubleFPURegister(a1, f0, a4); __ SmiToDoubleFPURegister(t1, f0, a4);
__ bind(&done_restore); __ bind(&done_restore);
} }
__ SmiUntag(a3); __ SmiUntag(a3);
__ SmiUntag(a0); __ SmiUntag(a0);
__ Pop(cp, a1);
__ Pop(ra, fp);
} }
__ jmp(&convert); __ jmp(&convert);
__ bind(&convert_number); __ bind(&convert_number);
...@@ -222,20 +229,20 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -222,20 +229,20 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
} }
__ Move(at, f0); __ Move(at, f0);
__ Branch(&loop, eq, a4, Operand(at)); __ Branch(&loop, eq, a4, Operand(at));
__ mov(a1, a2); __ mov(t1, a2);
__ jmp(&loop); __ jmp(&loop);
// At least one side is NaN, which means that the result will be NaN too. // At least one side is NaN, which means that the result will be NaN too.
__ bind(&compare_nan); __ bind(&compare_nan);
__ LoadRoot(a1, Heap::kNanValueRootIndex); __ LoadRoot(t1, Heap::kNanValueRootIndex);
__ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset)); __ ldc1(f0, FieldMemOperand(t1, HeapNumber::kValueOffset));
__ jmp(&loop); __ jmp(&loop);
} }
__ bind(&done_loop); __ bind(&done_loop);
__ Dlsa(sp, sp, a3, kPointerSizeLog2); __ Dlsa(sp, sp, a3, kPointerSizeLog2);
__ Ret(USE_DELAY_SLOT); __ Ret(USE_DELAY_SLOT);
__ mov(v0, a1); // In delay slot. __ mov(v0, t1); // In delay slot.
} }
// static // static
......
...@@ -1637,6 +1637,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) { ...@@ -1637,6 +1637,8 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : number of arguments // -- rax : number of arguments
// -- rdi : function
// -- rsi : context
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[(argc - n) * 8] : arg[n] (zero-based) // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
// -- rsp[(argc + 1) * 8] : receiver // -- rsp[(argc + 1) * 8] : receiver
...@@ -1672,7 +1674,11 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -1672,7 +1674,11 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
Heap::kHeapNumberMapRootIndex, &convert_number); Heap::kHeapNumberMapRootIndex, &convert_number);
{ {
// Parameter is not a Number, use the ToNumber builtin to convert it. // Parameter is not a Number, use the ToNumber builtin to convert it.
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::MANUAL);
__ Push(rbp);
__ Move(rbp, rsp);
__ Push(rsi);
__ Push(rdi);
__ Integer32ToSmi(rax, rax); __ Integer32ToSmi(rax, rax);
__ Integer32ToSmi(rcx, rcx); __ Integer32ToSmi(rcx, rcx);
__ Push(rax); __ Push(rax);
...@@ -1684,6 +1690,8 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -1684,6 +1690,8 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
__ Pop(rdx); __ Pop(rdx);
__ Pop(rcx); __ Pop(rcx);
__ Pop(rax); __ Pop(rax);
__ Pop(rdi);
__ Pop(rsi);
{ {
// Restore the double accumulator value (xmm0). // Restore the double accumulator value (xmm0).
Label restore_smi, done_restore; Label restore_smi, done_restore;
...@@ -1696,6 +1704,7 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { ...@@ -1696,6 +1704,7 @@ void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
} }
__ SmiToInteger32(rcx, rcx); __ SmiToInteger32(rcx, rcx);
__ SmiToInteger32(rax, rax); __ SmiToInteger32(rax, rax);
__ leave();
} }
__ jmp(&convert); __ jmp(&convert);
__ bind(&convert_number); __ bind(&convert_number);
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var thrower = { [Symbol.toPrimitive]: () => FAIL };
// Tests that a native conversion function is included in the
// stack trace.
function testTraceNativeConversion(nativeFunc) {
var nativeFuncName = nativeFunc.name;
try {
nativeFunc(thrower);
assertUnreachable(nativeFuncName);
} catch (e) {
assertTrue(e.stack.indexOf(nativeFuncName) >= 0, nativeFuncName);
}
}
testTraceNativeConversion(Math.max);
testTraceNativeConversion(Math.min);
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