| Index: src/builtins.cc
|
| diff --git a/src/builtins.cc b/src/builtins.cc
|
| index 22ad3fa22cd39da15cf5d045f6561c99d676cf54..269736b76adff537077fa42792eb622b7bb50e9d 100644
|
| --- a/src/builtins.cc
|
| +++ b/src/builtins.cc
|
| @@ -31,7 +31,10 @@ template <BuiltinExtraArguments extra_args>
|
| class BuiltinArguments : public Arguments {
|
| public:
|
| 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) {
|
| DCHECK(index < length());
|
| @@ -47,47 +50,64 @@ class BuiltinArguments : public Arguments {
|
| return Arguments::at<Object>(0);
|
| }
|
|
|
| - Handle<JSFunction> called_function() {
|
| - STATIC_ASSERT(extra_args == NEEDS_CALLED_FUNCTION);
|
| - return Arguments::at<JSFunction>(Arguments::length() - 1);
|
| - }
|
| + Handle<JSFunction> target();
|
| + Handle<HeapObject> new_target();
|
|
|
| // Gets the total number of arguments including the receiver (but
|
| // excluding extra arguments).
|
| - 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
|
| + int length() const;
|
| };
|
|
|
|
|
| -// Specialize BuiltinArguments for the called function extra argument.
|
| +// Specialize BuiltinArguments for the extra arguments.
|
| +
|
| +template <>
|
| +int BuiltinArguments<BuiltinExtraArguments::kNone>::length() const {
|
| + return Arguments::length();
|
| +}
|
|
|
| template <>
|
| -int BuiltinArguments<NEEDS_CALLED_FUNCTION>::length() const {
|
| +int BuiltinArguments<BuiltinExtraArguments::kTarget>::length() const {
|
| return Arguments::length() - 1;
|
| }
|
|
|
| -#ifdef DEBUG
|
| template <>
|
| -void BuiltinArguments<NEEDS_CALLED_FUNCTION>::Verify() {
|
| - // Check we have at least the receiver and the called function.
|
| - DCHECK(Arguments::length() >= 2);
|
| - // Make sure cast to JSFunction succeeds.
|
| - called_function();
|
| +Handle<JSFunction> BuiltinArguments<BuiltinExtraArguments::kTarget>::target() {
|
| + return Arguments::at<JSFunction>(Arguments::length() - 1);
|
| }
|
| -#endif
|
|
|
| +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);
|
| +}
|
|
|
| -#define DEF_ARG_TYPE(name, spec) \
|
| - typedef BuiltinArguments<spec> name##ArgumentsType;
|
| +template <>
|
| +Handle<HeapObject>
|
| +BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::new_target() {
|
| + return Arguments::at<HeapObject>(Arguments::length() - 1);
|
| +}
|
| +
|
| +
|
| +#define DEF_ARG_TYPE(name, spec) \
|
| + typedef BuiltinArguments<BuiltinExtraArguments::spec> name##ArgumentsType;
|
| BUILTIN_LIST_C(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
|
| // through the BuiltinArguments object args.
|
|
|
| -#ifdef DEBUG
|
| -
|
| #define BUILTIN(name) \
|
| MUST_USE_RESULT static Object* Builtin_Impl_##name( \
|
| name##ArgumentsType args, Isolate* isolate); \
|
| MUST_USE_RESULT static Object* Builtin_##name( \
|
| int args_length, Object** args_object, Isolate* isolate) { \
|
| name##ArgumentsType args(args_length, args_object); \
|
| - args.Verify(); \
|
| return Builtin_Impl_##name(args, isolate); \
|
| } \
|
| MUST_USE_RESULT static Object* Builtin_Impl_##name( \
|
| 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(
|
| Isolate* isolate, Handle<JSFunction> function,
|
| - BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
|
| + BuiltinArguments<BuiltinExtraArguments::kNone> args) {
|
| HandleScope handleScope(isolate);
|
| int argc = args.length() - 1;
|
| ScopedVector<Handle<Object> > argv(argc);
|
| @@ -1764,7 +1738,7 @@ BUILTIN(SymbolConstructor_ConstructStub) {
|
| HandleScope scope(isolate);
|
| // The ConstructStub is executed in the context of the caller, so we need
|
| // 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(
|
| isolate, NewTypeError(MessageTemplate::kNotConstructor,
|
| isolate->factory()->Symbol_string()));
|
| @@ -1794,11 +1768,13 @@ BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
|
| //
|
|
|
|
|
| +namespace {
|
| +
|
| template <bool is_construct>
|
| -MUST_USE_RESULT static MaybeHandle<Object> HandleApiCallHelper(
|
| - Isolate* isolate, BuiltinArguments<NEEDS_CALLED_FUNCTION>& args) {
|
| +MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
|
| + Isolate* isolate, BuiltinArguments<BuiltinExtraArguments::kTarget> args) {
|
| HandleScope scope(isolate);
|
| - Handle<JSFunction> function = args.called_function();
|
| + Handle<JSFunction> function = args.target();
|
| // TODO(ishell): turn this back to a DCHECK.
|
| CHECK(function->shared()->IsApiFunction());
|
|
|
| @@ -1873,10 +1849,11 @@ MUST_USE_RESULT static MaybeHandle<Object> HandleApiCallHelper(
|
| return scope.CloseAndEscape(args.receiver());
|
| }
|
|
|
| +} // namespace
|
| +
|
|
|
| BUILTIN(HandleApiCall) {
|
| HandleScope scope(isolate);
|
| - DCHECK(!CalledAsConstructor(isolate));
|
| Handle<Object> result;
|
| ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| HandleApiCallHelper<false>(isolate, args));
|
| @@ -1886,7 +1863,6 @@ BUILTIN(HandleApiCall) {
|
|
|
| BUILTIN(HandleApiCallConstruct) {
|
| HandleScope scope(isolate);
|
| - DCHECK(CalledAsConstructor(isolate));
|
| Handle<Object> result;
|
| ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
| HandleApiCallHelper<true>(isolate, args));
|
| @@ -1924,11 +1900,12 @@ Handle<Code> Builtins::Call(ConvertReceiverMode mode) {
|
|
|
| namespace {
|
|
|
| -class RelocatableArguments : public BuiltinArguments<NEEDS_CALLED_FUNCTION>,
|
| - public Relocatable {
|
| +class RelocatableArguments
|
| + : public BuiltinArguments<BuiltinExtraArguments::kTarget>,
|
| + public Relocatable {
|
| public:
|
| RelocatableArguments(Isolate* isolate, int length, Object** arguments)
|
| - : BuiltinArguments<NEEDS_CALLED_FUNCTION>(length, arguments),
|
| + : BuiltinArguments<BuiltinExtraArguments::kTarget>(length, arguments),
|
| Relocatable(isolate) {}
|
|
|
| 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
|
| // a function (without new).
|
| MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
|
| - Isolate* isolate,
|
| - bool is_construct_call,
|
| - 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));
|
| + Isolate* isolate, bool is_construct_call,
|
| + BuiltinArguments<BuiltinExtraArguments::kNone> args) {
|
| Heap* heap = isolate->heap();
|
|
|
| Handle<Object> receiver = args.receiver();
|
| @@ -2240,36 +2213,34 @@ void Builtins::InitBuiltinFunctionTable() {
|
| functions[builtin_count].s_name = NULL;
|
| functions[builtin_count].name = builtin_count;
|
| functions[builtin_count].flags = static_cast<Code::Flags>(0);
|
| - functions[builtin_count].extra_args = NO_EXTRA_ARGUMENTS;
|
| -
|
| -#define DEF_FUNCTION_PTR_C(aname, aextra_args) \
|
| - functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
|
| - functions->c_code = FUNCTION_ADDR(Builtin_##aname); \
|
| - functions->s_name = #aname; \
|
| - functions->name = c_##aname; \
|
| - functions->flags = Code::ComputeFlags(Code::BUILTIN); \
|
| - functions->extra_args = aextra_args; \
|
| - ++functions;
|
| -
|
| -#define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \
|
| - functions->generator = FUNCTION_ADDR(Generate_##aname); \
|
| - functions->c_code = NULL; \
|
| - functions->s_name = #aname; \
|
| - functions->name = k##aname; \
|
| - functions->flags = Code::ComputeFlags(Code::kind, \
|
| - state, \
|
| - extra); \
|
| - functions->extra_args = NO_EXTRA_ARGUMENTS; \
|
| - ++functions;
|
| -
|
| -#define DEF_FUNCTION_PTR_H(aname, kind) \
|
| - functions->generator = FUNCTION_ADDR(Generate_##aname); \
|
| - functions->c_code = NULL; \
|
| - functions->s_name = #aname; \
|
| - functions->name = k##aname; \
|
| - functions->flags = Code::ComputeHandlerFlags(Code::kind); \
|
| - functions->extra_args = NO_EXTRA_ARGUMENTS; \
|
| - ++functions;
|
| + functions[builtin_count].extra_args = BuiltinExtraArguments::kNone;
|
| +
|
| +#define DEF_FUNCTION_PTR_C(aname, aextra_args) \
|
| + functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
|
| + functions->c_code = FUNCTION_ADDR(Builtin_##aname); \
|
| + functions->s_name = #aname; \
|
| + functions->name = c_##aname; \
|
| + functions->flags = Code::ComputeFlags(Code::BUILTIN); \
|
| + functions->extra_args = BuiltinExtraArguments::aextra_args; \
|
| + ++functions;
|
| +
|
| +#define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \
|
| + functions->generator = FUNCTION_ADDR(Generate_##aname); \
|
| + functions->c_code = NULL; \
|
| + functions->s_name = #aname; \
|
| + functions->name = k##aname; \
|
| + functions->flags = Code::ComputeFlags(Code::kind, state, extra); \
|
| + functions->extra_args = BuiltinExtraArguments::kNone; \
|
| + ++functions;
|
| +
|
| +#define DEF_FUNCTION_PTR_H(aname, kind) \
|
| + functions->generator = FUNCTION_ADDR(Generate_##aname); \
|
| + functions->c_code = NULL; \
|
| + functions->s_name = #aname; \
|
| + functions->name = k##aname; \
|
| + functions->flags = Code::ComputeHandlerFlags(Code::kind); \
|
| + functions->extra_args = BuiltinExtraArguments::kNone; \
|
| + ++functions;
|
|
|
| BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
|
| BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
|
|
|