[builtins] Some refactoring on the builtin mechanism.
Allow to pass new.target (in addition to target) to C++ builtins, and remove some obsolete/dangerous code from the C++ builtins. R=yangguo@chromium.org Review URL: https://codereview.chromium.org/1491883002 Cr-Commit-Position: refs/heads/master@{#32505}
This commit is contained in:
parent
d4fc4a8cad
commit
4013a8df54
@ -22,7 +22,8 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
BuiltinExtraArguments extra_args) {
|
BuiltinExtraArguments extra_args) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- r0 : number of arguments excluding receiver
|
// -- r0 : number of arguments excluding receiver
|
||||||
// -- r1 : called function
|
// -- r1 : target
|
||||||
|
// -- r3 : new.target
|
||||||
// -- sp[0] : last argument
|
// -- sp[0] : last argument
|
||||||
// -- ...
|
// -- ...
|
||||||
// -- sp[4 * (argc - 1)] : first argument
|
// -- sp[4 * (argc - 1)] : first argument
|
||||||
@ -32,11 +33,21 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
|
|
||||||
// Insert extra arguments.
|
// Insert extra arguments.
|
||||||
int num_extra_args = 0;
|
int num_extra_args = 0;
|
||||||
if (extra_args == NEEDS_CALLED_FUNCTION) {
|
switch (extra_args) {
|
||||||
num_extra_args = 1;
|
case BuiltinExtraArguments::kTarget:
|
||||||
__ push(r1);
|
__ Push(r1);
|
||||||
} else {
|
++num_extra_args;
|
||||||
DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
|
break;
|
||||||
|
case BuiltinExtraArguments::kNewTarget:
|
||||||
|
__ Push(r3);
|
||||||
|
++num_extra_args;
|
||||||
|
break;
|
||||||
|
case BuiltinExtraArguments::kTargetAndNewTarget:
|
||||||
|
__ Push(r1, r3);
|
||||||
|
num_extra_args += 2;
|
||||||
|
break;
|
||||||
|
case BuiltinExtraArguments::kNone:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpToExternalReference expects r0 to contain the number of arguments
|
// JumpToExternalReference expects r0 to contain the number of arguments
|
||||||
|
@ -38,7 +38,8 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
BuiltinExtraArguments extra_args) {
|
BuiltinExtraArguments extra_args) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- x0 : number of arguments excluding receiver
|
// -- x0 : number of arguments excluding receiver
|
||||||
// -- x1 : called function
|
// -- x1 : target
|
||||||
|
// -- x3 : new target
|
||||||
// -- sp[0] : last argument
|
// -- sp[0] : last argument
|
||||||
// -- ...
|
// -- ...
|
||||||
// -- sp[4 * (argc - 1)] : first argument
|
// -- sp[4 * (argc - 1)] : first argument
|
||||||
@ -48,11 +49,21 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
|
|
||||||
// Insert extra arguments.
|
// Insert extra arguments.
|
||||||
int num_extra_args = 0;
|
int num_extra_args = 0;
|
||||||
if (extra_args == NEEDS_CALLED_FUNCTION) {
|
switch (extra_args) {
|
||||||
num_extra_args = 1;
|
case BuiltinExtraArguments::kTarget:
|
||||||
__ Push(x1);
|
__ Push(x1);
|
||||||
} else {
|
++num_extra_args;
|
||||||
DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
|
break;
|
||||||
|
case BuiltinExtraArguments::kNewTarget:
|
||||||
|
__ Push(x3);
|
||||||
|
++num_extra_args;
|
||||||
|
break;
|
||||||
|
case BuiltinExtraArguments::kTargetAndNewTarget:
|
||||||
|
__ Push(x1, x3);
|
||||||
|
num_extra_args += 2;
|
||||||
|
break;
|
||||||
|
case BuiltinExtraArguments::kNone:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpToExternalReference expects x0 to contain the number of arguments
|
// JumpToExternalReference expects x0 to contain the number of arguments
|
||||||
|
159
src/builtins.cc
159
src/builtins.cc
@ -31,7 +31,10 @@ template <BuiltinExtraArguments extra_args>
|
|||||||
class BuiltinArguments : public Arguments {
|
class BuiltinArguments : public Arguments {
|
||||||
public:
|
public:
|
||||||
BuiltinArguments(int length, Object** arguments)
|
BuiltinArguments(int length, Object** arguments)
|
||||||
: Arguments(length, arguments) { }
|
: Arguments(length, arguments) {
|
||||||
|
// Check we have at least the receiver.
|
||||||
|
DCHECK_LE(1, this->length());
|
||||||
|
}
|
||||||
|
|
||||||
Object*& operator[] (int index) {
|
Object*& operator[] (int index) {
|
||||||
DCHECK(index < length());
|
DCHECK(index < length());
|
||||||
@ -47,47 +50,64 @@ class BuiltinArguments : public Arguments {
|
|||||||
return Arguments::at<Object>(0);
|
return Arguments::at<Object>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<JSFunction> called_function() {
|
Handle<JSFunction> target();
|
||||||
STATIC_ASSERT(extra_args == NEEDS_CALLED_FUNCTION);
|
Handle<HeapObject> new_target();
|
||||||
return Arguments::at<JSFunction>(Arguments::length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the total number of arguments including the receiver (but
|
// Gets the total number of arguments including the receiver (but
|
||||||
// excluding extra arguments).
|
// excluding extra arguments).
|
||||||
int length() const {
|
int length() const;
|
||||||
STATIC_ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
|
|
||||||
return Arguments::length();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
void Verify() {
|
|
||||||
// Check we have at least the receiver.
|
|
||||||
DCHECK(Arguments::length() >= 1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Specialize BuiltinArguments for the called function extra argument.
|
// Specialize BuiltinArguments for the extra arguments.
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
int BuiltinArguments<NEEDS_CALLED_FUNCTION>::length() const {
|
int BuiltinArguments<BuiltinExtraArguments::kNone>::length() const {
|
||||||
|
return Arguments::length();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
int BuiltinArguments<BuiltinExtraArguments::kTarget>::length() const {
|
||||||
return Arguments::length() - 1;
|
return Arguments::length() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
template <>
|
template <>
|
||||||
void BuiltinArguments<NEEDS_CALLED_FUNCTION>::Verify() {
|
Handle<JSFunction> BuiltinArguments<BuiltinExtraArguments::kTarget>::target() {
|
||||||
// Check we have at least the receiver and the called function.
|
return Arguments::at<JSFunction>(Arguments::length() - 1);
|
||||||
DCHECK(Arguments::length() >= 2);
|
}
|
||||||
// Make sure cast to JSFunction succeeds.
|
|
||||||
called_function();
|
template <>
|
||||||
|
int BuiltinArguments<BuiltinExtraArguments::kNewTarget>::length() const {
|
||||||
|
return Arguments::length() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
Handle<HeapObject>
|
||||||
|
BuiltinArguments<BuiltinExtraArguments::kNewTarget>::new_target() {
|
||||||
|
return Arguments::at<HeapObject>(Arguments::length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
int BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::length()
|
||||||
|
const {
|
||||||
|
return Arguments::length() - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
Handle<JSFunction>
|
||||||
|
BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::target() {
|
||||||
|
return Arguments::at<JSFunction>(Arguments::length() - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
Handle<HeapObject>
|
||||||
|
BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::new_target() {
|
||||||
|
return Arguments::at<HeapObject>(Arguments::length() - 1);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define DEF_ARG_TYPE(name, spec) \
|
#define DEF_ARG_TYPE(name, spec) \
|
||||||
typedef BuiltinArguments<spec> name##ArgumentsType;
|
typedef BuiltinArguments<BuiltinExtraArguments::spec> name##ArgumentsType;
|
||||||
BUILTIN_LIST_C(DEF_ARG_TYPE)
|
BUILTIN_LIST_C(DEF_ARG_TYPE)
|
||||||
#undef DEF_ARG_TYPE
|
#undef DEF_ARG_TYPE
|
||||||
|
|
||||||
@ -105,63 +125,17 @@ BUILTIN_LIST_C(DEF_ARG_TYPE)
|
|||||||
// In the body of the builtin function the arguments can be accessed
|
// In the body of the builtin function the arguments can be accessed
|
||||||
// through the BuiltinArguments object args.
|
// through the BuiltinArguments object args.
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
|
|
||||||
#define BUILTIN(name) \
|
#define BUILTIN(name) \
|
||||||
MUST_USE_RESULT static Object* Builtin_Impl_##name( \
|
MUST_USE_RESULT static Object* Builtin_Impl_##name( \
|
||||||
name##ArgumentsType args, Isolate* isolate); \
|
name##ArgumentsType args, Isolate* isolate); \
|
||||||
MUST_USE_RESULT static Object* Builtin_##name( \
|
MUST_USE_RESULT static Object* Builtin_##name( \
|
||||||
int args_length, Object** args_object, Isolate* isolate) { \
|
int args_length, Object** args_object, Isolate* isolate) { \
|
||||||
name##ArgumentsType args(args_length, args_object); \
|
name##ArgumentsType args(args_length, args_object); \
|
||||||
args.Verify(); \
|
|
||||||
return Builtin_Impl_##name(args, isolate); \
|
return Builtin_Impl_##name(args, isolate); \
|
||||||
} \
|
} \
|
||||||
MUST_USE_RESULT static Object* Builtin_Impl_##name( \
|
MUST_USE_RESULT static Object* Builtin_Impl_##name( \
|
||||||
name##ArgumentsType args, Isolate* isolate)
|
name##ArgumentsType args, Isolate* isolate)
|
||||||
|
|
||||||
#else // For release mode.
|
|
||||||
|
|
||||||
#define BUILTIN(name) \
|
|
||||||
static Object* Builtin_impl##name( \
|
|
||||||
name##ArgumentsType args, Isolate* isolate); \
|
|
||||||
static Object* Builtin_##name( \
|
|
||||||
int args_length, Object** args_object, Isolate* isolate) { \
|
|
||||||
name##ArgumentsType args(args_length, args_object); \
|
|
||||||
return Builtin_impl##name(args, isolate); \
|
|
||||||
} \
|
|
||||||
static Object* Builtin_impl##name( \
|
|
||||||
name##ArgumentsType args, Isolate* isolate)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
inline bool CalledAsConstructor(Isolate* isolate) {
|
|
||||||
// Calculate the result using a full stack frame iterator and check
|
|
||||||
// that the state of the stack is as we assume it to be in the
|
|
||||||
// code below.
|
|
||||||
StackFrameIterator it(isolate);
|
|
||||||
DCHECK(it.frame()->is_exit());
|
|
||||||
it.Advance();
|
|
||||||
StackFrame* frame = it.frame();
|
|
||||||
bool reference_result = frame->is_construct();
|
|
||||||
Address fp = Isolate::c_entry_fp(isolate->thread_local_top());
|
|
||||||
// Because we know fp points to an exit frame we can use the relevant
|
|
||||||
// part of ExitFrame::ComputeCallerState directly.
|
|
||||||
const int kCallerOffset = ExitFrameConstants::kCallerFPOffset;
|
|
||||||
Address caller_fp = Memory::Address_at(fp + kCallerOffset);
|
|
||||||
// This inlines the part of StackFrame::ComputeType that grabs the
|
|
||||||
// type of the current frame. Note that StackFrame::ComputeType
|
|
||||||
// has been specialized for each architecture so if any one of them
|
|
||||||
// changes this code has to be changed as well.
|
|
||||||
const int kMarkerOffset = StandardFrameConstants::kMarkerOffset;
|
|
||||||
const Smi* kConstructMarker = Smi::FromInt(StackFrame::CONSTRUCT);
|
|
||||||
Object* marker = Memory::Object_at(caller_fp + kMarkerOffset);
|
|
||||||
bool result = (marker == kConstructMarker);
|
|
||||||
DCHECK_EQ(result, reference_result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -306,7 +280,7 @@ inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
|
|||||||
|
|
||||||
MUST_USE_RESULT static Object* CallJsIntrinsic(
|
MUST_USE_RESULT static Object* CallJsIntrinsic(
|
||||||
Isolate* isolate, Handle<JSFunction> function,
|
Isolate* isolate, Handle<JSFunction> function,
|
||||||
BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
|
BuiltinArguments<BuiltinExtraArguments::kNone> args) {
|
||||||
HandleScope handleScope(isolate);
|
HandleScope handleScope(isolate);
|
||||||
int argc = args.length() - 1;
|
int argc = args.length() - 1;
|
||||||
ScopedVector<Handle<Object> > argv(argc);
|
ScopedVector<Handle<Object> > argv(argc);
|
||||||
@ -1764,7 +1738,7 @@ BUILTIN(SymbolConstructor_ConstructStub) {
|
|||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
// The ConstructStub is executed in the context of the caller, so we need
|
// The ConstructStub is executed in the context of the caller, so we need
|
||||||
// to enter the callee context first before raising an exception.
|
// to enter the callee context first before raising an exception.
|
||||||
isolate->set_context(args.called_function()->context());
|
isolate->set_context(args.target()->context());
|
||||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||||
isolate, NewTypeError(MessageTemplate::kNotConstructor,
|
isolate, NewTypeError(MessageTemplate::kNotConstructor,
|
||||||
isolate->factory()->Symbol_string()));
|
isolate->factory()->Symbol_string()));
|
||||||
@ -1794,11 +1768,13 @@ BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
|
|||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
template <bool is_construct>
|
template <bool is_construct>
|
||||||
MUST_USE_RESULT static MaybeHandle<Object> HandleApiCallHelper(
|
MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
|
||||||
Isolate* isolate, BuiltinArguments<NEEDS_CALLED_FUNCTION>& args) {
|
Isolate* isolate, BuiltinArguments<BuiltinExtraArguments::kTarget> args) {
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
Handle<JSFunction> function = args.called_function();
|
Handle<JSFunction> function = args.target();
|
||||||
// TODO(ishell): turn this back to a DCHECK.
|
// TODO(ishell): turn this back to a DCHECK.
|
||||||
CHECK(function->shared()->IsApiFunction());
|
CHECK(function->shared()->IsApiFunction());
|
||||||
|
|
||||||
@ -1873,10 +1849,11 @@ MUST_USE_RESULT static MaybeHandle<Object> HandleApiCallHelper(
|
|||||||
return scope.CloseAndEscape(args.receiver());
|
return scope.CloseAndEscape(args.receiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
BUILTIN(HandleApiCall) {
|
BUILTIN(HandleApiCall) {
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
DCHECK(!CalledAsConstructor(isolate));
|
|
||||||
Handle<Object> result;
|
Handle<Object> result;
|
||||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
||||||
HandleApiCallHelper<false>(isolate, args));
|
HandleApiCallHelper<false>(isolate, args));
|
||||||
@ -1886,7 +1863,6 @@ BUILTIN(HandleApiCall) {
|
|||||||
|
|
||||||
BUILTIN(HandleApiCallConstruct) {
|
BUILTIN(HandleApiCallConstruct) {
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
DCHECK(CalledAsConstructor(isolate));
|
|
||||||
Handle<Object> result;
|
Handle<Object> result;
|
||||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
||||||
HandleApiCallHelper<true>(isolate, args));
|
HandleApiCallHelper<true>(isolate, args));
|
||||||
@ -1924,11 +1900,12 @@ Handle<Code> Builtins::Call(ConvertReceiverMode mode) {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class RelocatableArguments : public BuiltinArguments<NEEDS_CALLED_FUNCTION>,
|
class RelocatableArguments
|
||||||
|
: public BuiltinArguments<BuiltinExtraArguments::kTarget>,
|
||||||
public Relocatable {
|
public Relocatable {
|
||||||
public:
|
public:
|
||||||
RelocatableArguments(Isolate* isolate, int length, Object** arguments)
|
RelocatableArguments(Isolate* isolate, int length, Object** arguments)
|
||||||
: BuiltinArguments<NEEDS_CALLED_FUNCTION>(length, arguments),
|
: BuiltinArguments<BuiltinExtraArguments::kTarget>(length, arguments),
|
||||||
Relocatable(isolate) {}
|
Relocatable(isolate) {}
|
||||||
|
|
||||||
virtual inline void IterateInstance(ObjectVisitor* v) {
|
virtual inline void IterateInstance(ObjectVisitor* v) {
|
||||||
@ -1978,12 +1955,8 @@ MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<JSFunction> function,
|
|||||||
// API. The object can be called as either a constructor (using new) or just as
|
// API. The object can be called as either a constructor (using new) or just as
|
||||||
// a function (without new).
|
// a function (without new).
|
||||||
MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
|
MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
|
||||||
Isolate* isolate,
|
Isolate* isolate, bool is_construct_call,
|
||||||
bool is_construct_call,
|
BuiltinArguments<BuiltinExtraArguments::kNone> args) {
|
||||||
BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
|
|
||||||
// Non-functions are never called as constructors. Even if this is an object
|
|
||||||
// called as a constructor the delegate call is not a construct call.
|
|
||||||
DCHECK(!CalledAsConstructor(isolate));
|
|
||||||
Heap* heap = isolate->heap();
|
Heap* heap = isolate->heap();
|
||||||
|
|
||||||
Handle<Object> receiver = args.receiver();
|
Handle<Object> receiver = args.receiver();
|
||||||
@ -2240,7 +2213,7 @@ void Builtins::InitBuiltinFunctionTable() {
|
|||||||
functions[builtin_count].s_name = NULL;
|
functions[builtin_count].s_name = NULL;
|
||||||
functions[builtin_count].name = builtin_count;
|
functions[builtin_count].name = builtin_count;
|
||||||
functions[builtin_count].flags = static_cast<Code::Flags>(0);
|
functions[builtin_count].flags = static_cast<Code::Flags>(0);
|
||||||
functions[builtin_count].extra_args = NO_EXTRA_ARGUMENTS;
|
functions[builtin_count].extra_args = BuiltinExtraArguments::kNone;
|
||||||
|
|
||||||
#define DEF_FUNCTION_PTR_C(aname, aextra_args) \
|
#define DEF_FUNCTION_PTR_C(aname, aextra_args) \
|
||||||
functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
|
functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
|
||||||
@ -2248,7 +2221,7 @@ void Builtins::InitBuiltinFunctionTable() {
|
|||||||
functions->s_name = #aname; \
|
functions->s_name = #aname; \
|
||||||
functions->name = c_##aname; \
|
functions->name = c_##aname; \
|
||||||
functions->flags = Code::ComputeFlags(Code::BUILTIN); \
|
functions->flags = Code::ComputeFlags(Code::BUILTIN); \
|
||||||
functions->extra_args = aextra_args; \
|
functions->extra_args = BuiltinExtraArguments::aextra_args; \
|
||||||
++functions;
|
++functions;
|
||||||
|
|
||||||
#define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \
|
#define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \
|
||||||
@ -2256,10 +2229,8 @@ void Builtins::InitBuiltinFunctionTable() {
|
|||||||
functions->c_code = NULL; \
|
functions->c_code = NULL; \
|
||||||
functions->s_name = #aname; \
|
functions->s_name = #aname; \
|
||||||
functions->name = k##aname; \
|
functions->name = k##aname; \
|
||||||
functions->flags = Code::ComputeFlags(Code::kind, \
|
functions->flags = Code::ComputeFlags(Code::kind, state, extra); \
|
||||||
state, \
|
functions->extra_args = BuiltinExtraArguments::kNone; \
|
||||||
extra); \
|
|
||||||
functions->extra_args = NO_EXTRA_ARGUMENTS; \
|
|
||||||
++functions;
|
++functions;
|
||||||
|
|
||||||
#define DEF_FUNCTION_PTR_H(aname, kind) \
|
#define DEF_FUNCTION_PTR_H(aname, kind) \
|
||||||
@ -2268,7 +2239,7 @@ void Builtins::InitBuiltinFunctionTable() {
|
|||||||
functions->s_name = #aname; \
|
functions->s_name = #aname; \
|
||||||
functions->name = k##aname; \
|
functions->name = k##aname; \
|
||||||
functions->flags = Code::ComputeHandlerFlags(Code::kind); \
|
functions->flags = Code::ComputeHandlerFlags(Code::kind); \
|
||||||
functions->extra_args = NO_EXTRA_ARGUMENTS; \
|
functions->extra_args = BuiltinExtraArguments::kNone; \
|
||||||
++functions;
|
++functions;
|
||||||
|
|
||||||
BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
|
BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
|
||||||
|
@ -5,17 +5,24 @@
|
|||||||
#ifndef V8_BUILTINS_H_
|
#ifndef V8_BUILTINS_H_
|
||||||
#define V8_BUILTINS_H_
|
#define V8_BUILTINS_H_
|
||||||
|
|
||||||
|
#include "src/base/flags.h"
|
||||||
#include "src/handles.h"
|
#include "src/handles.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// Specifies extra arguments required by a C++ builtin.
|
// Specifies extra arguments required by a C++ builtin.
|
||||||
enum BuiltinExtraArguments {
|
enum class BuiltinExtraArguments : uint8_t {
|
||||||
NO_EXTRA_ARGUMENTS = 0,
|
kNone = 0u,
|
||||||
NEEDS_CALLED_FUNCTION = 1
|
kTarget = 1u << 0,
|
||||||
|
kNewTarget = 1u << 1,
|
||||||
|
kTargetAndNewTarget = kTarget | kNewTarget
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
|
||||||
|
return static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define CODE_AGE_LIST_WITH_ARG(V, A) \
|
#define CODE_AGE_LIST_WITH_ARG(V, A) \
|
||||||
V(Quadragenarian, A) \
|
V(Quadragenarian, A) \
|
||||||
@ -45,42 +52,42 @@ enum BuiltinExtraArguments {
|
|||||||
|
|
||||||
// Define list of builtins implemented in C++.
|
// Define list of builtins implemented in C++.
|
||||||
#define BUILTIN_LIST_C(V) \
|
#define BUILTIN_LIST_C(V) \
|
||||||
V(Illegal, NO_EXTRA_ARGUMENTS) \
|
V(Illegal, kNone) \
|
||||||
\
|
\
|
||||||
V(EmptyFunction, NO_EXTRA_ARGUMENTS) \
|
V(EmptyFunction, kNone) \
|
||||||
\
|
\
|
||||||
V(ArrayPush, NO_EXTRA_ARGUMENTS) \
|
V(ArrayPush, kNone) \
|
||||||
V(ArrayPop, NO_EXTRA_ARGUMENTS) \
|
V(ArrayPop, kNone) \
|
||||||
V(ArrayShift, NO_EXTRA_ARGUMENTS) \
|
V(ArrayShift, kNone) \
|
||||||
V(ArrayUnshift, NO_EXTRA_ARGUMENTS) \
|
V(ArrayUnshift, kNone) \
|
||||||
V(ArraySlice, NO_EXTRA_ARGUMENTS) \
|
V(ArraySlice, kNone) \
|
||||||
V(ArraySplice, NO_EXTRA_ARGUMENTS) \
|
V(ArraySplice, kNone) \
|
||||||
V(ArrayConcat, NO_EXTRA_ARGUMENTS) \
|
V(ArrayConcat, kNone) \
|
||||||
\
|
\
|
||||||
V(DateToPrimitive, NO_EXTRA_ARGUMENTS) \
|
V(DateToPrimitive, kNone) \
|
||||||
\
|
\
|
||||||
V(ReflectDefineProperty, NO_EXTRA_ARGUMENTS) \
|
V(ReflectDefineProperty, kNone) \
|
||||||
V(ReflectDeleteProperty, NO_EXTRA_ARGUMENTS) \
|
V(ReflectDeleteProperty, kNone) \
|
||||||
V(ReflectGet, NO_EXTRA_ARGUMENTS) \
|
V(ReflectGet, kNone) \
|
||||||
V(ReflectGetOwnPropertyDescriptor, NO_EXTRA_ARGUMENTS) \
|
V(ReflectGetOwnPropertyDescriptor, kNone) \
|
||||||
V(ReflectGetPrototypeOf, NO_EXTRA_ARGUMENTS) \
|
V(ReflectGetPrototypeOf, kNone) \
|
||||||
V(ReflectHas, NO_EXTRA_ARGUMENTS) \
|
V(ReflectHas, kNone) \
|
||||||
V(ReflectIsExtensible, NO_EXTRA_ARGUMENTS) \
|
V(ReflectIsExtensible, kNone) \
|
||||||
V(ReflectOwnKeys, NO_EXTRA_ARGUMENTS) \
|
V(ReflectOwnKeys, kNone) \
|
||||||
V(ReflectPreventExtensions, NO_EXTRA_ARGUMENTS) \
|
V(ReflectPreventExtensions, kNone) \
|
||||||
V(ReflectSet, NO_EXTRA_ARGUMENTS) \
|
V(ReflectSet, kNone) \
|
||||||
V(ReflectSetPrototypeOf, NO_EXTRA_ARGUMENTS) \
|
V(ReflectSetPrototypeOf, kNone) \
|
||||||
\
|
\
|
||||||
V(SymbolConstructor, NO_EXTRA_ARGUMENTS) \
|
V(SymbolConstructor, kNone) \
|
||||||
V(SymbolConstructor_ConstructStub, NEEDS_CALLED_FUNCTION) \
|
V(SymbolConstructor_ConstructStub, kTarget) \
|
||||||
\
|
\
|
||||||
V(HandleApiCall, NEEDS_CALLED_FUNCTION) \
|
V(HandleApiCall, kTarget) \
|
||||||
V(HandleApiCallConstruct, NEEDS_CALLED_FUNCTION) \
|
V(HandleApiCallConstruct, kTarget) \
|
||||||
V(HandleApiCallAsFunction, NO_EXTRA_ARGUMENTS) \
|
V(HandleApiCallAsFunction, kNone) \
|
||||||
V(HandleApiCallAsConstructor, NO_EXTRA_ARGUMENTS) \
|
V(HandleApiCallAsConstructor, kNone) \
|
||||||
\
|
\
|
||||||
V(RestrictedFunctionPropertiesThrower, NO_EXTRA_ARGUMENTS) \
|
V(RestrictedFunctionPropertiesThrower, kNone) \
|
||||||
V(RestrictedStrictArgumentsPropertiesThrower, NO_EXTRA_ARGUMENTS)
|
V(RestrictedStrictArgumentsPropertiesThrower, kNone)
|
||||||
|
|
||||||
// Define list of builtins implemented in assembly.
|
// Define list of builtins implemented in assembly.
|
||||||
#define BUILTIN_LIST_A(V) \
|
#define BUILTIN_LIST_A(V) \
|
||||||
|
@ -22,7 +22,8 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
BuiltinExtraArguments extra_args) {
|
BuiltinExtraArguments extra_args) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- eax : number of arguments excluding receiver
|
// -- eax : number of arguments excluding receiver
|
||||||
// -- edi : called function
|
// -- edi : target
|
||||||
|
// -- edx : new.target
|
||||||
// -- esp[0] : return address
|
// -- esp[0] : return address
|
||||||
// -- esp[4] : last argument
|
// -- esp[4] : last argument
|
||||||
// -- ...
|
// -- ...
|
||||||
@ -33,14 +34,17 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
|
|
||||||
// Insert extra arguments.
|
// Insert extra arguments.
|
||||||
int num_extra_args = 0;
|
int num_extra_args = 0;
|
||||||
if (extra_args == NEEDS_CALLED_FUNCTION) {
|
if (extra_args != BuiltinExtraArguments::kNone) {
|
||||||
num_extra_args = 1;
|
__ PopReturnAddressTo(ecx);
|
||||||
Register scratch = ebx;
|
if (extra_args & BuiltinExtraArguments::kTarget) {
|
||||||
__ pop(scratch); // Save return address.
|
++num_extra_args;
|
||||||
__ push(edi);
|
__ Push(edi);
|
||||||
__ push(scratch); // Restore return address.
|
}
|
||||||
} else {
|
if (extra_args & BuiltinExtraArguments::kNewTarget) {
|
||||||
DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
|
++num_extra_args;
|
||||||
|
__ Push(edx);
|
||||||
|
}
|
||||||
|
__ PushReturnAddressFrom(ecx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpToExternalReference expects eax to contain the number of arguments
|
// JumpToExternalReference expects eax to contain the number of arguments
|
||||||
|
@ -23,7 +23,8 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
BuiltinExtraArguments extra_args) {
|
BuiltinExtraArguments extra_args) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- a0 : number of arguments excluding receiver
|
// -- a0 : number of arguments excluding receiver
|
||||||
// -- a1 : called function
|
// -- a1 : target
|
||||||
|
// -- a3 : new.target
|
||||||
// -- sp[0] : last argument
|
// -- sp[0] : last argument
|
||||||
// -- ...
|
// -- ...
|
||||||
// -- sp[4 * (argc - 1)] : first argument
|
// -- sp[4 * (argc - 1)] : first argument
|
||||||
@ -33,11 +34,21 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
|
|
||||||
// Insert extra arguments.
|
// Insert extra arguments.
|
||||||
int num_extra_args = 0;
|
int num_extra_args = 0;
|
||||||
if (extra_args == NEEDS_CALLED_FUNCTION) {
|
switch (extra_args) {
|
||||||
num_extra_args = 1;
|
case BuiltinExtraArguments::kTarget:
|
||||||
__ push(a1);
|
__ Push(a1);
|
||||||
} else {
|
++num_extra_args;
|
||||||
DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
|
break;
|
||||||
|
case BuiltinExtraArguments::kNewTarget:
|
||||||
|
__ Push(a3);
|
||||||
|
++num_extra_args;
|
||||||
|
break;
|
||||||
|
case BuiltinExtraArguments::kTargetAndNewTarget:
|
||||||
|
__ Push(a1, a3);
|
||||||
|
num_extra_args += 2;
|
||||||
|
break;
|
||||||
|
case BuiltinExtraArguments::kNone:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpToExternalReference expects a0 to contain the number of arguments
|
// JumpToExternalReference expects a0 to contain the number of arguments
|
||||||
|
@ -22,7 +22,8 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
BuiltinExtraArguments extra_args) {
|
BuiltinExtraArguments extra_args) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- a0 : number of arguments excluding receiver
|
// -- a0 : number of arguments excluding receiver
|
||||||
// -- a1 : called function
|
// -- a1 : target
|
||||||
|
// -- a3 : new.target
|
||||||
// -- sp[0] : last argument
|
// -- sp[0] : last argument
|
||||||
// -- ...
|
// -- ...
|
||||||
// -- sp[8 * (argc - 1)] : first argument
|
// -- sp[8 * (argc - 1)] : first argument
|
||||||
@ -32,11 +33,21 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
|
|
||||||
// Insert extra arguments.
|
// Insert extra arguments.
|
||||||
int num_extra_args = 0;
|
int num_extra_args = 0;
|
||||||
if (extra_args == NEEDS_CALLED_FUNCTION) {
|
switch (extra_args) {
|
||||||
num_extra_args = 1;
|
case BuiltinExtraArguments::kTarget:
|
||||||
__ push(a1);
|
__ Push(a1);
|
||||||
} else {
|
++num_extra_args;
|
||||||
DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
|
break;
|
||||||
|
case BuiltinExtraArguments::kNewTarget:
|
||||||
|
__ Push(a3);
|
||||||
|
++num_extra_args;
|
||||||
|
break;
|
||||||
|
case BuiltinExtraArguments::kTargetAndNewTarget:
|
||||||
|
__ Push(a1, a3);
|
||||||
|
num_extra_args += 2;
|
||||||
|
break;
|
||||||
|
case BuiltinExtraArguments::kNone:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpToExternalReference expects a0 to contain the number of arguments
|
// JumpToExternalReference expects a0 to contain the number of arguments
|
||||||
|
@ -21,7 +21,8 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
|||||||
BuiltinExtraArguments extra_args) {
|
BuiltinExtraArguments extra_args) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- r3 : number of arguments excluding receiver
|
// -- r3 : number of arguments excluding receiver
|
||||||
// -- r4 : called function
|
// -- r4 : target
|
||||||
|
// -- r6 : new.target
|
||||||
// -- sp[0] : last argument
|
// -- sp[0] : last argument
|
||||||
// -- ...
|
// -- ...
|
||||||
// -- sp[4 * (argc - 1)] : first argument
|
// -- sp[4 * (argc - 1)] : first argument
|
||||||
@ -31,11 +32,21 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
|||||||
|
|
||||||
// Insert extra arguments.
|
// Insert extra arguments.
|
||||||
int num_extra_args = 0;
|
int num_extra_args = 0;
|
||||||
if (extra_args == NEEDS_CALLED_FUNCTION) {
|
switch (extra_args) {
|
||||||
num_extra_args = 1;
|
case BuiltinExtraArguments::kTarget:
|
||||||
__ push(r4);
|
__ Push(r4);
|
||||||
} else {
|
++num_extra_args;
|
||||||
DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
|
break;
|
||||||
|
case BuiltinExtraArguments::kNewTarget:
|
||||||
|
__ Push(r6);
|
||||||
|
++num_extra_args;
|
||||||
|
break;
|
||||||
|
case BuiltinExtraArguments::kTargetAndNewTarget:
|
||||||
|
__ Push(r4, r6);
|
||||||
|
num_extra_args += 2;
|
||||||
|
break;
|
||||||
|
case BuiltinExtraArguments::kNone:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpToExternalReference expects r3 to contain the number of arguments
|
// JumpToExternalReference expects r3 to contain the number of arguments
|
||||||
|
@ -21,7 +21,8 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
BuiltinExtraArguments extra_args) {
|
BuiltinExtraArguments extra_args) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- rax : number of arguments excluding receiver
|
// -- rax : number of arguments excluding receiver
|
||||||
// -- rdi : called function
|
// -- rdi : target
|
||||||
|
// -- rdx : new.target
|
||||||
// -- rsp[0] : return address
|
// -- rsp[0] : return address
|
||||||
// -- rsp[8] : last argument
|
// -- rsp[8] : last argument
|
||||||
// -- ...
|
// -- ...
|
||||||
@ -32,13 +33,17 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
|
|
||||||
// Insert extra arguments.
|
// Insert extra arguments.
|
||||||
int num_extra_args = 0;
|
int num_extra_args = 0;
|
||||||
if (extra_args == NEEDS_CALLED_FUNCTION) {
|
if (extra_args != BuiltinExtraArguments::kNone) {
|
||||||
num_extra_args = 1;
|
|
||||||
__ PopReturnAddressTo(kScratchRegister);
|
__ PopReturnAddressTo(kScratchRegister);
|
||||||
|
if (extra_args & BuiltinExtraArguments::kTarget) {
|
||||||
|
++num_extra_args;
|
||||||
__ Push(rdi);
|
__ Push(rdi);
|
||||||
|
}
|
||||||
|
if (extra_args & BuiltinExtraArguments::kNewTarget) {
|
||||||
|
++num_extra_args;
|
||||||
|
__ Push(rdx);
|
||||||
|
}
|
||||||
__ PushReturnAddressFrom(kScratchRegister);
|
__ PushReturnAddressFrom(kScratchRegister);
|
||||||
} else {
|
|
||||||
DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpToExternalReference expects rax to contain the number of arguments
|
// JumpToExternalReference expects rax to contain the number of arguments
|
||||||
|
@ -22,7 +22,8 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
BuiltinExtraArguments extra_args) {
|
BuiltinExtraArguments extra_args) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- eax : number of arguments excluding receiver
|
// -- eax : number of arguments excluding receiver
|
||||||
// -- edi : called function
|
// -- edi : target
|
||||||
|
// -- edx : new.target
|
||||||
// -- esp[0] : return address
|
// -- esp[0] : return address
|
||||||
// -- esp[4] : last argument
|
// -- esp[4] : last argument
|
||||||
// -- ...
|
// -- ...
|
||||||
@ -33,14 +34,17 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
|
|||||||
|
|
||||||
// Insert extra arguments.
|
// Insert extra arguments.
|
||||||
int num_extra_args = 0;
|
int num_extra_args = 0;
|
||||||
if (extra_args == NEEDS_CALLED_FUNCTION) {
|
if (extra_args != BuiltinExtraArguments::kNone) {
|
||||||
num_extra_args = 1;
|
__ PopReturnAddressTo(ecx);
|
||||||
Register scratch = ebx;
|
if (extra_args & BuiltinExtraArguments::kTarget) {
|
||||||
__ pop(scratch); // Save return address.
|
++num_extra_args;
|
||||||
__ push(edi);
|
__ Push(edi);
|
||||||
__ push(scratch); // Restore return address.
|
}
|
||||||
} else {
|
if (extra_args & BuiltinExtraArguments::kNewTarget) {
|
||||||
DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
|
++num_extra_args;
|
||||||
|
__ Push(edx);
|
||||||
|
}
|
||||||
|
__ PushReturnAddressFrom(ecx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpToExternalReference expects eax to contain the number of arguments
|
// JumpToExternalReference expects eax to contain the number of arguments
|
||||||
|
Loading…
Reference in New Issue
Block a user