5 #include "src/execution.h" 7 #include "src/api-inl.h" 8 #include "src/bootstrapper.h" 9 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" 10 #include "src/debug/debug.h" 11 #include "src/isolate-inl.h" 12 #include "src/runtime-profiler.h" 13 #include "src/vm-state-inl.h" 18 void StackGuard::set_interrupt_limits(
const ExecutionAccess& lock) {
19 DCHECK_NOT_NULL(isolate_);
20 thread_local_.set_jslimit(kInterruptLimit);
21 thread_local_.set_climit(kInterruptLimit);
22 isolate_->heap()->SetStackLimits();
26 void StackGuard::reset_limits(
const ExecutionAccess& lock) {
27 DCHECK_NOT_NULL(isolate_);
28 thread_local_.set_jslimit(thread_local_.real_jslimit_);
29 thread_local_.set_climit(thread_local_.real_climit_);
30 isolate_->heap()->SetStackLimits();
34 static void PrintDeserializedCodeInfo(Handle<JSFunction>
function) {
35 if (function->code() ==
function->shared()->GetCode() &&
36 function->shared()->deserialized()) {
37 PrintF(
"[Running deserialized script");
38 Object* script =
function->shared()->script();
39 if (script->IsScript()) {
40 Object* name = Script::cast(script)->name();
41 if (name->IsString()) {
42 PrintF(
": %s", String::cast(name)->ToCString().
get());
52 V8_WARN_UNUSED_RESULT MaybeHandle<Object> Invoke(
53 Isolate* isolate,
bool is_construct, Handle<Object> target,
54 Handle<Object> receiver,
int argc, Handle<Object> args[],
55 Handle<Object> new_target, Execution::MessageHandling message_handling,
56 Execution::Target execution_target) {
57 DCHECK(!receiver->IsJSGlobalObject());
64 StackLimitCheck check(isolate);
65 if (check.HasOverflowed()) {
66 isolate->StackOverflow();
67 if (message_handling == Execution::MessageHandling::kReport) {
68 isolate->ReportPendingMessages();
70 return MaybeHandle<Object>();
76 if (target->IsJSFunction()) {
77 Handle<JSFunction>
function = Handle<JSFunction>::cast(target);
78 if ((!is_construct || function->IsConstructor()) &&
79 function->shared()->IsApiFunction() &&
80 !
function->shared()->BreakAtEntry()) {
81 SaveContext save(isolate);
82 isolate->set_context(function->context());
83 DCHECK(function->context()->global_object()->IsJSGlobalObject());
84 if (is_construct) receiver = isolate->factory()->the_hole_value();
85 auto value = Builtins::InvokeApiFunction(
86 isolate, is_construct,
function, receiver, argc, args,
87 Handle<HeapObject>::cast(new_target));
88 bool has_exception = value.is_null();
89 DCHECK(has_exception == isolate->has_pending_exception());
91 if (message_handling == Execution::MessageHandling::kReport) {
92 isolate->ReportPendingMessages();
94 return MaybeHandle<Object>();
96 isolate->clear_pending_message();
103 VMState<JS> state(isolate);
104 CHECK(AllowJavascriptExecution::IsAllowed(isolate));
105 if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
106 isolate->ThrowIllegalOperation();
107 if (message_handling == Execution::MessageHandling::kReport) {
108 isolate->ReportPendingMessages();
110 return MaybeHandle<Object>();
112 if (!DumpOnJavascriptExecution::IsAllowed(isolate)) {
113 V8::GetCurrentPlatform()->DumpWithoutCrashing();
114 return isolate->factory()->undefined_value();
118 Object* value =
nullptr;
120 using JSEntryFunction =
121 GeneratedCode<Object*(Object * new_target, Object * target,
122 Object * receiver,
int argc, Object*** args)>;
125 switch (execution_target) {
126 case Execution::Target::kCallable:
127 code = is_construct ? isolate->factory()->js_construct_entry_code()
128 : isolate->factory()->js_entry_code();
130 case Execution::Target::kRunMicrotasks:
131 code = isolate->factory()->js_run_microtasks_entry_code();
140 SaveContext save(isolate);
141 SealHandleScope shs(isolate);
142 JSEntryFunction stub_entry =
143 JSEntryFunction::FromAddress(isolate, code->entry());
145 if (FLAG_clear_exceptions_on_js_entry) isolate->clear_pending_exception();
148 Object* orig_func = *new_target;
149 Object* func = *target;
150 Object* recv = *receiver;
151 Object*** argv =
reinterpret_cast<Object***
>(args);
152 if (FLAG_profile_deserialization && target->IsJSFunction()) {
153 PrintDeserializedCodeInfo(Handle<JSFunction>::cast(target));
155 RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kJS_Execution);
156 value = stub_entry.Call(orig_func, func, recv, argc, argv);
160 if (FLAG_verify_heap) {
161 value->ObjectVerify(isolate);
166 bool has_exception = value->IsException(isolate);
167 DCHECK(has_exception == isolate->has_pending_exception());
169 if (message_handling == Execution::MessageHandling::kReport) {
170 isolate->ReportPendingMessages();
172 return MaybeHandle<Object>();
174 isolate->clear_pending_message();
177 return Handle<Object>(value, isolate);
180 MaybeHandle<Object> CallInternal(Isolate* isolate, Handle<Object> callable,
181 Handle<Object> receiver,
int argc,
182 Handle<Object> argv[],
183 Execution::MessageHandling message_handling,
184 Execution::Target target) {
188 if (receiver->IsJSGlobalObject()) {
190 handle(Handle<JSGlobalObject>::cast(receiver)->global_proxy(), isolate);
192 return Invoke(isolate,
false, callable, receiver, argc, argv,
193 isolate->factory()->undefined_value(), message_handling,
200 MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
201 Handle<Object> receiver,
int argc,
202 Handle<Object> argv[]) {
203 return CallInternal(isolate, callable, receiver, argc, argv,
204 MessageHandling::kReport, Execution::Target::kCallable);
209 MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor,
210 int argc, Handle<Object> argv[]) {
211 return New(isolate, constructor, constructor, argc, argv);
216 MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor,
217 Handle<Object> new_target,
int argc,
218 Handle<Object> argv[]) {
219 return Invoke(isolate,
true, constructor,
220 isolate->factory()->undefined_value(), argc, argv, new_target,
221 MessageHandling::kReport, Execution::Target::kCallable);
224 MaybeHandle<Object> Execution::TryCall(
225 Isolate* isolate, Handle<Object> callable, Handle<Object> receiver,
226 int argc, Handle<Object> args[], MessageHandling message_handling,
227 MaybeHandle<Object>* exception_out, Target target) {
228 bool is_termination =
false;
229 MaybeHandle<Object> maybe_result;
230 if (exception_out !=
nullptr) *exception_out = MaybeHandle<Object>();
231 DCHECK_IMPLIES(message_handling == MessageHandling::kKeepPending,
232 exception_out ==
nullptr);
238 v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
239 catcher.SetVerbose(
false);
240 catcher.SetCaptureMessage(
false);
242 maybe_result = CallInternal(isolate, callable, receiver, argc, args,
243 message_handling, target);
245 if (maybe_result.is_null()) {
246 DCHECK(isolate->has_pending_exception());
247 if (isolate->pending_exception() ==
248 ReadOnlyRoots(isolate).termination_exception()) {
249 is_termination =
true;
251 if (exception_out !=
nullptr) {
252 DCHECK(catcher.HasCaught());
253 DCHECK(isolate->external_caught_exception());
254 *exception_out = v8::Utils::OpenHandle(*catcher.Exception());
257 if (message_handling == MessageHandling::kReport) {
258 isolate->OptionalRescheduleException(
true);
264 if (is_termination) isolate->stack_guard()->RequestTerminateExecution();
269 MaybeHandle<Object> Execution::RunMicrotasks(
270 Isolate* isolate, MessageHandling message_handling,
271 MaybeHandle<Object>* exception_out) {
272 auto undefined = isolate->factory()->undefined_value();
273 return TryCall(isolate, undefined, undefined, 0, {}, message_handling,
274 exception_out, Target::kRunMicrotasks);
277 void StackGuard::SetStackLimit(
uintptr_t limit) {
278 ExecutionAccess access(isolate_);
281 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
282 if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
283 thread_local_.set_jslimit(jslimit);
285 if (thread_local_.climit() == thread_local_.real_climit_) {
286 thread_local_.set_climit(limit);
288 thread_local_.real_climit_ = limit;
289 thread_local_.real_jslimit_ = jslimit;
293 void StackGuard::AdjustStackLimitForSimulator() {
294 ExecutionAccess access(isolate_);
295 uintptr_t climit = thread_local_.real_climit_;
298 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, climit);
299 if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
300 thread_local_.set_jslimit(jslimit);
301 isolate_->heap()->SetStackLimits();
306 void StackGuard::EnableInterrupts() {
307 ExecutionAccess access(isolate_);
308 if (has_pending_interrupts(access)) {
309 set_interrupt_limits(access);
314 void StackGuard::DisableInterrupts() {
315 ExecutionAccess access(isolate_);
316 reset_limits(access);
319 void StackGuard::PushInterruptsScope(InterruptsScope* scope) {
320 ExecutionAccess access(isolate_);
321 DCHECK_NE(scope->mode_, InterruptsScope::kNoop);
322 if (scope->mode_ == InterruptsScope::kPostponeInterrupts) {
324 int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
325 scope->intercepted_flags_ = intercepted;
326 thread_local_.interrupt_flags_ &= ~intercepted;
328 DCHECK_EQ(scope->mode_, InterruptsScope::kRunInterrupts);
330 int restored_flags = 0;
331 for (InterruptsScope* current = thread_local_.interrupt_scopes_;
332 current !=
nullptr; current = current->prev_) {
333 restored_flags |= (current->intercepted_flags_ & scope->intercept_mask_);
334 current->intercepted_flags_ &= ~scope->intercept_mask_;
336 thread_local_.interrupt_flags_ |= restored_flags;
338 if (!has_pending_interrupts(access)) reset_limits(access);
340 scope->prev_ = thread_local_.interrupt_scopes_;
341 thread_local_.interrupt_scopes_ = scope;
344 void StackGuard::PopInterruptsScope() {
345 ExecutionAccess access(isolate_);
346 InterruptsScope* top = thread_local_.interrupt_scopes_;
347 DCHECK_NE(top->mode_, InterruptsScope::kNoop);
348 if (top->mode_ == InterruptsScope::kPostponeInterrupts) {
350 DCHECK_EQ(thread_local_.interrupt_flags_ & top->intercept_mask_, 0);
351 thread_local_.interrupt_flags_ |= top->intercepted_flags_;
353 DCHECK_EQ(top->mode_, InterruptsScope::kRunInterrupts);
356 for (
int interrupt = 1; interrupt < ALL_INTERRUPTS;
357 interrupt = interrupt << 1) {
358 InterruptFlag flag =
static_cast<InterruptFlag
>(interrupt);
359 if ((thread_local_.interrupt_flags_ & flag) &&
360 top->prev_->Intercept(flag)) {
361 thread_local_.interrupt_flags_ &= ~flag;
366 if (has_pending_interrupts(access)) set_interrupt_limits(access);
368 thread_local_.interrupt_scopes_ = top->prev_;
372 bool StackGuard::CheckInterrupt(InterruptFlag flag) {
373 ExecutionAccess access(isolate_);
374 return thread_local_.interrupt_flags_ & flag;
378 void StackGuard::RequestInterrupt(InterruptFlag flag) {
379 ExecutionAccess access(isolate_);
381 if (thread_local_.interrupt_scopes_ &&
382 thread_local_.interrupt_scopes_->Intercept(flag)) {
387 thread_local_.interrupt_flags_ |= flag;
388 set_interrupt_limits(access);
391 isolate_->futex_wait_list_node()->NotifyWake();
395 void StackGuard::ClearInterrupt(InterruptFlag flag) {
396 ExecutionAccess access(isolate_);
398 for (InterruptsScope* current = thread_local_.interrupt_scopes_;
399 current !=
nullptr; current = current->prev_) {
400 current->intercepted_flags_ &= ~flag;
404 thread_local_.interrupt_flags_ &= ~flag;
405 if (!has_pending_interrupts(access)) reset_limits(access);
409 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
410 ExecutionAccess access(isolate_);
411 bool result = (thread_local_.interrupt_flags_ & flag);
412 thread_local_.interrupt_flags_ &= ~flag;
413 if (!has_pending_interrupts(access)) reset_limits(access);
418 char* StackGuard::ArchiveStackGuard(
char* to) {
419 ExecutionAccess access(isolate_);
420 MemCopy(to, reinterpret_cast<char*>(&thread_local_),
sizeof(ThreadLocal));
428 isolate_->heap()->SetStackLimits();
429 thread_local_ = blank;
431 return to +
sizeof(ThreadLocal);
435 char* StackGuard::RestoreStackGuard(
char* from) {
436 ExecutionAccess access(isolate_);
437 MemCopy(reinterpret_cast<char*>(&thread_local_), from,
sizeof(ThreadLocal));
438 isolate_->heap()->SetStackLimits();
439 return from +
sizeof(ThreadLocal);
443 void StackGuard::FreeThreadResources() {
444 Isolate::PerIsolateThreadData* per_thread =
445 isolate_->FindOrAllocatePerThreadDataForThisThread();
446 per_thread->set_stack_limit(thread_local_.real_climit_);
450 void StackGuard::ThreadLocal::Clear() {
451 real_jslimit_ = kIllegalLimit;
452 set_jslimit(kIllegalLimit);
453 real_climit_ = kIllegalLimit;
454 set_climit(kIllegalLimit);
455 interrupt_scopes_ =
nullptr;
456 interrupt_flags_ = 0;
460 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
461 bool should_set_stack_limits =
false;
462 if (real_climit_ == kIllegalLimit) {
463 const uintptr_t kLimitSize = FLAG_stack_size * KB;
464 DCHECK_GT(GetCurrentStackPosition(), kLimitSize);
465 uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
466 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
467 set_jslimit(SimulatorStack::JsLimitFromCLimit(isolate, limit));
468 real_climit_ = limit;
470 should_set_stack_limits =
true;
472 interrupt_scopes_ =
nullptr;
473 interrupt_flags_ = 0;
474 return should_set_stack_limits;
478 void StackGuard::ClearThread(
const ExecutionAccess& lock) {
479 thread_local_.Clear();
480 isolate_->heap()->SetStackLimits();
484 void StackGuard::InitThread(
const ExecutionAccess& lock) {
485 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
486 Isolate::PerIsolateThreadData* per_thread =
487 isolate_->FindOrAllocatePerThreadDataForThisThread();
488 uintptr_t stored_limit = per_thread->stack_limit();
490 if (stored_limit != 0) {
491 SetStackLimit(stored_limit);
499 Object* StackGuard::HandleInterrupts() {
500 if (FLAG_verify_predictable) {
502 isolate_->heap()->MonotonicallyIncreasingTimeInMs();
505 bool any_interrupt_handled =
false;
506 if (FLAG_trace_interrupts) {
507 PrintF(
"[Handling interrupts: ");
510 if (CheckAndClearInterrupt(GC_REQUEST)) {
511 if (FLAG_trace_interrupts) {
512 PrintF(
"GC_REQUEST");
513 any_interrupt_handled =
true;
515 isolate_->heap()->HandleGCRequest();
518 if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
519 if (FLAG_trace_interrupts) {
520 if (any_interrupt_handled) PrintF(
", ");
521 PrintF(
"TERMINATE_EXECUTION");
522 any_interrupt_handled =
true;
524 return isolate_->TerminateExecution();
527 if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
528 if (FLAG_trace_interrupts) {
529 if (any_interrupt_handled) PrintF(
", ");
530 PrintF(
"DEOPT_MARKED_ALLOCATION_SITES");
531 any_interrupt_handled =
true;
533 isolate_->heap()->DeoptMarkedAllocationSites();
536 if (CheckAndClearInterrupt(INSTALL_CODE)) {
537 if (FLAG_trace_interrupts) {
538 if (any_interrupt_handled) PrintF(
", ");
539 PrintF(
"INSTALL_CODE");
540 any_interrupt_handled =
true;
542 DCHECK(isolate_->concurrent_recompilation_enabled());
543 isolate_->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
546 if (CheckAndClearInterrupt(API_INTERRUPT)) {
547 if (FLAG_trace_interrupts) {
548 if (any_interrupt_handled) PrintF(
", ");
549 PrintF(
"API_INTERRUPT");
550 any_interrupt_handled =
true;
553 isolate_->InvokeApiInterruptCallbacks();
556 if (FLAG_trace_interrupts) {
557 if (!any_interrupt_handled) {
558 PrintF(
"No interrupt flags set");
563 isolate_->counters()->stack_interrupts()->Increment();
564 isolate_->counters()->runtime_profiler_ticks()->Increment();
565 isolate_->runtime_profiler()->MarkCandidatesForOptimization();
567 return ReadOnlyRoots(isolate_).undefined_value();