• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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