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