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