Commit 23af060d authored by Camillo Bruni's avatar Camillo Bruni Committed by V8 LUCI CQ

[runtime] Introduce explicit Execute::CallScript

For the upcoming host_defined_options fixes we will have to explicitly
pass the host-defined options to Invoke so we will be able to install
it in the script context in the future.

Bug: chromium:1244145
Change-Id: I690cc774d6a17278db4381aba8c3408e979606c1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3222765
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarShu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77524}
parent 06021c14
......@@ -2090,9 +2090,12 @@ MaybeLocal<Value> Script::Run(Local<Context> context) {
}
i::Handle<i::Object> receiver = isolate->global_proxy();
i::Handle<i::FixedArray> host_defined_options(
i::Script::cast(fun->shared().script()).host_defined_options(), isolate);
Local<Value> result;
has_pending_exception = !ToLocal<Value>(
i::Execution::Call(isolate, fun, receiver, 0, nullptr), &result);
i::Execution::CallScript(isolate, fun, receiver, host_defined_options),
&result);
if (i::FLAG_script_delay_fraction > 0.0) {
delta = v8::base::TimeDelta::FromMillisecondsD(
......
......@@ -72,9 +72,13 @@ MaybeHandle<Object> DebugEvaluate::Global(Isolate* isolate,
if (mode == debug::EvaluateGlobalMode::kDisableBreaksAndThrowOnSideEffect) {
isolate->debug()->StartSideEffectCheckMode();
}
MaybeHandle<Object> result = Execution::Call(
isolate, function, Handle<JSObject>(context->global_proxy(), isolate), 0,
nullptr);
// TODO(cbruni, 1244145): Use host-defined options from script context.
Handle<FixedArray> host_defined_options(
Script::cast(function->shared().script()).host_defined_options(),
isolate);
MaybeHandle<Object> result = Execution::CallScript(
isolate, function, Handle<JSObject>(context->global_proxy(), isolate),
host_defined_options);
if (mode == debug::EvaluateGlobalMode::kDisableBreaksAndThrowOnSideEffect) {
isolate->debug()->StopSideEffectCheckMode();
}
......
......@@ -51,6 +51,12 @@ struct InvokeParams {
MicrotaskQueue* microtask_queue,
MaybeHandle<Object>* exception_out);
bool IsScript() const {
if (!target->IsJSFunction()) return false;
Handle<JSFunction> function = Handle<JSFunction>::cast(target);
return function->shared().is_script();
}
Handle<Object> target;
Handle<Object> receiver;
int argc;
......@@ -75,6 +81,7 @@ InvokeParams InvokeParams::SetUpForNew(Isolate* isolate,
InvokeParams params;
params.target = constructor;
params.receiver = isolate->factory()->undefined_value();
DCHECK(!params.IsScript());
params.argc = argc;
params.argv = argv;
params.new_target = new_target;
......@@ -95,6 +102,9 @@ InvokeParams InvokeParams::SetUpForCall(Isolate* isolate,
InvokeParams params;
params.target = callable;
params.receiver = NormalizeReceiver(isolate, receiver);
// Check for host-defined options argument for scripts.
DCHECK_IMPLIES(params.IsScript(), argc == 1);
DCHECK_IMPLIES(params.IsScript(), argv[0]->IsFixedArray());
params.argc = argc;
params.argv = argv;
params.new_target = isolate->factory()->undefined_value();
......@@ -115,6 +125,9 @@ InvokeParams InvokeParams::SetUpForTryCall(
InvokeParams params;
params.target = callable;
params.receiver = NormalizeReceiver(isolate, receiver);
// Check for host-defined options argument for scripts.
DCHECK_IMPLIES(params.IsScript(), argc == 1);
DCHECK_IMPLIES(params.IsScript(), argv[0]->IsFixedArray());
params.argc = argc;
params.argv = argv;
params.new_target = isolate->factory()->undefined_value();
......@@ -163,7 +176,9 @@ Handle<Code> JSEntry(Isolate* isolate, Execution::Target execution_target,
}
MaybeHandle<Context> NewScriptContext(Isolate* isolate,
Handle<JSFunction> function) {
Handle<JSFunction> function,
Handle<FixedArray> host_defined_options) {
// TODO(cbruni, 1244145): Use passed in host_defined_options.
// Creating a script context is a side effect, so abort if that's not
// allowed.
if (isolate->debug_execution_mode() == DebugInfo::kSideEffects) {
......@@ -303,11 +318,24 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> Invoke(Isolate* isolate,
}
return value;
}
#ifdef DEBUG
if (function->shared().is_script()) {
DCHECK(params.IsScript());
DCHECK(params.receiver->IsJSGlobalProxy());
DCHECK_EQ(params.argc, 1);
DCHECK(params.argv[0]->IsFixedArray());
} else {
DCHECK(!params.IsScript());
}
#endif
// Set up a ScriptContext when running scripts that need it.
if (function->shared().needs_script_context()) {
DCHECK_EQ(params.argc, 1);
Handle<Context> context;
if (!NewScriptContext(isolate, function).ToHandle(&context)) {
Handle<FixedArray> host_defined_options =
Handle<FixedArray>::cast(params.argv[0]);
if (!NewScriptContext(isolate, function, host_defined_options)
.ToHandle(&context)) {
if (params.message_handling == Execution::MessageHandling::kReport) {
isolate->ReportPendingMessages();
}
......@@ -475,10 +503,24 @@ MaybeHandle<Object> InvokeWithTryCatch(Isolate* isolate,
MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
Handle<Object> receiver, int argc,
Handle<Object> argv[]) {
// Use Execution::CallScript instead for scripts:
DCHECK_IMPLIES(callable->IsJSFunction(),
!JSFunction::cast(*callable).shared().is_script());
return Invoke(isolate, InvokeParams::SetUpForCall(isolate, callable, receiver,
argc, argv));
}
// static
MaybeHandle<Object> Execution::CallScript(
Isolate* isolate, Handle<JSFunction> script_function,
Handle<Object> receiver, Handle<FixedArray> host_defined_options) {
DCHECK(script_function->shared().is_script());
DCHECK(receiver->IsJSGlobalProxy() || receiver->IsJSGlobalObject());
Handle<Object> argument = host_defined_options;
return Invoke(isolate, InvokeParams::SetUpForCall(isolate, script_function,
receiver, 1, &argument));
}
MaybeHandle<Object> Execution::CallBuiltin(Isolate* isolate,
Handle<JSFunction> builtin,
Handle<Object> receiver, int argc,
......@@ -503,11 +545,29 @@ MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor,
new_target, argc, argv));
}
// static
MaybeHandle<Object> Execution::TryCallScript(
Isolate* isolate, Handle<JSFunction> script_function,
Handle<Object> receiver, Handle<FixedArray> host_defined_options,
MessageHandling message_handling, MaybeHandle<Object>* exception_out,
bool reschedule_terminate) {
DCHECK(script_function->shared().is_script());
DCHECK(receiver->IsJSGlobalProxy() || receiver->IsJSGlobalObject());
Handle<Object> argument = host_defined_options;
return InvokeWithTryCatch(
isolate, InvokeParams::SetUpForTryCall(
isolate, script_function, receiver, 1, &argument,
message_handling, exception_out, reschedule_terminate));
}
// static
MaybeHandle<Object> Execution::TryCall(
Isolate* isolate, Handle<Object> callable, Handle<Object> receiver,
int argc, Handle<Object> argv[], MessageHandling message_handling,
MaybeHandle<Object>* exception_out, bool reschedule_terminate) {
// Use Execution::TryCallScript instead for scripts:
DCHECK_IMPLIES(callable->IsJSFunction(),
!JSFunction::cast(*callable).shared().is_script());
return InvokeWithTryCatch(
isolate, InvokeParams::SetUpForTryCall(
isolate, callable, receiver, argc, argv, message_handling,
......
......@@ -21,15 +21,19 @@ class Execution final : public AllStatic {
enum class MessageHandling { kReport, kKeepPending };
enum class Target { kCallable, kRunMicrotasks };
// Call a function, the caller supplies a receiver and an array
// of arguments.
//
// Call a function (that is not a script), the caller supplies a receiver and
// an array of arguments.
// When the function called is not in strict mode, receiver is
// converted to an object.
//
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object> Call(
Isolate* isolate, Handle<Object> callable, Handle<Object> receiver,
int argc, Handle<Object> argv[]);
// Run a script. For JSFunctions that are not scripts, use Execution::Call.
// Depending on the script, the host_defined_options might not be used but the
// caller has to provide it at all times.
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object> CallScript(
Isolate* isolate, Handle<JSFunction> callable, Handle<Object> receiver,
Handle<FixedArray> host_defined_options);
V8_WARN_UNUSED_RESULT static MaybeHandle<Object> CallBuiltin(
Isolate* isolate, Handle<JSFunction> builtin, Handle<Object> receiver,
......@@ -55,6 +59,14 @@ class Execution final : public AllStatic {
Isolate* isolate, Handle<Object> callable, Handle<Object> receiver,
int argc, Handle<Object> argv[], MessageHandling message_handling,
MaybeHandle<Object>* exception_out, bool reschedule_terminate = true);
// Same as Execute::TryCall but for scripts which need an explicit
// host-defined options object. See Execution:CallScript
V8_EXPORT_PRIVATE static MaybeHandle<Object> TryCallScript(
Isolate* isolate, Handle<JSFunction> script_function,
Handle<Object> receiver, Handle<FixedArray> host_defined_options,
MessageHandling message_handling, MaybeHandle<Object>* exception_out,
bool reschedule_terminate = true);
// Convenience method for performing RunMicrotasks
static MaybeHandle<Object> TryRunMicrotasks(
Isolate* isolate, MicrotaskQueue* microtask_queue,
......
......@@ -4122,8 +4122,11 @@ bool Genesis::CompileExtension(Isolate* isolate, v8::Extension* extension) {
// Call function using either the runtime object or the global
// object as the receiver. Provide no parameters.
Handle<Object> receiver = isolate->global_object();
return !Execution::TryCall(isolate, fun, receiver, 0, nullptr,
Execution::MessageHandling::kKeepPending, nullptr)
Handle<FixedArray> host_defined_options =
isolate->factory()->empty_fixed_array();
return !Execution::TryCallScript(isolate, fun, receiver, host_defined_options,
Execution::MessageHandling::kKeepPending,
nullptr)
.is_null();
}
......
......@@ -93,7 +93,9 @@ static double Inc(Isolate* isolate, int x) {
if (fun.is_null()) return -1;
Handle<JSObject> global(isolate->context().global_object(), isolate);
Execution::Call(isolate, fun, global, 0, nullptr).Check();
Execution::CallScript(isolate, fun, global,
isolate->factory()->empty_fixed_array())
.Check();
return GetGlobalProperty("result")->Number();
}
......@@ -112,7 +114,9 @@ static double Add(Isolate* isolate, int x, int y) {
SetGlobalProperty("x", Smi::FromInt(x));
SetGlobalProperty("y", Smi::FromInt(y));
Handle<JSObject> global(isolate->context().global_object(), isolate);
Execution::Call(isolate, fun, global, 0, nullptr).Check();
Execution::CallScript(isolate, fun, global,
isolate->factory()->empty_fixed_array())
.Check();
return GetGlobalProperty("result")->Number();
}
......@@ -130,7 +134,9 @@ static double Abs(Isolate* isolate, int x) {
SetGlobalProperty("x", Smi::FromInt(x));
Handle<JSObject> global(isolate->context().global_object(), isolate);
Execution::Call(isolate, fun, global, 0, nullptr).Check();
Execution::CallScript(isolate, fun, global,
isolate->factory()->empty_fixed_array())
.Check();
return GetGlobalProperty("result")->Number();
}
......@@ -149,7 +155,9 @@ static double Sum(Isolate* isolate, int n) {
SetGlobalProperty("n", Smi::FromInt(n));
Handle<JSObject> global(isolate->context().global_object(), isolate);
Execution::Call(isolate, fun, global, 0, nullptr).Check();
Execution::CallScript(isolate, fun, global,
isolate->factory()->empty_fixed_array())
.Check();
return GetGlobalProperty("result")->Number();
}
......@@ -168,9 +176,11 @@ TEST(Print) {
const char* source = "for (n = 0; n < 100; ++n) print(n, 1, 2);";
Handle<JSFunction> fun = Compile(source);
if (fun.is_null()) return;
Handle<JSObject> global(CcTest::i_isolate()->context().global_object(),
fun->GetIsolate());
Execution::Call(CcTest::i_isolate(), fun, global, 0, nullptr).Check();
auto isolate = CcTest::i_isolate();
Handle<JSObject> global(isolate->context().global_object(), isolate);
Execution::CallScript(isolate, fun, global,
isolate->factory()->empty_fixed_array())
.Check();
}
......@@ -200,9 +210,11 @@ TEST(Stuff) {
Handle<JSFunction> fun = Compile(source);
CHECK(!fun.is_null());
Handle<JSObject> global(CcTest::i_isolate()->context().global_object(),
fun->GetIsolate());
Execution::Call(CcTest::i_isolate(), fun, global, 0, nullptr).Check();
auto isolate = CcTest::i_isolate();
Handle<JSObject> global(isolate->context().global_object(), isolate);
Execution::CallScript(isolate, fun, global,
isolate->factory()->empty_fixed_array())
.Check();
CHECK_EQ(511.0, GetGlobalProperty("r")->Number());
}
......@@ -216,7 +228,9 @@ TEST(UncaughtThrow) {
CHECK(!fun.is_null());
Isolate* isolate = fun->GetIsolate();
Handle<JSObject> global(isolate->context().global_object(), isolate);
CHECK(Execution::Call(isolate, fun, global, 0, nullptr).is_null());
CHECK(Execution::CallScript(isolate, fun, global,
isolate->factory()->empty_fixed_array())
.is_null());
CHECK_EQ(42.0, isolate->pending_exception().Number());
}
......@@ -242,7 +256,9 @@ TEST(C2JSFrames) {
// Run the generated code to populate the global object with 'foo'.
Handle<JSObject> global(isolate->context().global_object(), isolate);
Execution::Call(isolate, fun0, global, 0, nullptr).Check();
Execution::CallScript(isolate, fun0, global,
isolate->factory()->empty_fixed_array())
.Check();
Handle<Object> fun1 =
JSReceiver::GetProperty(isolate, isolate->global_object(), "foo")
......
......@@ -1757,7 +1757,9 @@ void TestCodeSerializerOnePlusOneImpl(bool verify_builtins_count = true) {
.Build();
Handle<JSObject> global(isolate->context().global_object(), isolate);
Handle<Object> copy_result =
Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
Execution::CallScript(isolate, copy_fun, global,
isolate->factory()->empty_fixed_array())
.ToHandleChecked();
CHECK_EQ(2, Handle<Smi>::cast(copy_result)->value());
if (verify_builtins_count) CHECK_EQ(builtins_count, CountBuiltins());
......@@ -1854,7 +1856,7 @@ TEST(CodeSerializerPromotedToCompilationCache) {
}
{
// Lookup with different string should fail:
// Lookup with different name string should fail:
ScriptDetails script_details(
isolate->factory()->NewStringFromAsciiChecked("other"));
MaybeHandle<SharedFunctionInfo> shared =
......@@ -1945,7 +1947,9 @@ TEST(CodeSerializerInternalizedString) {
Factory::JSFunctionBuilder{isolate, orig, isolate->native_context()}
.Build();
Handle<Object> orig_result =
Execution::Call(isolate, orig_fun, global, 0, nullptr).ToHandleChecked();
Execution::CallScript(isolate, orig_fun, global,
isolate->factory()->empty_fixed_array())
.ToHandleChecked();
CHECK(orig_result->IsInternalizedString());
int builtins_count = CountBuiltins();
......@@ -1964,7 +1968,9 @@ TEST(CodeSerializerInternalizedString) {
.Build();
CHECK_NE(*orig_fun, *copy_fun);
Handle<Object> copy_result =
Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
Execution::CallScript(isolate, copy_fun, global,
isolate->factory()->empty_fixed_array())
.ToHandleChecked();
CHECK(orig_result.is_identical_to(copy_result));
Handle<String> expected =
isolate->factory()->NewStringFromAsciiChecked("string1");
......@@ -2017,7 +2023,9 @@ TEST(CodeSerializerLargeCodeObject) {
.Build();
Handle<Object> copy_result =
Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
Execution::CallScript(isolate, copy_fun, global,
isolate->factory()->empty_fixed_array())
.ToHandleChecked();
int result_int;
CHECK(copy_result->ToInt32(&result_int));
......@@ -2097,7 +2105,9 @@ TEST(CodeSerializerLargeCodeObjectWithIncrementalMarking) {
.Build();
Handle<Object> copy_result =
Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
Execution::CallScript(isolate, copy_fun, global,
isolate->factory()->empty_fixed_array())
.ToHandleChecked();
int result_int;
CHECK(copy_result->ToInt32(&result_int));
......@@ -2147,7 +2157,9 @@ TEST(CodeSerializerLargeStrings) {
.Build();
Handle<Object> copy_result =
Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
Execution::CallScript(isolate, copy_fun, global,
isolate->factory()->empty_fixed_array())
.ToHandleChecked();
CHECK_EQ(6 * 1999999, Handle<String>::cast(copy_result)->length());
Handle<Object> property = JSReceiver::GetDataProperty(
......@@ -2220,7 +2232,8 @@ TEST(CodeSerializerThreeBigStrings) {
Factory::JSFunctionBuilder{isolate, copy, isolate->native_context()}
.Build();
USE(Execution::Call(isolate, copy_fun, global, 0, nullptr));
USE(Execution::CallScript(isolate, copy_fun, global,
isolate->factory()->empty_fixed_array()));
v8::Maybe<int32_t> result =
CompileRun("(a + b).length")
......@@ -2340,7 +2353,9 @@ TEST(CodeSerializerExternalString) {
.Build();
Handle<Object> copy_result =
Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
Execution::CallScript(isolate, copy_fun, global,
isolate->factory()->empty_fixed_array())
.ToHandleChecked();
CHECK_EQ(15.0, copy_result->Number());
......@@ -2404,7 +2419,9 @@ TEST(CodeSerializerLargeExternalString) {
.Build();
Handle<Object> copy_result =
Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
Execution::CallScript(isolate, copy_fun, global,
isolate->factory()->empty_fixed_array())
.ToHandleChecked();
CHECK_EQ(42.0, copy_result->Number());
......@@ -2458,7 +2475,9 @@ TEST(CodeSerializerExternalScriptName) {
.Build();
Handle<Object> copy_result =
Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
Execution::CallScript(isolate, copy_fun, global,
isolate->factory()->empty_fixed_array())
.ToHandleChecked();
CHECK_EQ(10.0, copy_result->Number());
......
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