1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/execution/execution.h"
6
7 #include "src/api/api-inl.h"
8 #include "src/debug/debug.h"
9 #include "src/execution/frames.h"
10 #include "src/execution/isolate-inl.h"
11 #include "src/execution/vm-state-inl.h"
12 #include "src/logging/runtime-call-stats-scope.h"
13
14 #if V8_ENABLE_WEBASSEMBLY
15 #include "src/compiler/wasm-compiler.h" // Only for static asserts.
16 #include "src/wasm/code-space-access.h"
17 #include "src/wasm/wasm-engine.h"
18 #endif // V8_ENABLE_WEBASSEMBLY
19
20 namespace v8 {
21 namespace internal {
22
23 namespace {
24
NormalizeReceiver(Isolate * isolate,Handle<Object> receiver)25 Handle<Object> NormalizeReceiver(Isolate* isolate, Handle<Object> receiver) {
26 // Convert calls on global objects to be calls on the global
27 // receiver instead to avoid having a 'this' pointer which refers
28 // directly to a global object.
29 if (receiver->IsJSGlobalObject()) {
30 return handle(Handle<JSGlobalObject>::cast(receiver)->global_proxy(),
31 isolate);
32 }
33 return receiver;
34 }
35
36 struct InvokeParams {
37 static InvokeParams SetUpForNew(Isolate* isolate, Handle<Object> constructor,
38 Handle<Object> new_target, int argc,
39 Handle<Object>* argv);
40
41 static InvokeParams SetUpForCall(Isolate* isolate, Handle<Object> callable,
42 Handle<Object> receiver, int argc,
43 Handle<Object>* argv);
44
45 static InvokeParams SetUpForTryCall(
46 Isolate* isolate, Handle<Object> callable, Handle<Object> receiver,
47 int argc, Handle<Object>* argv,
48 Execution::MessageHandling message_handling,
49 MaybeHandle<Object>* exception_out, bool reschedule_terminate);
50
51 static InvokeParams SetUpForRunMicrotasks(Isolate* isolate,
52 MicrotaskQueue* microtask_queue,
53 MaybeHandle<Object>* exception_out);
54
IsScriptv8::internal::__anon4e22d6320111::InvokeParams55 bool IsScript() const {
56 if (!target->IsJSFunction()) return false;
57 Handle<JSFunction> function = Handle<JSFunction>::cast(target);
58 return function->shared().is_script();
59 }
60
GetAndResetHostDefinedOptionsv8::internal::__anon4e22d6320111::InvokeParams61 Handle<FixedArray> GetAndResetHostDefinedOptions() {
62 DCHECK(IsScript());
63 DCHECK_EQ(argc, 1);
64 auto options = Handle<FixedArray>::cast(argv[0]);
65 argv = nullptr;
66 argc = 0;
67 return options;
68 }
69
70 Handle<Object> target;
71 Handle<Object> receiver;
72 int argc;
73 Handle<Object>* argv;
74 Handle<Object> new_target;
75
76 MicrotaskQueue* microtask_queue;
77
78 Execution::MessageHandling message_handling;
79 MaybeHandle<Object>* exception_out;
80
81 bool is_construct;
82 Execution::Target execution_target;
83 bool reschedule_terminate;
84 };
85
86 // static
SetUpForNew(Isolate * isolate,Handle<Object> constructor,Handle<Object> new_target,int argc,Handle<Object> * argv)87 InvokeParams InvokeParams::SetUpForNew(Isolate* isolate,
88 Handle<Object> constructor,
89 Handle<Object> new_target, int argc,
90 Handle<Object>* argv) {
91 InvokeParams params;
92 params.target = constructor;
93 params.receiver = isolate->factory()->undefined_value();
94 DCHECK(!params.IsScript());
95 params.argc = argc;
96 params.argv = argv;
97 params.new_target = new_target;
98 params.microtask_queue = nullptr;
99 params.message_handling = Execution::MessageHandling::kReport;
100 params.exception_out = nullptr;
101 params.is_construct = true;
102 params.execution_target = Execution::Target::kCallable;
103 params.reschedule_terminate = true;
104 return params;
105 }
106
107 // static
SetUpForCall(Isolate * isolate,Handle<Object> callable,Handle<Object> receiver,int argc,Handle<Object> * argv)108 InvokeParams InvokeParams::SetUpForCall(Isolate* isolate,
109 Handle<Object> callable,
110 Handle<Object> receiver, int argc,
111 Handle<Object>* argv) {
112 InvokeParams params;
113 params.target = callable;
114 params.receiver = NormalizeReceiver(isolate, receiver);
115 // Check for host-defined options argument for scripts.
116 DCHECK_IMPLIES(params.IsScript(), argc == 1);
117 DCHECK_IMPLIES(params.IsScript(), argv[0]->IsFixedArray());
118 params.argc = argc;
119 params.argv = argv;
120 params.new_target = isolate->factory()->undefined_value();
121 params.microtask_queue = nullptr;
122 params.message_handling = Execution::MessageHandling::kReport;
123 params.exception_out = nullptr;
124 params.is_construct = false;
125 params.execution_target = Execution::Target::kCallable;
126 params.reschedule_terminate = true;
127 return params;
128 }
129
130 // static
SetUpForTryCall(Isolate * isolate,Handle<Object> callable,Handle<Object> receiver,int argc,Handle<Object> * argv,Execution::MessageHandling message_handling,MaybeHandle<Object> * exception_out,bool reschedule_terminate)131 InvokeParams InvokeParams::SetUpForTryCall(
132 Isolate* isolate, Handle<Object> callable, Handle<Object> receiver,
133 int argc, Handle<Object>* argv, Execution::MessageHandling message_handling,
134 MaybeHandle<Object>* exception_out, bool reschedule_terminate) {
135 InvokeParams params;
136 params.target = callable;
137 params.receiver = NormalizeReceiver(isolate, receiver);
138 // Check for host-defined options argument for scripts.
139 DCHECK_IMPLIES(params.IsScript(), argc == 1);
140 DCHECK_IMPLIES(params.IsScript(), argv[0]->IsFixedArray());
141 params.argc = argc;
142 params.argv = argv;
143 params.new_target = isolate->factory()->undefined_value();
144 params.microtask_queue = nullptr;
145 params.message_handling = message_handling;
146 params.exception_out = exception_out;
147 params.is_construct = false;
148 params.execution_target = Execution::Target::kCallable;
149 params.reschedule_terminate = reschedule_terminate;
150 return params;
151 }
152
153 // static
SetUpForRunMicrotasks(Isolate * isolate,MicrotaskQueue * microtask_queue,MaybeHandle<Object> * exception_out)154 InvokeParams InvokeParams::SetUpForRunMicrotasks(
155 Isolate* isolate, MicrotaskQueue* microtask_queue,
156 MaybeHandle<Object>* exception_out) {
157 auto undefined = isolate->factory()->undefined_value();
158 InvokeParams params;
159 params.target = undefined;
160 params.receiver = undefined;
161 params.argc = 0;
162 params.argv = nullptr;
163 params.new_target = undefined;
164 params.microtask_queue = microtask_queue;
165 params.message_handling = Execution::MessageHandling::kReport;
166 params.exception_out = exception_out;
167 params.is_construct = false;
168 params.execution_target = Execution::Target::kRunMicrotasks;
169 params.reschedule_terminate = true;
170 return params;
171 }
172
JSEntry(Isolate * isolate,Execution::Target execution_target,bool is_construct)173 Handle<CodeT> JSEntry(Isolate* isolate, Execution::Target execution_target,
174 bool is_construct) {
175 if (is_construct) {
176 DCHECK_EQ(Execution::Target::kCallable, execution_target);
177 return BUILTIN_CODE(isolate, JSConstructEntry);
178 } else if (execution_target == Execution::Target::kCallable) {
179 DCHECK(!is_construct);
180 return BUILTIN_CODE(isolate, JSEntry);
181 } else if (execution_target == Execution::Target::kRunMicrotasks) {
182 DCHECK(!is_construct);
183 return BUILTIN_CODE(isolate, JSRunMicrotasksEntry);
184 }
185 UNREACHABLE();
186 }
187
NewScriptContext(Isolate * isolate,Handle<JSFunction> function,Handle<FixedArray> host_defined_options)188 MaybeHandle<Context> NewScriptContext(Isolate* isolate,
189 Handle<JSFunction> function,
190 Handle<FixedArray> host_defined_options) {
191 // TODO(cbruni, 1244145): Use passed in host_defined_options.
192 // Creating a script context is a side effect, so abort if that's not
193 // allowed.
194 if (isolate->debug_execution_mode() == DebugInfo::kSideEffects) {
195 isolate->Throw(*isolate->factory()->NewEvalError(
196 MessageTemplate::kNoSideEffectDebugEvaluate));
197 return MaybeHandle<Context>();
198 }
199 SaveAndSwitchContext save(isolate, function->context());
200 SharedFunctionInfo sfi = function->shared();
201 Handle<Script> script(Script::cast(sfi.script()), isolate);
202 Handle<ScopeInfo> scope_info(sfi.scope_info(), isolate);
203 Handle<NativeContext> native_context(NativeContext::cast(function->context()),
204 isolate);
205 Handle<JSGlobalObject> global_object(native_context->global_object(),
206 isolate);
207 Handle<ScriptContextTable> script_context(
208 native_context->script_context_table(), isolate);
209
210 // Find name clashes.
211 for (auto it : ScopeInfo::IterateLocalNames(scope_info)) {
212 Handle<String> name(it->name(), isolate);
213 VariableMode mode = scope_info->ContextLocalMode(it->index());
214 VariableLookupResult lookup;
215 if (script_context->Lookup(name, &lookup)) {
216 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
217 Handle<Context> context = ScriptContextTable::GetContext(
218 isolate, script_context, lookup.context_index);
219 // If we are trying to re-declare a REPL-mode let as a let or REPL-mode
220 // const as a const, allow it.
221 if (!(((mode == VariableMode::kLet &&
222 lookup.mode == VariableMode::kLet) ||
223 (mode == VariableMode::kConst &&
224 lookup.mode == VariableMode::kConst)) &&
225 scope_info->IsReplModeScope() &&
226 context->scope_info().IsReplModeScope())) {
227 // ES#sec-globaldeclarationinstantiation 5.b:
228 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
229 // exception.
230 MessageLocation location(script, 0, 1);
231 return isolate->ThrowAt<Context>(
232 isolate->factory()->NewSyntaxError(
233 MessageTemplate::kVarRedeclaration, name),
234 &location);
235 }
236 }
237 }
238
239 if (IsLexicalVariableMode(mode)) {
240 LookupIterator it(isolate, global_object, name, global_object,
241 LookupIterator::OWN_SKIP_INTERCEPTOR);
242 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
243 // Can't fail since the we looking up own properties on the global object
244 // skipping interceptors.
245 CHECK(!maybe.IsNothing());
246 if ((maybe.FromJust() & DONT_DELETE) != 0) {
247 // ES#sec-globaldeclarationinstantiation 5.a:
248 // If envRec.HasVarDeclaration(name) is true, throw a SyntaxError
249 // exception.
250 // ES#sec-globaldeclarationinstantiation 5.d:
251 // If hasRestrictedGlobal is true, throw a SyntaxError exception.
252 MessageLocation location(script, 0, 1);
253 return isolate->ThrowAt<Context>(
254 isolate->factory()->NewSyntaxError(
255 MessageTemplate::kVarRedeclaration, name),
256 &location);
257 }
258
259 JSGlobalObject::InvalidatePropertyCell(global_object, name);
260 }
261 }
262
263 Handle<Context> result =
264 isolate->factory()->NewScriptContext(native_context, scope_info);
265
266 result->Initialize(isolate);
267 // In REPL mode, we are allowed to add/modify let/const variables.
268 // We use the previous defined script context for those.
269 const bool ignore_duplicates = scope_info->IsReplModeScope();
270 Handle<ScriptContextTable> new_script_context_table =
271 ScriptContextTable::Extend(isolate, script_context, result,
272 ignore_duplicates);
273 native_context->synchronized_set_script_context_table(
274 *new_script_context_table);
275 return result;
276 }
277
Invoke(Isolate * isolate,const InvokeParams & params)278 V8_WARN_UNUSED_RESULT MaybeHandle<Object> Invoke(Isolate* isolate,
279 const InvokeParams& params) {
280 RCS_SCOPE(isolate, RuntimeCallCounterId::kInvoke);
281 DCHECK(!params.receiver->IsJSGlobalObject());
282 DCHECK_LE(params.argc, FixedArray::kMaxLength);
283
284 #if V8_ENABLE_WEBASSEMBLY
285 // When executing JS code, there should be no {CodeSpaceWriteScope} open.
286 DCHECK(!wasm::CodeSpaceWriteScope::IsInScope());
287 // If we have PKU support for Wasm, ensure that code is currently write
288 // protected for this thread.
289 DCHECK_IMPLIES(wasm::GetWasmCodeManager()->HasMemoryProtectionKeySupport(),
290 !wasm::GetWasmCodeManager()->MemoryProtectionKeyWritable());
291 #endif // V8_ENABLE_WEBASSEMBLY
292
293 #ifdef USE_SIMULATOR
294 // Simulators use separate stacks for C++ and JS. JS stack overflow checks
295 // are performed whenever a JS function is called. However, it can be the case
296 // that the C++ stack grows faster than the JS stack, resulting in an overflow
297 // there. Add a check here to make that less likely.
298 StackLimitCheck check(isolate);
299 if (check.HasOverflowed()) {
300 isolate->StackOverflow();
301 if (params.message_handling == Execution::MessageHandling::kReport) {
302 isolate->ReportPendingMessages();
303 }
304 return MaybeHandle<Object>();
305 }
306 #endif
307
308 // api callbacks can be called directly, unless we want to take the detour
309 // through JS to set up a frame for break-at-entry.
310 if (params.target->IsJSFunction()) {
311 Handle<JSFunction> function = Handle<JSFunction>::cast(params.target);
312 if ((!params.is_construct || function->IsConstructor()) &&
313 function->shared().IsApiFunction() &&
314 !function->shared().BreakAtEntry()) {
315 SaveAndSwitchContext save(isolate, function->context());
316 DCHECK(function->context().global_object().IsJSGlobalObject());
317
318 Handle<Object> receiver = params.is_construct
319 ? isolate->factory()->the_hole_value()
320 : params.receiver;
321 auto value = Builtins::InvokeApiFunction(
322 isolate, params.is_construct, function, receiver, params.argc,
323 params.argv, Handle<HeapObject>::cast(params.new_target));
324 bool has_exception = value.is_null();
325 DCHECK(has_exception == isolate->has_pending_exception());
326 if (has_exception) {
327 if (params.message_handling == Execution::MessageHandling::kReport) {
328 isolate->ReportPendingMessages();
329 }
330 return MaybeHandle<Object>();
331 } else {
332 isolate->clear_pending_message();
333 }
334 return value;
335 }
336 #ifdef DEBUG
337 if (function->shared().is_script()) {
338 DCHECK(params.IsScript());
339 DCHECK(params.receiver->IsJSGlobalProxy());
340 DCHECK_EQ(params.argc, 1);
341 DCHECK(params.argv[0]->IsFixedArray());
342 } else {
343 DCHECK(!params.IsScript());
344 }
345 #endif
346 // Set up a ScriptContext when running scripts that need it.
347 if (function->shared().needs_script_context()) {
348 Handle<Context> context;
349 Handle<FixedArray> host_defined_options =
350 const_cast<InvokeParams&>(params).GetAndResetHostDefinedOptions();
351 if (!NewScriptContext(isolate, function, host_defined_options)
352 .ToHandle(&context)) {
353 if (params.message_handling == Execution::MessageHandling::kReport) {
354 isolate->ReportPendingMessages();
355 }
356 return MaybeHandle<Object>();
357 }
358
359 // We mutate the context if we allocate a script context. This is
360 // guaranteed to only happen once in a native context since scripts will
361 // always produce name clashes with themselves.
362 function->set_context(*context);
363 }
364 }
365
366 // Entering JavaScript.
367 VMState<JS> state(isolate);
368 CHECK(AllowJavascriptExecution::IsAllowed(isolate));
369 if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
370 isolate->ThrowIllegalOperation();
371 if (params.message_handling == Execution::MessageHandling::kReport) {
372 isolate->ReportPendingMessages();
373 }
374 return MaybeHandle<Object>();
375 }
376 if (!DumpOnJavascriptExecution::IsAllowed(isolate)) {
377 V8::GetCurrentPlatform()->DumpWithoutCrashing();
378 return isolate->factory()->undefined_value();
379 }
380
381 if (params.execution_target == Execution::Target::kCallable) {
382 Handle<Context> context = isolate->native_context();
383 if (!context->script_execution_callback().IsUndefined(isolate)) {
384 v8::Context::AbortScriptExecutionCallback callback =
385 v8::ToCData<v8::Context::AbortScriptExecutionCallback>(
386 context->script_execution_callback());
387 v8::Isolate* api_isolate = reinterpret_cast<v8::Isolate*>(isolate);
388 v8::Local<v8::Context> api_context = v8::Utils::ToLocal(context);
389 callback(api_isolate, api_context);
390 DCHECK(!isolate->has_scheduled_exception());
391 // Always throw an exception to abort execution, if callback exists.
392 isolate->ThrowIllegalOperation();
393 return MaybeHandle<Object>();
394 }
395 }
396
397 // Placeholder for return value.
398 Object value;
399 Handle<CodeT> code =
400 JSEntry(isolate, params.execution_target, params.is_construct);
401 {
402 // Save and restore context around invocation and block the
403 // allocation of handles without explicit handle scopes.
404 SaveContext save(isolate);
405 SealHandleScope shs(isolate);
406
407 if (FLAG_clear_exceptions_on_js_entry) isolate->clear_pending_exception();
408
409 if (params.execution_target == Execution::Target::kCallable) {
410 // clang-format off
411 // {new_target}, {target}, {receiver}, return value: tagged pointers
412 // {argv}: pointer to array of tagged pointers
413 using JSEntryFunction = GeneratedCode<Address(
414 Address root_register_value, Address new_target, Address target,
415 Address receiver, intptr_t argc, Address** argv)>;
416 // clang-format on
417 JSEntryFunction stub_entry =
418 JSEntryFunction::FromAddress(isolate, code->InstructionStart());
419
420 Address orig_func = params.new_target->ptr();
421 Address func = params.target->ptr();
422 Address recv = params.receiver->ptr();
423 Address** argv = reinterpret_cast<Address**>(params.argv);
424 RCS_SCOPE(isolate, RuntimeCallCounterId::kJS_Execution);
425 value = Object(stub_entry.Call(isolate->isolate_data()->isolate_root(),
426 orig_func, func, recv,
427 JSParameterCount(params.argc), argv));
428 } else {
429 DCHECK_EQ(Execution::Target::kRunMicrotasks, params.execution_target);
430
431 // clang-format off
432 // return value: tagged pointers
433 // {microtask_queue}: pointer to a C++ object
434 using JSEntryFunction = GeneratedCode<Address(
435 Address root_register_value, MicrotaskQueue* microtask_queue)>;
436 // clang-format on
437 JSEntryFunction stub_entry =
438 JSEntryFunction::FromAddress(isolate, code->InstructionStart());
439
440 RCS_SCOPE(isolate, RuntimeCallCounterId::kJS_Execution);
441 value = Object(stub_entry.Call(isolate->isolate_data()->isolate_root(),
442 params.microtask_queue));
443 }
444 }
445
446 #ifdef VERIFY_HEAP
447 if (FLAG_verify_heap) {
448 value.ObjectVerify(isolate);
449 }
450 #endif
451
452 // Update the pending exception flag and return the value.
453 bool has_exception = value.IsException(isolate);
454 DCHECK(has_exception == isolate->has_pending_exception());
455 if (has_exception) {
456 if (params.message_handling == Execution::MessageHandling::kReport) {
457 isolate->ReportPendingMessages();
458 }
459 return MaybeHandle<Object>();
460 } else {
461 isolate->clear_pending_message();
462 }
463
464 return Handle<Object>(value, isolate);
465 }
466
InvokeWithTryCatch(Isolate * isolate,const InvokeParams & params)467 MaybeHandle<Object> InvokeWithTryCatch(Isolate* isolate,
468 const InvokeParams& params) {
469 bool is_termination = false;
470 MaybeHandle<Object> maybe_result;
471 if (params.exception_out != nullptr) {
472 *params.exception_out = MaybeHandle<Object>();
473 }
474 DCHECK_IMPLIES(
475 params.message_handling == Execution::MessageHandling::kKeepPending,
476 params.exception_out == nullptr);
477 // Enter a try-block while executing the JavaScript code. To avoid
478 // duplicate error printing it must be non-verbose. Also, to avoid
479 // creating message objects during stack overflow we shouldn't
480 // capture messages.
481 {
482 v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
483 catcher.SetVerbose(false);
484 catcher.SetCaptureMessage(false);
485
486 maybe_result = Invoke(isolate, params);
487
488 if (maybe_result.is_null()) {
489 DCHECK(isolate->has_pending_exception());
490 if (isolate->pending_exception() ==
491 ReadOnlyRoots(isolate).termination_exception()) {
492 is_termination = true;
493 } else {
494 if (params.exception_out != nullptr) {
495 DCHECK(catcher.HasCaught());
496 DCHECK(isolate->external_caught_exception());
497 *params.exception_out = v8::Utils::OpenHandle(*catcher.Exception());
498 }
499 if (params.message_handling == Execution::MessageHandling::kReport) {
500 isolate->OptionalRescheduleException(true);
501 }
502 }
503 }
504 }
505
506 if (is_termination && params.reschedule_terminate) {
507 // Reschedule terminate execution exception.
508 isolate->OptionalRescheduleException(false);
509 }
510
511 return maybe_result;
512 }
513
514 } // namespace
515
516 // static
Call(Isolate * isolate,Handle<Object> callable,Handle<Object> receiver,int argc,Handle<Object> argv[])517 MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
518 Handle<Object> receiver, int argc,
519 Handle<Object> argv[]) {
520 // Use Execution::CallScript instead for scripts:
521 DCHECK_IMPLIES(callable->IsJSFunction(),
522 !JSFunction::cast(*callable).shared().is_script());
523 return Invoke(isolate, InvokeParams::SetUpForCall(isolate, callable, receiver,
524 argc, argv));
525 }
526
527 // static
CallScript(Isolate * isolate,Handle<JSFunction> script_function,Handle<Object> receiver,Handle<Object> host_defined_options)528 MaybeHandle<Object> Execution::CallScript(Isolate* isolate,
529 Handle<JSFunction> script_function,
530 Handle<Object> receiver,
531 Handle<Object> host_defined_options) {
532 DCHECK(script_function->shared().is_script());
533 DCHECK(receiver->IsJSGlobalProxy() || receiver->IsJSGlobalObject());
534 return Invoke(
535 isolate, InvokeParams::SetUpForCall(isolate, script_function, receiver, 1,
536 &host_defined_options));
537 }
538
CallBuiltin(Isolate * isolate,Handle<JSFunction> builtin,Handle<Object> receiver,int argc,Handle<Object> argv[])539 MaybeHandle<Object> Execution::CallBuiltin(Isolate* isolate,
540 Handle<JSFunction> builtin,
541 Handle<Object> receiver, int argc,
542 Handle<Object> argv[]) {
543 DCHECK(builtin->code().is_builtin());
544 DisableBreak no_break(isolate->debug());
545 return Invoke(isolate, InvokeParams::SetUpForCall(isolate, builtin, receiver,
546 argc, argv));
547 }
548
549 // static
New(Isolate * isolate,Handle<Object> constructor,int argc,Handle<Object> argv[])550 MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor,
551 int argc, Handle<Object> argv[]) {
552 return New(isolate, constructor, constructor, argc, argv);
553 }
554
555 // static
New(Isolate * isolate,Handle<Object> constructor,Handle<Object> new_target,int argc,Handle<Object> argv[])556 MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor,
557 Handle<Object> new_target, int argc,
558 Handle<Object> argv[]) {
559 return Invoke(isolate, InvokeParams::SetUpForNew(isolate, constructor,
560 new_target, argc, argv));
561 }
562
563 // static
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)564 MaybeHandle<Object> Execution::TryCallScript(
565 Isolate* isolate, Handle<JSFunction> script_function,
566 Handle<Object> receiver, Handle<FixedArray> host_defined_options,
567 MessageHandling message_handling, MaybeHandle<Object>* exception_out,
568 bool reschedule_terminate) {
569 DCHECK(script_function->shared().is_script());
570 DCHECK(receiver->IsJSGlobalProxy() || receiver->IsJSGlobalObject());
571 Handle<Object> argument = host_defined_options;
572 return InvokeWithTryCatch(
573 isolate, InvokeParams::SetUpForTryCall(
574 isolate, script_function, receiver, 1, &argument,
575 message_handling, exception_out, reschedule_terminate));
576 }
577
578 // static
TryCall(Isolate * isolate,Handle<Object> callable,Handle<Object> receiver,int argc,Handle<Object> argv[],MessageHandling message_handling,MaybeHandle<Object> * exception_out,bool reschedule_terminate)579 MaybeHandle<Object> Execution::TryCall(
580 Isolate* isolate, Handle<Object> callable, Handle<Object> receiver,
581 int argc, Handle<Object> argv[], MessageHandling message_handling,
582 MaybeHandle<Object>* exception_out, bool reschedule_terminate) {
583 // Use Execution::TryCallScript instead for scripts:
584 DCHECK_IMPLIES(callable->IsJSFunction(),
585 !JSFunction::cast(*callable).shared().is_script());
586 return InvokeWithTryCatch(
587 isolate, InvokeParams::SetUpForTryCall(
588 isolate, callable, receiver, argc, argv, message_handling,
589 exception_out, reschedule_terminate));
590 }
591
592 // static
TryRunMicrotasks(Isolate * isolate,MicrotaskQueue * microtask_queue,MaybeHandle<Object> * exception_out)593 MaybeHandle<Object> Execution::TryRunMicrotasks(
594 Isolate* isolate, MicrotaskQueue* microtask_queue,
595 MaybeHandle<Object>* exception_out) {
596 return InvokeWithTryCatch(
597 isolate, InvokeParams::SetUpForRunMicrotasks(isolate, microtask_queue,
598 exception_out));
599 }
600
601 struct StackHandlerMarker {
602 Address next;
603 Address padding;
604 };
605 STATIC_ASSERT(offsetof(StackHandlerMarker, next) ==
606 StackHandlerConstants::kNextOffset);
607 STATIC_ASSERT(offsetof(StackHandlerMarker, padding) ==
608 StackHandlerConstants::kPaddingOffset);
609 STATIC_ASSERT(sizeof(StackHandlerMarker) == StackHandlerConstants::kSize);
610
611 #if V8_ENABLE_WEBASSEMBLY
CallWasm(Isolate * isolate,Handle<CodeT> wrapper_code,Address wasm_call_target,Handle<Object> object_ref,Address packed_args)612 void Execution::CallWasm(Isolate* isolate, Handle<CodeT> wrapper_code,
613 Address wasm_call_target, Handle<Object> object_ref,
614 Address packed_args) {
615 using WasmEntryStub = GeneratedCode<Address(
616 Address target, Address object_ref, Address argv, Address c_entry_fp)>;
617 WasmEntryStub stub_entry =
618 WasmEntryStub::FromAddress(isolate, wrapper_code->InstructionStart());
619
620 // Save and restore context around invocation and block the
621 // allocation of handles without explicit handle scopes.
622 SaveContext save(isolate);
623 SealHandleScope shs(isolate);
624
625 Address saved_c_entry_fp = *isolate->c_entry_fp_address();
626 Address saved_js_entry_sp = *isolate->js_entry_sp_address();
627 if (saved_js_entry_sp == kNullAddress) {
628 *isolate->js_entry_sp_address() = GetCurrentStackPosition();
629 }
630 StackHandlerMarker stack_handler;
631 stack_handler.next = isolate->thread_local_top()->handler_;
632 #ifdef V8_USE_ADDRESS_SANITIZER
633 stack_handler.padding = GetCurrentStackPosition();
634 #else
635 stack_handler.padding = 0;
636 #endif
637 isolate->thread_local_top()->handler_ =
638 reinterpret_cast<Address>(&stack_handler);
639 trap_handler::SetThreadInWasm();
640
641 {
642 RCS_SCOPE(isolate, RuntimeCallCounterId::kJS_Execution);
643 STATIC_ASSERT(compiler::CWasmEntryParameters::kCodeEntry == 0);
644 STATIC_ASSERT(compiler::CWasmEntryParameters::kObjectRef == 1);
645 STATIC_ASSERT(compiler::CWasmEntryParameters::kArgumentsBuffer == 2);
646 STATIC_ASSERT(compiler::CWasmEntryParameters::kCEntryFp == 3);
647 Address result = stub_entry.Call(wasm_call_target, object_ref->ptr(),
648 packed_args, saved_c_entry_fp);
649 if (result != kNullAddress) {
650 isolate->set_pending_exception(Object(result));
651 }
652 }
653
654 // If there was an exception, then the thread-in-wasm flag is cleared
655 // already.
656 if (trap_handler::IsThreadInWasm()) {
657 trap_handler::ClearThreadInWasm();
658 }
659 isolate->thread_local_top()->handler_ = stack_handler.next;
660 if (saved_js_entry_sp == kNullAddress) {
661 *isolate->js_entry_sp_address() = saved_js_entry_sp;
662 }
663 *isolate->c_entry_fp_address() = saved_c_entry_fp;
664 }
665 #endif // V8_ENABLE_WEBASSEMBLY
666
667 } // namespace internal
668 } // namespace v8
669