Commit d5bbd45f authored by bmeurer's avatar bmeurer Committed by Commit bot

[runtime] Initial step towards switching Execution::Call to callable.

Currently Execution::Call (and friends) still duplicate a lot of the
Call sequence logic that should be encapsulated in the Call and
CallFunction builtins. So the plan now is to switch Execution::Call
to accept any Callable and just pass that through to the Call builtin.

CQ_INCLUDE_TRYBOTS=tryserver.v8:v8_linux_nosnap_dbg
R=jarin@chromium.org
BUG=v8:4413
LOG=n

Committed: https://crrev.com/359645f48156e15f235e9a9ede7910e0bcd9ae45
Cr-Commit-Position: refs/heads/master@{#30791}

Review URL: https://codereview.chromium.org/1353723002

Cr-Commit-Position: refs/heads/master@{#30808}
parent 632c3679
This diff is collapsed.
...@@ -798,8 +798,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, ...@@ -798,8 +798,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS); CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
__ CallStub(&stub); __ CallStub(&stub);
} else { } else {
ParameterCount actual(r0); __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
__ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper());
} }
// Exit the JS frame and remove the parameters (except function), and // Exit the JS frame and remove the parameters (except function), and
// return. // return.
......
...@@ -835,8 +835,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, ...@@ -835,8 +835,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS); CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
__ CallStub(&stub); __ CallStub(&stub);
} else { } else {
ParameterCount actual(x0); __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
__ InvokeFunction(function, actual, CALL_FUNCTION, NullCallWrapper());
} }
// Exit the JS internal frame and remove the parameters (except function), // Exit the JS internal frame and remove the parameters (except function),
// and return. // and return.
......
...@@ -489,8 +489,8 @@ Handle<Code> TurboFanCodeStub::GenerateCode() { ...@@ -489,8 +489,8 @@ Handle<Code> TurboFanCodeStub::GenerateCode() {
Handle<Object> call_conv = factory->InternalizeUtf8String(name); Handle<Object> call_conv = factory->InternalizeUtf8String(name);
Handle<Object> minor_key = factory->NewNumber(MinorKey()); Handle<Object> minor_key = factory->NewNumber(MinorKey());
Handle<Object> args[] = {call_conv, minor_key}; Handle<Object> args[] = {call_conv, minor_key};
MaybeHandle<Object> result = Execution::Call( MaybeHandle<Object> result =
isolate(), outer, factory->undefined_value(), 2, args, false); Execution::Call(isolate(), outer, factory->undefined_value(), 2, args);
Handle<JSFunction> inner = Handle<JSFunction>::cast(result.ToHandleChecked()); Handle<JSFunction> inner = Handle<JSFunction>::cast(result.ToHandleChecked());
// Just to make sure nobody calls this... // Just to make sure nobody calls this...
inner->set_code(isolate()->builtins()->builtin(Builtins::kIllegal)); inner->set_code(isolate()->builtins()->builtin(Builtins::kIllegal));
......
...@@ -53,20 +53,35 @@ static void PrintDeserializedCodeInfo(Handle<JSFunction> function) { ...@@ -53,20 +53,35 @@ static void PrintDeserializedCodeInfo(Handle<JSFunction> function) {
} }
MUST_USE_RESULT static MaybeHandle<Object> Invoke( namespace {
bool is_construct,
Handle<JSFunction> function, MUST_USE_RESULT MaybeHandle<Object> Invoke(bool is_construct,
Handle<Object> receiver, Handle<JSFunction> function,
int argc, Handle<Object> receiver, int argc,
Handle<Object> args[]) { Handle<Object> args[]) {
Isolate* isolate = function->GetIsolate(); 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. // api callbacks can be called directly.
if (!is_construct && function->shared()->IsApiFunction()) { if (!is_construct && function->shared()->IsApiFunction()) {
SaveContext save(isolate); SaveContext save(isolate);
isolate->set_context(function->context()); isolate->set_context(function->context());
if (receiver->IsGlobalObject()) { // Do proper receiver conversion for non-strict mode api functions.
receiver = handle(Handle<GlobalObject>::cast(receiver)->global_proxy()); 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()); DCHECK(function->context()->global_object()->IsGlobalObject());
auto value = Builtins::InvokeApiFunction(function, receiver, argc, args); auto value = Builtins::InvokeApiFunction(function, receiver, argc, args);
...@@ -103,13 +118,6 @@ MUST_USE_RESULT static MaybeHandle<Object> Invoke( ...@@ -103,13 +118,6 @@ MUST_USE_RESULT static MaybeHandle<Object> Invoke(
? isolate->factory()->js_construct_entry_code() ? isolate->factory()->js_construct_entry_code()
: isolate->factory()->js_entry_code(); : isolate->factory()->js_entry_code();
// 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());
}
// Make sure that the global object of the context we're about to // Make sure that the global object of the context we're about to
// make the current one is indeed a global object. // make the current one is indeed a global object.
DCHECK(function->context()->global_object()->IsGlobalObject()); DCHECK(function->context()->global_object()->IsGlobalObject());
...@@ -122,13 +130,12 @@ MUST_USE_RESULT static MaybeHandle<Object> Invoke( ...@@ -122,13 +130,12 @@ MUST_USE_RESULT static MaybeHandle<Object> Invoke(
JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry()); JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
// Call the function through the right JS entry stub. // Call the function through the right JS entry stub.
byte* function_entry = function->code()->entry(); byte* ignored = nullptr; // TODO(bmeurer): Remove this altogether.
JSFunction* func = *function; JSFunction* func = *function;
Object* recv = *receiver; Object* recv = *receiver;
Object*** argv = reinterpret_cast<Object***>(args); Object*** argv = reinterpret_cast<Object***>(args);
if (FLAG_profile_deserialization) PrintDeserializedCodeInfo(function); if (FLAG_profile_deserialization) PrintDeserializedCodeInfo(function);
value = value = CALL_GENERATED_CODE(stub_entry, ignored, func, recv, argc, argv);
CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv);
} }
#ifdef VERIFY_HEAP #ifdef VERIFY_HEAP
...@@ -154,31 +161,18 @@ MUST_USE_RESULT static MaybeHandle<Object> Invoke( ...@@ -154,31 +161,18 @@ MUST_USE_RESULT static MaybeHandle<Object> Invoke(
return Handle<Object>(value, isolate); return Handle<Object>(value, isolate);
} }
} // namespace
MaybeHandle<Object> Execution::Call(Isolate* isolate,
Handle<Object> callable, MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
Handle<Object> receiver, Handle<Object> receiver, int argc,
int argc, Handle<Object> argv[]) {
Handle<Object> argv[],
bool convert_receiver) {
if (!callable->IsJSFunction()) { if (!callable->IsJSFunction()) {
ASSIGN_RETURN_ON_EXCEPTION(isolate, callable, ASSIGN_RETURN_ON_EXCEPTION(isolate, callable,
GetFunctionDelegate(isolate, callable), Object); GetFunctionDelegate(isolate, callable), Object);
} }
Handle<JSFunction> func = Handle<JSFunction>::cast(callable); Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
// In sloppy mode, convert receiver.
if (convert_receiver && !receiver->IsJSReceiver() &&
!func->shared()->native() && is_sloppy(func->shared()->language_mode())) {
if (receiver->IsUndefined() || receiver->IsNull()) {
receiver = handle(func->global_proxy());
DCHECK(!receiver->IsJSBuiltinsObject());
} else {
ASSIGN_RETURN_ON_EXCEPTION(
isolate, receiver, ToObject(isolate, receiver), Object);
}
}
return Invoke(false, func, receiver, argc, argv); return Invoke(false, func, receiver, argc, argv);
} }
...@@ -207,7 +201,7 @@ MaybeHandle<Object> Execution::TryCall(Handle<JSFunction> func, ...@@ -207,7 +201,7 @@ MaybeHandle<Object> Execution::TryCall(Handle<JSFunction> func,
catcher.SetVerbose(false); catcher.SetVerbose(false);
catcher.SetCaptureMessage(false); catcher.SetCaptureMessage(false);
maybe_result = Invoke(false, func, receiver, argc, args); maybe_result = Call(isolate, func, receiver, argc, args);
if (maybe_result.is_null()) { if (maybe_result.is_null()) {
DCHECK(catcher.HasCaught()); DCHECK(catcher.HasCaught());
......
...@@ -19,23 +19,16 @@ class JSRegExp; ...@@ -19,23 +19,16 @@ class JSRegExp;
class Execution final : public AllStatic { class Execution final : public AllStatic {
public: public:
// Call a function, the caller supplies a receiver and an array // Call a function, the caller supplies a receiver and an array
// of arguments. Arguments are Object* type. After function returns, // of arguments.
// pointers in 'args' might be invalid.
//
// *pending_exception tells whether the invoke resulted in
// a pending exception.
// //
// When convert_receiver is set, and the receiver is not an object, // When the function called is not in strict mode, receiver is
// and the function called is not in strict mode, receiver is converted to // converted to an object.
// an object.
// //
MUST_USE_RESULT static MaybeHandle<Object> Call( MUST_USE_RESULT static MaybeHandle<Object> Call(Isolate* isolate,
Isolate* isolate, Handle<Object> callable,
Handle<Object> callable, Handle<Object> receiver,
Handle<Object> receiver, int argc,
int argc, Handle<Object> argv[]);
Handle<Object> argv[],
bool convert_receiver = false);
// Construct object from function, the caller supplies an array of // Construct object from function, the caller supplies an array of
// arguments. Arguments are Object* type. After function returns, // arguments. Arguments are Object* type. After function returns,
......
...@@ -534,9 +534,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, ...@@ -534,9 +534,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS); CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
__ CallStub(&stub); __ CallStub(&stub);
} else { } else {
ParameterCount actual(eax); __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
__ InvokeFunction(edi, actual, CALL_FUNCTION,
NullCallWrapper());
} }
// Exit the internal frame. Notice that this also removes the empty. // Exit the internal frame. Notice that this also removes the empty.
......
...@@ -796,8 +796,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, ...@@ -796,8 +796,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS); CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
__ CallStub(&stub); __ CallStub(&stub);
} else { } else {
ParameterCount actual(a0); __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
__ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
} }
// Leave internal frame. // Leave internal frame.
......
...@@ -794,8 +794,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, ...@@ -794,8 +794,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS); CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
__ CallStub(&stub); __ CallStub(&stub);
} else { } else {
ParameterCount actual(a0); __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
__ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
} }
// Leave internal frame. // Leave internal frame.
......
...@@ -841,7 +841,7 @@ MaybeHandle<Object> Object::GetPropertyWithDefinedGetter( ...@@ -841,7 +841,7 @@ MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
// TODO(rossberg): should this apply to getters that are function proxies? // TODO(rossberg): should this apply to getters that are function proxies?
if (debug->is_active()) debug->HandleStepIn(getter, false); if (debug->is_active()) debug->HandleStepIn(getter, false);
return Execution::Call(isolate, getter, receiver, 0, NULL, true); return Execution::Call(isolate, getter, receiver, 0, NULL);
} }
...@@ -858,7 +858,7 @@ MaybeHandle<Object> Object::SetPropertyWithDefinedSetter( ...@@ -858,7 +858,7 @@ MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
Handle<Object> argv[] = { value }; Handle<Object> argv[] = { value };
RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver, RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver,
arraysize(argv), argv, true), arraysize(argv), argv),
Object); Object);
return value; return value;
} }
......
...@@ -522,7 +522,7 @@ RUNTIME_FUNCTION(Runtime_Call) { ...@@ -522,7 +522,7 @@ RUNTIME_FUNCTION(Runtime_Call) {
Handle<Object> result; Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION( ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, isolate, result,
Execution::Call(isolate, target, receiver, argc, argv.start(), true)); Execution::Call(isolate, target, receiver, argc, argv.start()));
return *result; return *result;
} }
...@@ -559,8 +559,7 @@ RUNTIME_FUNCTION(Runtime_Apply) { ...@@ -559,8 +559,7 @@ RUNTIME_FUNCTION(Runtime_Apply) {
Handle<Object> result; Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION( ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, isolate, result, Execution::Call(isolate, fun, receiver, argc, argv));
Execution::Call(isolate, fun, receiver, argc, argv, true));
return *result; return *result;
} }
...@@ -627,8 +626,7 @@ RUNTIME_FUNCTION(Runtime_CallFunction) { ...@@ -627,8 +626,7 @@ RUNTIME_FUNCTION(Runtime_CallFunction) {
Handle<Object> hreceiver(receiver, isolate); Handle<Object> hreceiver(receiver, isolate);
Handle<Object> result; Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION( ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, isolate, result, Execution::Call(isolate, hfun, hreceiver, argc, argv));
Execution::Call(isolate, hfun, hreceiver, argc, argv, true));
return *result; return *result;
} }
......
...@@ -593,9 +593,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, ...@@ -593,9 +593,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS); CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
__ CallStub(&stub); __ CallStub(&stub);
} else { } else {
ParameterCount actual(rax); __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
// Function must be in rdi.
__ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper());
} }
// Exit the internal frame. Notice that this also removes the empty // Exit the internal frame. Notice that this also removes the empty
// context and the function left on the stack by the code // context and the function left on the stack by the code
......
...@@ -51,13 +51,13 @@ class FunctionTester : public InitializedHandleScope { ...@@ -51,13 +51,13 @@ class FunctionTester : public InitializedHandleScope {
MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) { MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) {
Handle<Object> args[] = {a, b}; Handle<Object> args[] = {a, b};
return Execution::Call(isolate, function, undefined(), 2, args, false); return Execution::Call(isolate, function, undefined(), 2, args);
} }
MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, Handle<Object> c, MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, Handle<Object> c,
Handle<Object> d) { Handle<Object> d) {
Handle<Object> args[] = {a, b, c, d}; Handle<Object> args[] = {a, b, c, d};
return Execution::Call(isolate, function, undefined(), 4, args, false); return Execution::Call(isolate, function, undefined(), 4, args);
} }
void CheckThrows(Handle<Object> a, Handle<Object> b) { void CheckThrows(Handle<Object> a, Handle<Object> b) {
......
...@@ -25,8 +25,7 @@ static const char kFunctionName[] = "f"; ...@@ -25,8 +25,7 @@ static const char kFunctionName[] = "f";
static MaybeHandle<Object> CallFunction(Isolate* isolate, static MaybeHandle<Object> CallFunction(Isolate* isolate,
Handle<JSFunction> function) { Handle<JSFunction> function) {
return Execution::Call(isolate, function, return Execution::Call(isolate, function,
isolate->factory()->undefined_value(), 0, nullptr, isolate->factory()->undefined_value(), 0, nullptr);
false);
} }
...@@ -37,7 +36,7 @@ static MaybeHandle<Object> CallFunction(Isolate* isolate, ...@@ -37,7 +36,7 @@ static MaybeHandle<Object> CallFunction(Isolate* isolate,
Handle<Object> argv[] = {args...}; Handle<Object> argv[] = {args...};
return Execution::Call(isolate, function, return Execution::Call(isolate, function,
isolate->factory()->undefined_value(), sizeof...(args), isolate->factory()->undefined_value(), sizeof...(args),
argv, false); argv);
} }
......
...@@ -82,7 +82,7 @@ class SimplifiedLoweringTester : public GraphBuilderTester<ReturnType> { ...@@ -82,7 +82,7 @@ class SimplifiedLoweringTester : public GraphBuilderTester<ReturnType> {
Handle<JSFunction> fun = FunctionTester::ForMachineGraph(this->graph()); Handle<JSFunction> fun = FunctionTester::ForMachineGraph(this->graph());
Handle<Object>* args = NULL; Handle<Object>* args = NULL;
MaybeHandle<Object> result = Execution::Call( MaybeHandle<Object> result = Execution::Call(
this->isolate(), fun, factory()->undefined_value(), 0, args, false); this->isolate(), fun, factory()->undefined_value(), 0, args);
return T::cast(*result.ToHandleChecked()); return T::cast(*result.ToHandleChecked());
} }
......
...@@ -18,8 +18,7 @@ namespace interpreter { ...@@ -18,8 +18,7 @@ namespace interpreter {
static MaybeHandle<Object> CallInterpreter(Isolate* isolate, static MaybeHandle<Object> CallInterpreter(Isolate* isolate,
Handle<JSFunction> function) { Handle<JSFunction> function) {
return Execution::Call(isolate, function, return Execution::Call(isolate, function,
isolate->factory()->undefined_value(), 0, nullptr, isolate->factory()->undefined_value(), 0, nullptr);
false);
} }
...@@ -30,7 +29,7 @@ static MaybeHandle<Object> CallInterpreter(Isolate* isolate, ...@@ -30,7 +29,7 @@ static MaybeHandle<Object> CallInterpreter(Isolate* isolate,
Handle<Object> argv[] = { args... }; Handle<Object> argv[] = { args... };
return Execution::Call(isolate, function, return Execution::Call(isolate, function,
isolate->factory()->undefined_value(), sizeof...(args), isolate->factory()->undefined_value(), sizeof...(args),
argv, false); argv);
} }
......
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