auto recv_obj = Utils::OpenHandle(*recv);
STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Object**));
i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
- i::Handle<i::JSFunction> fun;
- if (self->IsJSFunction()) {
- fun = i::Handle<i::JSFunction>::cast(self);
- } else {
- has_pending_exception =
- !i::Execution::GetFunctionDelegate(isolate, self).ToHandle(&fun);
- RETURN_ON_FAILED_EXECUTION(Value);
- recv_obj = self;
- }
Local<Value> result;
has_pending_exception = !ToLocal<Value>(
- i::Execution::Call(isolate, fun, recv_obj, argc, args), &result);
+ i::Execution::Call(isolate, self, recv_obj, argc, args), &result);
RETURN_ON_FAILED_EXECUTION(Value);
RETURN_ESCAPED(result);
}
auto self = Utils::OpenHandle(this);
STATIC_ASSERT(sizeof(v8::Local<v8::Value>) == sizeof(i::Object**));
i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
- if (self->IsJSFunction()) {
- auto fun = i::Handle<i::JSFunction>::cast(self);
- Local<Value> result;
- has_pending_exception =
- !ToLocal<Value>(i::Execution::New(fun, argc, args), &result);
- RETURN_ON_FAILED_EXECUTION(Value);
- RETURN_ESCAPED(result);
- }
- i::Handle<i::JSFunction> fun;
- has_pending_exception =
- !i::Execution::GetConstructorDelegate(isolate, self).ToHandle(&fun);
- RETURN_ON_FAILED_EXECUTION(Value);
Local<Value> result;
has_pending_exception = !ToLocal<Value>(
- i::Execution::Call(isolate, fun, self, argc, args), &result);
+ i::Execution::New(isolate, self, self, argc, args), &result);
RETURN_ON_FAILED_EXECUTION(Value);
RETURN_ESCAPED(result);
}
// -- r1 : the target to call (can be any Object).
// -----------------------------------
- Label non_smi, non_function;
- __ JumpIfSmi(r1, &non_function);
+ Label non_callable, non_function, non_smi;
+ __ JumpIfSmi(r1, &non_callable);
__ bind(&non_smi);
- __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
+ __ CompareObjectType(r1, r4, r5, JS_FUNCTION_TYPE);
__ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET,
eq);
- __ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE));
+ __ cmp(r5, Operand(JS_FUNCTION_PROXY_TYPE));
__ b(ne, &non_function);
// 1. Call to function proxy.
// 2. Call to something else, which might have a [[Call]] internal method (if
// not we raise an exception).
__ bind(&non_function);
- // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could
- // be awesome instead; i.e. a trivial improvement would be to call into the
- // runtime and just deal with the API function there instead of returning a
- // delegate from a runtime call that just jumps back to the runtime once
- // called. Or, bonus points, call directly into the C API function here, as
- // we do in some Crankshaft fast cases.
- // Overwrite the original receiver with the (original) target.
+ // Check if target has a [[Call]] internal method.
+ __ ldrb(r4, FieldMemOperand(r4, Map::kBitFieldOffset));
+ __ tst(r4, Operand(1 << Map::kIsCallable));
+ __ b(eq, &non_callable);
+ // Overwrite the original receiver the (original) target.
__ str(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
+ // Let the "call_as_function_delegate" take care of the rest.
+ __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, r1);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+
+ // 3. Call to something that is not callable.
+ __ bind(&non_callable);
{
- // Determine the delegate for the target (if any).
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
- __ SmiTag(r0);
- __ Push(r0, r1);
- __ CallRuntime(Runtime::kGetFunctionDelegate, 1);
- __ mov(r1, r0);
- __ Pop(r0);
- __ SmiUntag(r0);
+ __ Push(r1);
+ __ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
- // The delegate is always a regular function.
- __ AssertFunction(r1);
- __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
}
// the JSFunction on which new was invoked initially)
// -----------------------------------
- Label slow;
- __ JumpIfSmi(r1, &slow);
- __ CompareObjectType(r1, r5, r5, JS_FUNCTION_TYPE);
+ Label non_callable, non_function;
+ __ JumpIfSmi(r1, &non_callable);
+ __ CompareObjectType(r1, r4, r5, JS_FUNCTION_TYPE);
__ Jump(masm->isolate()->builtins()->ConstructFunction(),
RelocInfo::CODE_TARGET, eq);
__ cmp(r5, Operand(JS_FUNCTION_PROXY_TYPE));
- __ b(ne, &slow);
+ __ b(ne, &non_function);
+ // 1. Construct of function proxy.
// TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies.
__ ldr(r1, FieldMemOperand(r1, JSFunctionProxy::kConstructTrapOffset));
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
- __ bind(&slow);
+ // 2. Construct of something that else, which might have a [[Construct]]
+ // internal method (if not we raise an exception).
+ __ bind(&non_function);
+ // Check if target has a [[Call]] internal method.
+ // TODO(bmeurer): This shoud use IsConstructor once available.
+ __ ldrb(r4, FieldMemOperand(r4, Map::kBitFieldOffset));
+ __ tst(r4, Operand(1 << Map::kIsCallable));
+ __ b(eq, &non_callable);
+ // Overwrite the original receiver the (original) target.
+ __ str(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
+ // Let the "call_as_constructor_delegate" take care of the rest.
+ __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, r1);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+
+ // 3. Construct of something that is not callable.
+ __ bind(&non_callable);
{
- // Determine the delegate for the target (if any).
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
- __ SmiTag(r0);
- __ Push(r0, r1);
- __ CallRuntime(Runtime::kGetConstructorDelegate, 1);
- __ mov(r1, r0);
- __ Pop(r0);
- __ SmiUntag(r0);
+ __ Push(r1);
+ __ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
- // The delegate is always a regular function.
- __ AssertFunction(r1);
- __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
}
// -- x1 : the target to call (can be any Object).
// -----------------------------------
- Label non_smi, non_jsfunction, non_function;
- __ JumpIfSmi(x1, &non_function);
+ Label non_callable, non_function, non_smi;
+ __ JumpIfSmi(x1, &non_callable);
__ Bind(&non_smi);
- __ CompareObjectType(x1, x2, x2, JS_FUNCTION_TYPE);
- __ B(ne, &non_jsfunction);
- __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
- __ Bind(&non_jsfunction);
- __ Cmp(x2, JS_FUNCTION_PROXY_TYPE);
+ __ CompareObjectType(x1, x4, x5, JS_FUNCTION_TYPE);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET,
+ eq);
+ __ Cmp(x5, JS_FUNCTION_PROXY_TYPE);
__ B(ne, &non_function);
// 1. Call to function proxy.
// 2. Call to something else, which might have a [[Call]] internal method (if
// not we raise an exception).
__ Bind(&non_function);
- // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could
- // be awesome instead; i.e. a trivial improvement would be to call into the
- // runtime and just deal with the API function there instead of returning a
- // delegate from a runtime call that just jumps back to the runtime once
- // called. Or, bonus points, call directly into the C API function here, as
- // we do in some Crankshaft fast cases.
+ // Check if target has a [[Call]] internal method.
+ __ Ldrb(x4, FieldMemOperand(x4, Map::kBitFieldOffset));
+ __ TestAndBranchIfAllClear(x4, 1 << Map::kIsCallable, &non_callable);
// Overwrite the original receiver with the (original) target.
__ Poke(x1, Operand(x0, LSL, kXRegSizeLog2));
+ // Let the "call_as_function_delegate" take care of the rest.
+ __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, x1);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+
+ // 3. Call to something that is not callable.
+ __ bind(&non_callable);
{
- // Determine the delegate for the target (if any).
FrameScope scope(masm, StackFrame::INTERNAL);
- __ SmiTag(x0);
- __ Push(x0, x1);
- __ CallRuntime(Runtime::kGetFunctionDelegate, 1);
- __ Mov(x1, x0);
- __ Pop(x0);
- __ SmiUntag(x0);
+ __ Push(x1);
+ __ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
- // The delegate is always a regular function.
- __ AssertFunction(x1);
- __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
}
// the JSFunction on which new was invoked initially)
// -----------------------------------
- Label slow;
- __ JumpIfSmi(x1, &slow);
- __ CompareObjectType(x1, x5, x5, JS_FUNCTION_TYPE);
+ Label non_callable, non_function;
+ __ JumpIfSmi(x1, &non_callable);
+ __ CompareObjectType(x1, x4, x5, JS_FUNCTION_TYPE);
__ Jump(masm->isolate()->builtins()->ConstructFunction(),
RelocInfo::CODE_TARGET, eq);
- __ Cmp(x5, Operand(JS_FUNCTION_PROXY_TYPE));
- __ B(ne, &slow);
+ __ Cmp(x5, JS_FUNCTION_PROXY_TYPE);
+ __ B(ne, &non_function);
+ // 1. Construct of function proxy.
// TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies.
__ Ldr(x1, FieldMemOperand(x1, JSFunctionProxy::kConstructTrapOffset));
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
- __ Bind(&slow);
+ // 2. Construct of something that else, which might have a [[Construct]]
+ // internal method (if not we raise an exception).
+ __ Bind(&non_function);
+ // Check if target has a [[Call]] internal method.
+ // TODO(bmeurer): This shoud use IsConstructor once available.
+ __ Ldrb(x4, FieldMemOperand(x4, Map::kBitFieldOffset));
+ __ TestAndBranchIfAllClear(x4, 1 << Map::kIsCallable, &non_callable);
+ // Overwrite the original receiver with the (original) target.
+ __ Poke(x1, Operand(x0, LSL, kXRegSizeLog2));
+ // Let the "call_as_constructor_delegate" take care of the rest.
+ __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, x1);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+
+ // 3. Construct of something that is not callable.
+ __ bind(&non_callable);
{
- // Determine the delegate for the target (if any).
FrameScope scope(masm, StackFrame::INTERNAL);
- __ SmiTag(x0);
- __ Push(x0, x1);
- __ CallRuntime(Runtime::kGetConstructorDelegate, 1);
- __ Mov(x1, x0);
- __ Pop(x0);
- __ SmiUntag(x0);
+ __ Push(x1);
+ __ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
- // The delegate is always a regular function.
- __ AssertFunction(x1);
- __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
}
int64_t Simulator::CallJS(byte* entry,
Object* new_target,
- JSFunction* func,
+ Object* target,
Object* revc,
int64_t argc,
Object*** argv) {
CallArgument args[] = {
CallArgument(new_target),
- CallArgument(func),
+ CallArgument(target),
CallArgument(revc),
CallArgument(argc),
CallArgument(argv),
return CallInt64(entry, args);
}
+
int64_t Simulator::CallRegExp(byte* entry,
String* input,
int64_t start_offset,
// which set up the simulator state and grab the result on return.
int64_t CallJS(byte* entry,
Object* new_target,
- JSFunction* func,
+ Object* target,
Object* revc,
int64_t argc,
Object*** argv);
#include "src/deoptimizer.h"
#include "src/isolate-inl.h"
#include "src/messages.h"
-#include "src/parser.h"
-#include "src/prettyprinter.h"
#include "src/vm-state-inl.h"
namespace v8 {
namespace {
-MUST_USE_RESULT MaybeHandle<Object> Invoke(bool is_construct,
- Handle<JSFunction> function,
+MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct,
+ Handle<Object> target,
Handle<Object> receiver, int argc,
Handle<Object> args[],
Handle<Object> new_target) {
- Isolate* const isolate = function->GetIsolate();
-
- // Convert calls on global objects to be calls on the global
- // receiver instead to avoid having a 'this' pointer which refers
- // directly to a global object.
- if (receiver->IsGlobalObject()) {
- receiver =
- handle(Handle<GlobalObject>::cast(receiver)->global_proxy(), isolate);
- }
-
- // api callbacks can be called directly.
- if (!is_construct && function->shared()->IsApiFunction()) {
- SaveContext save(isolate);
- isolate->set_context(function->context());
- // Do proper receiver conversion for non-strict mode api functions.
- if (!receiver->IsJSReceiver() &&
- is_sloppy(function->shared()->language_mode())) {
- if (receiver->IsUndefined() || receiver->IsNull()) {
- receiver = handle(function->global_proxy(), isolate);
- } else {
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, receiver, Execution::ToObject(isolate, receiver), Object);
- }
- }
- DCHECK(function->context()->global_object()->IsGlobalObject());
- auto value = Builtins::InvokeApiFunction(function, receiver, argc, args);
- bool has_exception = value.is_null();
- DCHECK(has_exception == isolate->has_pending_exception());
- if (has_exception) {
- isolate->ReportPendingMessages();
- return MaybeHandle<Object>();
- } else {
- isolate->clear_pending_message();
- }
- return value;
- }
+ DCHECK(!receiver->IsGlobalObject());
// Entering JavaScript.
VMState<JS> state(isolate);
// Placeholder for return value.
Object* value = NULL;
- typedef Object* (*JSEntryFunction)(Object* new_target, Object* function,
+ typedef Object* (*JSEntryFunction)(Object* new_target, Object* target,
Object* receiver, int argc,
Object*** args);
? isolate->factory()->js_construct_entry_code()
: isolate->factory()->js_entry_code();
- // Make sure that the global object of the context we're about to
- // make the current one is indeed a global object.
- DCHECK(function->context()->global_object()->IsGlobalObject());
-
{
// Save and restore context around invocation and block the
// allocation of handles without explicit handle scopes.
// Call the function through the right JS entry stub.
Object* orig_func = *new_target;
- JSFunction* func = *function;
+ Object* func = *target;
Object* recv = *receiver;
Object*** argv = reinterpret_cast<Object***>(args);
- if (FLAG_profile_deserialization) PrintDeserializedCodeInfo(function);
+ if (FLAG_profile_deserialization && target->IsJSFunction()) {
+ PrintDeserializedCodeInfo(Handle<JSFunction>::cast(target));
+ }
value = CALL_GENERATED_CODE(stub_entry, orig_func, func, recv, argc, argv);
}
} // namespace
+// static
MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
Handle<Object> receiver, int argc,
Handle<Object> argv[]) {
- if (!callable->IsJSFunction()) {
- ASSIGN_RETURN_ON_EXCEPTION(isolate, callable,
- GetFunctionDelegate(isolate, callable), Object);
+ // Convert calls on global objects to be calls on the global
+ // receiver instead to avoid having a 'this' pointer which refers
+ // directly to a global object.
+ if (receiver->IsGlobalObject()) {
+ receiver =
+ handle(Handle<GlobalObject>::cast(receiver)->global_proxy(), isolate);
+ }
+
+ // api callbacks can be called directly.
+ if (callable->IsJSFunction() &&
+ Handle<JSFunction>::cast(callable)->shared()->IsApiFunction()) {
+ Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
+ SaveContext save(isolate);
+ isolate->set_context(function->context());
+ // Do proper receiver conversion for non-strict mode api functions.
+ if (!receiver->IsJSReceiver() &&
+ is_sloppy(function->shared()->language_mode())) {
+ if (receiver->IsUndefined() || receiver->IsNull()) {
+ receiver = handle(function->global_proxy(), isolate);
+ } else {
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, receiver, Execution::ToObject(isolate, receiver), Object);
+ }
+ }
+ DCHECK(function->context()->global_object()->IsGlobalObject());
+ auto value = Builtins::InvokeApiFunction(function, receiver, argc, argv);
+ bool has_exception = value.is_null();
+ DCHECK(has_exception == isolate->has_pending_exception());
+ if (has_exception) {
+ isolate->ReportPendingMessages();
+ return MaybeHandle<Object>();
+ } else {
+ isolate->clear_pending_message();
+ }
+ return value;
}
- Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
- return Invoke(false, func, receiver, argc, argv,
+ return Invoke(isolate, false, callable, receiver, argc, argv,
isolate->factory()->undefined_value());
}
+// static
MaybeHandle<Object> Execution::New(Handle<JSFunction> constructor, int argc,
Handle<Object> argv[]) {
- return New(constructor, constructor, argc, argv);
+ return New(constructor->GetIsolate(), constructor, constructor, argc, argv);
}
-MaybeHandle<Object> Execution::New(Handle<JSFunction> constructor,
- Handle<JSFunction> new_target, int argc,
+// static
+MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor,
+ Handle<Object> new_target, int argc,
Handle<Object> argv[]) {
- return Invoke(true, constructor, handle(constructor->global_proxy()), argc,
- argv, new_target);
+ return Invoke(isolate, true, constructor,
+ isolate->factory()->undefined_value(), argc, argv, new_target);
}
}
-// static
-MaybeHandle<JSFunction> Execution::GetFunctionDelegate(Isolate* isolate,
- Handle<Object> object) {
- DCHECK(!object->IsJSFunction());
- if (object->IsHeapObject()) {
- DisallowHeapAllocation no_gc;
-
- // If object is a function proxy, get its handler. Iterate if necessary.
- Object* fun = *object;
- while (fun->IsJSFunctionProxy()) {
- fun = JSFunctionProxy::cast(fun)->call_trap();
- }
- if (fun->IsJSFunction()) {
- return handle(JSFunction::cast(fun), isolate);
- }
-
- // We can also have exotic objects with [[Call]] internal methods.
- if (fun->IsCallable()) {
- return handle(isolate->native_context()->call_as_function_delegate(),
- isolate);
- }
- }
-
- // If the Object doesn't have an instance-call handler we should
- // throw a non-callable exception.
- Handle<String> callsite = RenderCallSite(isolate, object);
- THROW_NEW_ERROR(isolate,
- NewTypeError(MessageTemplate::kCalledNonCallable, callsite),
- JSFunction);
-}
-
-
-// static
-MaybeHandle<JSFunction> Execution::GetConstructorDelegate(
- Isolate* isolate, Handle<Object> object) {
- // If you return a function from here, it will be called when an
- // attempt is made to call the given object as a constructor.
-
- DCHECK(!object->IsJSFunction());
- if (object->IsHeapObject()) {
- DisallowHeapAllocation no_gc;
-
- // If object is a function proxies, get its handler. Iterate if necessary.
- Object* fun = *object;
- while (fun->IsJSFunctionProxy()) {
- // TODO(bmeurer): This should work based on [[Construct]]; our proxies
- // are screwed.
- fun = JSFunctionProxy::cast(fun)->call_trap();
- }
- if (fun->IsJSFunction()) {
- return handle(JSFunction::cast(fun), isolate);
- }
-
- // We can also have exotic objects with [[Construct]] internal methods.
- // TODO(bmeurer): This should use IsConstructor() as dictacted by the spec.
- if (fun->IsCallable()) {
- return handle(isolate->native_context()->call_as_constructor_delegate(),
- isolate);
- }
- }
-
- // If the Object doesn't have an instance-call handler we should
- // throw a non-callable exception.
- Handle<String> callsite = RenderCallSite(isolate, object);
- THROW_NEW_ERROR(isolate,
- NewTypeError(MessageTemplate::kCalledNonCallable, callsite),
- JSFunction);
-}
-
-
-// static
-Handle<String> Execution::RenderCallSite(Isolate* isolate,
- Handle<Object> object) {
- MessageLocation location;
- if (isolate->ComputeLocation(&location)) {
- Zone zone;
- base::SmartPointer<ParseInfo> info(
- location.function()->shared()->is_function()
- ? new ParseInfo(&zone, location.function())
- : new ParseInfo(&zone, location.script()));
- if (Parser::ParseStatic(info.get())) {
- CallPrinter printer(isolate, &zone);
- const char* string = printer.Print(info->literal(), location.start_pos());
- return isolate->factory()->NewStringFromAsciiChecked(string);
- } else {
- isolate->clear_pending_exception();
- }
- }
- return Object::TypeOf(isolate, object);
-}
-
-
void StackGuard::SetStackLimit(uintptr_t limit) {
ExecutionAccess access(isolate_);
// If the current limits are special (e.g. due to a pending interrupt) then
MUST_USE_RESULT static MaybeHandle<Object> New(Handle<JSFunction> constructor,
int argc,
Handle<Object> argv[]);
- MUST_USE_RESULT static MaybeHandle<Object> New(Handle<JSFunction> constructor,
- Handle<JSFunction> new_target,
+ MUST_USE_RESULT static MaybeHandle<Object> New(Isolate* isolate,
+ Handle<Object> constructor,
+ Handle<Object> new_target,
int argc,
Handle<Object> argv[]);
Handle<JSFunction> fun,
Handle<Object> pos,
Handle<Object> is_global);
-
- // Get a function delegate for the given non-function object.
- // Used for support calling objects as functions.
- MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionDelegate(
- Isolate* isolate, Handle<Object> object);
-
- // Get a function delegate (or undefined) for the given non-function
- // object. Used for support calling objects as constructors.
- MUST_USE_RESULT static MaybeHandle<JSFunction> GetConstructorDelegate(
- Isolate* isolate, Handle<Object> object);
-
- private:
- MUST_USE_RESULT static Handle<String> RenderCallSite(Isolate* isolate,
- Handle<Object> object);
};
// -- edi : the target to call (can be any Object).
// -----------------------------------
- Label non_smi, non_function;
- __ JumpIfSmi(edi, &non_function);
+ Label non_callable, non_function, non_smi;
+ __ JumpIfSmi(edi, &non_callable);
__ bind(&non_smi);
- __ CmpObjectType(edi, JS_FUNCTION_TYPE, edx);
+ __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
__ j(equal, masm->isolate()->builtins()->CallFunction(),
RelocInfo::CODE_TARGET);
- __ CmpInstanceType(edx, JS_FUNCTION_PROXY_TYPE);
+ __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
__ j(not_equal, &non_function);
// 1. Call to function proxy.
// 2. Call to something else, which might have a [[Call]] internal method (if
// not we raise an exception).
__ bind(&non_function);
- // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could
- // be awesome instead; i.e. a trivial improvement would be to call into the
- // runtime and just deal with the API function there instead of returning a
- // delegate from a runtime call that just jumps back to the runtime once
- // called. Or, bonus points, call directly into the C API function here, as
- // we do in some Crankshaft fast cases.
+ // Check if target has a [[Call]] internal method.
+ __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable);
+ __ j(zero, &non_callable, Label::kNear);
// Overwrite the original receiver with the (original) target.
__ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi);
+ // Let the "call_as_function_delegate" take care of the rest.
+ __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, edi);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+
+ // 3. Call to something that is not callable.
+ __ bind(&non_callable);
{
- // Determine the delegate for the target (if any).
FrameScope scope(masm, StackFrame::INTERNAL);
- __ SmiTag(eax);
- __ Push(eax);
__ Push(edi);
- __ CallRuntime(Runtime::kGetFunctionDelegate, 1);
- __ mov(edi, eax);
- __ Pop(eax);
- __ SmiUntag(eax);
+ __ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
- // The delegate is always a regular function.
- __ AssertFunction(edi);
- __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
}
// -- edi : the constructor to call (can be any Object)
// -----------------------------------
- Label slow;
- __ JumpIfSmi(edi, &slow, Label::kNear);
+ Label non_callable, non_function;
+ __ JumpIfSmi(edi, &non_callable);
__ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
__ j(equal, masm->isolate()->builtins()->ConstructFunction(),
RelocInfo::CODE_TARGET);
__ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE);
- __ j(not_equal, &slow, Label::kNear);
+ __ j(not_equal, &non_function, Label::kNear);
+ // 1. Construct of function proxy.
// TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies.
__ mov(edi, FieldOperand(edi, JSFunctionProxy::kConstructTrapOffset));
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
- __ bind(&slow);
+ // 2. Construct of something else, which might have a [[Construct]] internal
+ // method (if not we raise an exception).
+ __ bind(&non_function);
+ // Check if target has a [[Call]] internal method.
+ // TODO(bmeurer): This shoud use IsConstructor once available.
+ __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable);
+ __ j(zero, &non_callable, Label::kNear);
+ // Overwrite the original receiver with the (original) target.
+ __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi);
+ // Let the "call_as_constructor_delegate" take care of the rest.
+ __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, edi);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+
+ // 3. Construct of something that is not callable.
+ __ bind(&non_callable);
{
- // Determine the delegate for the target (if any).
FrameScope scope(masm, StackFrame::INTERNAL);
- __ SmiTag(eax);
- __ Push(eax);
__ Push(edi);
- __ CallRuntime(Runtime::kGetConstructorDelegate, 1);
- __ mov(edi, eax);
- __ Pop(eax);
- __ SmiUntag(eax);
+ __ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
- // The delegate is always a regular function.
- __ AssertFunction(edi);
- __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
}
// -- a1 : the target to call (can be any Object).
// -----------------------------------
- Label non_smi, non_function;
- __ JumpIfSmi(a1, &non_function);
+ Label non_callable, non_function, non_smi;
+ __ JumpIfSmi(a1, &non_callable);
__ bind(&non_smi);
- __ GetObjectType(a1, a2, a2);
+ __ GetObjectType(a1, t1, t2);
__ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET,
- eq, a2, Operand(JS_FUNCTION_TYPE));
- __ Branch(&non_function, ne, a2, Operand(JS_FUNCTION_PROXY_TYPE));
-
+ eq, t2, Operand(JS_FUNCTION_TYPE));
+ __ Branch(&non_function, ne, t2, Operand(JS_FUNCTION_PROXY_TYPE));
// 1. Call to function proxy.
// TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies.
// 2. Call to something else, which might have a [[Call]] internal method (if
// not we raise an exception).
__ bind(&non_function);
- // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could
- // be awesome instead; i.e. a trivial improvement would be to call into the
- // runtime and just deal with the API function there instead of returning a
- // delegate from a runtime call that just jumps back to the runtime once
- // called. Or, bonus points, call directly into the C API function here, as
- // we do in some Crankshaft fast cases.
+ // Check if target has a [[Call]] internal method.
+ __ lbu(t1, FieldMemOperand(t1, Map::kBitFieldOffset));
+ __ And(t1, t1, Operand(1 << Map::kIsCallable));
+ __ Branch(&non_callable, eq, t1, Operand(zero_reg));
// Overwrite the original receiver with the (original) target.
__ sll(at, a0, kPointerSizeLog2);
__ addu(at, sp, at);
__ sw(a1, MemOperand(at));
+ // Let the "call_as_function_delegate" take care of the rest.
+ __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, a1);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+
+ // 3. Call to something that is not callable.
+ __ bind(&non_callable);
{
- // Determine the delegate for the target (if any).
- FrameScope scope(masm, StackFrame::INTERNAL);
- __ sll(a0, a0, kSmiTagSize); // Smi tagged.
- __ Push(a0, a1);
- __ CallRuntime(Runtime::kGetFunctionDelegate, 1);
- __ mov(a1, v0);
- __ Pop(a0);
- __ sra(a0, a0, kSmiTagSize); // Un-tag.
+ FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+ __ Push(a1);
+ __ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
- // The delegate is always a regular function.
- __ AssertFunction(a1);
- __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
}
// the JSFunction on which new was invoked initially)
// -----------------------------------
- Label slow;
- __ JumpIfSmi(a1, &slow);
- __ GetObjectType(a1, t1, t1);
+ Label non_callable, non_function;
+ __ JumpIfSmi(a1, &non_callable);
+ __ GetObjectType(a1, t1, t2);
__ Jump(masm->isolate()->builtins()->ConstructFunction(),
- RelocInfo::CODE_TARGET, eq, t1, Operand(JS_FUNCTION_TYPE));
- __ Branch(&slow, ne, t1, Operand(JS_FUNCTION_PROXY_TYPE));
+ RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE));
+ __ Branch(&non_function, ne, t2, Operand(JS_FUNCTION_PROXY_TYPE));
+ // 1. Construct of function proxy.
// TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies.
__ lw(a1, FieldMemOperand(a1, JSFunctionProxy::kConstructTrapOffset));
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
- __ bind(&slow);
+ // 2. Construct of something that else, which might have a [[Construct]]
+ // internal method (if not we raise an exception).
+ __ bind(&non_function);
+ // Check if target has a [[Call]] internal method.
+ // TODO(bmeurer): This shoud use IsConstructor once available.
+ __ lbu(t1, FieldMemOperand(t1, Map::kBitFieldOffset));
+ __ And(t1, t1, Operand(1 << Map::kIsCallable));
+ __ Branch(&non_callable, eq, t1, Operand(zero_reg));
+ // Overwrite the original receiver with the (original) target.
+ __ sll(at, a0, kPointerSizeLog2);
+ __ addu(at, sp, at);
+ __ sw(a1, MemOperand(at));
+ // Let the "call_as_constructor_delegate" take care of the rest.
+ __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, a1);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+
+ // 3. Construct of something that is not callable.
+ __ bind(&non_callable);
{
- // Determine the delegate for the target (if any).
- FrameScope scope(masm, StackFrame::INTERNAL);
- __ SmiTag(a0);
- __ Push(a0, a1);
- __ CallRuntime(Runtime::kGetConstructorDelegate, 1);
- __ mov(a1, v0);
- __ Pop(a0);
- __ SmiUntag(a0);
+ FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+ __ Push(a1);
+ __ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
- // The delegate is always a regular function.
- __ AssertFunction(a1);
- __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
}
// -- a1 : the target to call (can be any Object).
// -----------------------------------
- Label non_smi, non_function;
- __ JumpIfSmi(a1, &non_function);
+ Label non_callable, non_function, non_smi;
+ __ JumpIfSmi(a1, &non_callable);
__ bind(&non_smi);
- __ GetObjectType(a1, a2, a2);
+ __ GetObjectType(a1, t1, t2);
__ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET,
- eq, a2, Operand(JS_FUNCTION_TYPE));
- __ Branch(&non_function, ne, a2, Operand(JS_FUNCTION_PROXY_TYPE));
+ eq, t2, Operand(JS_FUNCTION_TYPE));
+ __ Branch(&non_function, ne, t2, Operand(JS_FUNCTION_PROXY_TYPE));
// 1. Call to function proxy.
// TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies.
// 2. Call to something else, which might have a [[Call]] internal method (if
// not we raise an exception).
__ bind(&non_function);
- // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could
- // be awesome instead; i.e. a trivial improvement would be to call into the
- // runtime and just deal with the API function there instead of returning a
- // delegate from a runtime call that just jumps back to the runtime once
- // called. Or, bonus points, call directly into the C API function here, as
- // we do in some Crankshaft fast cases.
+ // Check if target has a [[Call]] internal method.
+ __ lbu(t1, FieldMemOperand(t1, Map::kBitFieldOffset));
+ __ And(t1, t1, Operand(1 << Map::kIsCallable));
+ __ Branch(&non_callable, eq, t1, Operand(zero_reg));
// Overwrite the original receiver with the (original) target.
__ dsll(at, a0, kPointerSizeLog2);
__ daddu(at, sp, at);
__ sd(a1, MemOperand(at));
+ // Let the "call_as_function_delegate" take care of the rest.
+ __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, a1);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+
+ // 3. Call to something that is not callable.
+ __ bind(&non_callable);
{
- // Determine the delegate for the target (if any).
- FrameScope scope(masm, StackFrame::INTERNAL);
- __ SmiTag(a0);
- __ Push(a0, a1);
- __ CallRuntime(Runtime::kGetFunctionDelegate, 1);
- __ mov(a1, v0);
- __ Pop(a0);
- __ SmiUntag(a0);
+ FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+ __ Push(a1);
+ __ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
- // The delegate is always a regular function.
- __ AssertFunction(a1);
- __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
}
// the JSFunction on which new was invoked initially)
// -----------------------------------
- Label slow;
- __ JumpIfSmi(a1, &slow);
- __ GetObjectType(a1, a5, a5);
+ Label non_callable, non_function;
+ __ JumpIfSmi(a1, &non_callable);
+ __ GetObjectType(a1, t1, t2);
__ Jump(masm->isolate()->builtins()->ConstructFunction(),
- RelocInfo::CODE_TARGET, eq, a5, Operand(JS_FUNCTION_TYPE));
- __ Branch(&slow, ne, a5, Operand(JS_FUNCTION_PROXY_TYPE));
+ RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE));
+ __ Branch(&non_function, ne, t2, Operand(JS_FUNCTION_PROXY_TYPE));
+ // 1. Construct of function proxy.
// TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies.
__ ld(a1, FieldMemOperand(a1, JSFunctionProxy::kConstructTrapOffset));
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
- __ bind(&slow);
+ // 2. Construct of something that else, which might have a [[Construct]]
+ // internal method (if not we raise an exception).
+ __ bind(&non_function);
+ // Check if target has a [[Call]] internal method.
+ // TODO(bmeurer): This shoud use IsConstructor once available.
+ __ lbu(t1, FieldMemOperand(t1, Map::kBitFieldOffset));
+ __ And(t1, t1, Operand(1 << Map::kIsCallable));
+ __ Branch(&non_callable, eq, t1, Operand(zero_reg));
+ // Overwrite the original receiver with the (original) target.
+ __ dsll(at, a0, kPointerSizeLog2);
+ __ daddu(at, sp, at);
+ __ sd(a1, MemOperand(at));
+ // Let the "call_as_constructor_delegate" take care of the rest.
+ __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, a1);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+
+ // 3. Construct of something that is not callable.
+ __ bind(&non_callable);
{
- // Determine the delegate for the target (if any).
- FrameScope scope(masm, StackFrame::INTERNAL);
- __ SmiTag(a0);
- __ Push(a0, a1);
- __ CallRuntime(Runtime::kGetConstructorDelegate, 1);
- __ mov(a1, v0);
- __ Pop(a0);
- __ SmiUntag(a0);
+ FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+ __ Push(a1);
+ __ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
- // The delegate is always a regular function.
- __ AssertFunction(a1);
- __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
}
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, Execution::New(super_constructor, original_constructor,
- argument_count, arguments.get()));
+ isolate, result,
+ Execution::New(isolate, super_constructor, original_constructor,
+ argument_count, arguments.get()));
return *result;
}
bound_args->get(JSFunction::kBoundArgumentsStartIndex + i), isolate);
}
- if (!bound_function->IsJSFunction()) {
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, bound_function,
- Execution::GetConstructorDelegate(isolate, bound_function));
- }
- DCHECK(bound_function->IsJSFunction());
-
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, Execution::New(Handle<JSFunction>::cast(bound_function),
+ isolate, result, Execution::New(isolate, bound_function, bound_function,
total_argc, param_data.get()));
return *result;
}
}
-RUNTIME_FUNCTION(Runtime_GetFunctionDelegate) {
- HandleScope scope(isolate);
- DCHECK(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
- RUNTIME_ASSERT(!object->IsJSFunction());
- Handle<JSFunction> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, Execution::GetFunctionDelegate(isolate, object));
- return *result;
-}
-
-
-RUNTIME_FUNCTION(Runtime_GetConstructorDelegate) {
- HandleScope scope(isolate);
- DCHECK(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
- RUNTIME_ASSERT(!object->IsJSFunction());
- Handle<JSFunction> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, Execution::GetConstructorDelegate(isolate, object));
- return *result;
-}
-
-
RUNTIME_FUNCTION(Runtime_GetOriginalConstructor) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 0);
#include "src/frames-inl.h"
#include "src/isolate-inl.h"
#include "src/messages.h"
+#include "src/parser.h"
+#include "src/prettyprinter.h"
namespace v8 {
namespace internal {
return isolate->heap()->code_stub_exports_object();
}
+
+namespace {
+
+Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object) {
+ MessageLocation location;
+ if (isolate->ComputeLocation(&location)) {
+ Zone zone;
+ base::SmartPointer<ParseInfo> info(
+ location.function()->shared()->is_function()
+ ? new ParseInfo(&zone, location.function())
+ : new ParseInfo(&zone, location.script()));
+ if (Parser::ParseStatic(info.get())) {
+ CallPrinter printer(isolate, &zone);
+ const char* string = printer.Print(info->literal(), location.start_pos());
+ return isolate->factory()->NewStringFromAsciiChecked(string);
+ } else {
+ isolate->clear_pending_exception();
+ }
+ }
+ return Object::TypeOf(isolate, object);
+}
+
+} // namespace
+
+
+RUNTIME_FUNCTION(Runtime_ThrowCalledNonCallable) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(1, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+ Handle<String> callsite = RenderCallSite(isolate, object);
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError(MessageTemplate::kCalledNonCallable, callsite));
+}
+
} // namespace internal
} // namespace v8
F(NewObjectFromBound, 1, 1) \
F(Call, -1 /* >= 2 */, 1) \
F(Apply, 5, 1) \
- F(GetFunctionDelegate, 1, 1) \
- F(GetConstructorDelegate, 1, 1) \
F(GetOriginalConstructor, 0, 1) \
F(CallFunction, -1 /* receiver + n args + function */, 1) \
F(IsConstructCall, 0, 1) \
F(HarmonyToString, 0, 1) \
F(GetTypeFeedbackVector, 1, 1) \
F(GetCallerJSFunction, 0, 1) \
- F(GetCodeStubExportsObject, 0, 1)
+ F(GetCodeStubExportsObject, 0, 1) \
+ F(ThrowCalledNonCallable, 1, 1)
#define FOR_EACH_INTRINSIC_JSON(F) \
// -- rax : the number of arguments (not including the receiver)
// -- rdi : the target to call (can be any Object)
// -----------------------------------
+ StackArgumentsAccessor args(rsp, rax);
- Label non_smi, non_function;
- __ JumpIfSmi(rdi, &non_function);
+ Label non_callable, non_function, non_smi;
+ __ JumpIfSmi(rdi, &non_callable);
__ bind(&non_smi);
- __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rdx);
+ __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
__ j(equal, masm->isolate()->builtins()->CallFunction(),
RelocInfo::CODE_TARGET);
- __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE);
+ __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
__ j(not_equal, &non_function);
// 1. Call to function proxy.
// 2. Call to something else, which might have a [[Call]] internal method (if
// not we raise an exception).
__ bind(&non_function);
- // TODO(bmeurer): I wonder why we prefer to have slow API calls? This could
- // be awesome instead; i.e. a trivial improvement would be to call into the
- // runtime and just deal with the API function there instead of returning a
- // delegate from a runtime call that just jumps back to the runtime once
- // called. Or, bonus points, call directly into the C API function here, as
- // we do in some Crankshaft fast cases.
- StackArgumentsAccessor args(rsp, rax);
+ // Check if target has a [[Call]] internal method.
+ __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
+ Immediate(1 << Map::kIsCallable));
+ __ j(zero, &non_callable, Label::kNear);
// Overwrite the original receiver with the (original) target.
__ movp(args.GetReceiverOperand(), rdi);
+ // Let the "call_as_function_delegate" take care of the rest.
+ __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, rdi);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+
+ // 3. Call to something that is not callable.
+ __ bind(&non_callable);
{
- // Determine the delegate for the target (if any).
FrameScope scope(masm, StackFrame::INTERNAL);
- __ Integer32ToSmi(rax, rax);
- __ Push(rax);
__ Push(rdi);
- __ CallRuntime(Runtime::kGetFunctionDelegate, 1);
- __ movp(rdi, rax);
- __ Pop(rax);
- __ SmiToInteger32(rax, rax);
+ __ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
- // The delegate is always a regular function.
- __ AssertFunction(rdi);
- __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
}
// the JSFunction on which new was invoked initially)
// -- rdi : the constructor to call (can be any Object)
// -----------------------------------
+ StackArgumentsAccessor args(rsp, rax);
- Label slow;
- __ JumpIfSmi(rdi, &slow, Label::kNear);
+ Label non_callable, non_function;
+ __ JumpIfSmi(rdi, &non_callable);
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
__ j(equal, masm->isolate()->builtins()->ConstructFunction(),
RelocInfo::CODE_TARGET);
__ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
- __ j(not_equal, &slow, Label::kNear);
+ __ j(not_equal, &non_function, Label::kNear);
+ // 1. Construct of function proxy.
// TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies.
__ movp(rdi, FieldOperand(rdi, JSFunctionProxy::kConstructTrapOffset));
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
- __ bind(&slow);
+ // 2. Construct of something else, which might have a [[Construct]] internal
+ // method (if not we raise an exception).
+ __ bind(&non_function);
+ // Check if target has a [[Call]] internal method.
+ // TODO(bmeurer): This shoud use IsConstructor once available.
+ __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
+ Immediate(1 << Map::kIsCallable));
+ __ j(zero, &non_callable, Label::kNear);
+ // Overwrite the original receiver with the (original) target.
+ __ movp(args.GetReceiverOperand(), rdi);
+ // Let the "call_as_constructor_delegate" take care of the rest.
+ __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, rdi);
+ __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
+
+ // 3. Construct of something that is not callable.
+ __ bind(&non_callable);
{
- // Determine the delegate for the target (if any).
FrameScope scope(masm, StackFrame::INTERNAL);
- __ Integer32ToSmi(rax, rax);
- __ Push(rax);
__ Push(rdi);
- __ CallRuntime(Runtime::kGetConstructorDelegate, 1);
- __ movp(rdi, rax);
- __ Pop(rax);
- __ SmiToInteger32(rax, rax);
+ __ CallRuntime(Runtime::kThrowCalledNonCallable, 1);
}
- // The delegate is always a regular function.
- __ AssertFunction(rdi);
- __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET);
}