4ab2403e56f0a0cc9d9345e51e0a233a260ff21c
[platform/upstream/v8.git] / src / execution.cc
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.h"
6
7 #include "src/bootstrapper.h"
8 #include "src/codegen.h"
9 #include "src/deoptimizer.h"
10 #include "src/messages.h"
11 #include "src/vm-state-inl.h"
12
13 namespace v8 {
14 namespace internal {
15
16 StackGuard::StackGuard()
17     : isolate_(NULL) {
18 }
19
20
21 void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
22   DCHECK(isolate_ != NULL);
23   thread_local_.set_jslimit(kInterruptLimit);
24   thread_local_.set_climit(kInterruptLimit);
25   isolate_->heap()->SetStackLimits();
26 }
27
28
29 void StackGuard::reset_limits(const ExecutionAccess& lock) {
30   DCHECK(isolate_ != NULL);
31   thread_local_.set_jslimit(thread_local_.real_jslimit_);
32   thread_local_.set_climit(thread_local_.real_climit_);
33   isolate_->heap()->SetStackLimits();
34 }
35
36
37 static void PrintDeserializedCodeInfo(Handle<JSFunction> function) {
38   if (function->code() == function->shared()->code() &&
39       function->shared()->deserialized()) {
40     PrintF("[Running deserialized script");
41     Object* script = function->shared()->script();
42     if (script->IsScript()) {
43       Object* name = Script::cast(script)->name();
44       if (name->IsString()) {
45         PrintF(": %s", String::cast(name)->ToCString().get());
46       }
47     }
48     PrintF("]\n");
49   }
50 }
51
52
53 MUST_USE_RESULT static MaybeHandle<Object> Invoke(
54     bool is_construct,
55     Handle<JSFunction> function,
56     Handle<Object> receiver,
57     int argc,
58     Handle<Object> args[]) {
59   Isolate* isolate = function->GetIsolate();
60
61   // api callbacks can be called directly.
62   if (!is_construct && function->shared()->IsApiFunction()) {
63     SaveContext save(isolate);
64     isolate->set_context(function->context());
65     if (receiver->IsGlobalObject()) {
66       receiver = handle(Handle<GlobalObject>::cast(receiver)->global_proxy());
67     }
68     DCHECK(function->context()->global_object()->IsGlobalObject());
69     auto value = Builtins::InvokeApiFunction(function, receiver, argc, args);
70     bool has_exception = value.is_null();
71     DCHECK(has_exception == isolate->has_pending_exception());
72     if (has_exception) {
73       isolate->ReportPendingMessages();
74       return MaybeHandle<Object>();
75     } else {
76       isolate->clear_pending_message();
77     }
78     return value;
79   }
80
81   // Entering JavaScript.
82   VMState<JS> state(isolate);
83   CHECK(AllowJavascriptExecution::IsAllowed(isolate));
84   if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
85     isolate->ThrowIllegalOperation();
86     isolate->ReportPendingMessages();
87     return MaybeHandle<Object>();
88   }
89
90   // Placeholder for return value.
91   Object* value = NULL;
92
93   typedef Object* (*JSEntryFunction)(byte* entry,
94                                      Object* function,
95                                      Object* receiver,
96                                      int argc,
97                                      Object*** args);
98
99   Handle<Code> code = is_construct
100       ? isolate->factory()->js_construct_entry_code()
101       : isolate->factory()->js_entry_code();
102
103   // Convert calls on global objects to be calls on the global
104   // receiver instead to avoid having a 'this' pointer which refers
105   // directly to a global object.
106   if (receiver->IsGlobalObject()) {
107     receiver = handle(Handle<GlobalObject>::cast(receiver)->global_proxy());
108   }
109
110   // Make sure that the global object of the context we're about to
111   // make the current one is indeed a global object.
112   DCHECK(function->context()->global_object()->IsGlobalObject());
113
114   {
115     // Save and restore context around invocation and block the
116     // allocation of handles without explicit handle scopes.
117     SaveContext save(isolate);
118     SealHandleScope shs(isolate);
119     JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
120
121     // Call the function through the right JS entry stub.
122     byte* function_entry = function->code()->entry();
123     JSFunction* func = *function;
124     Object* recv = *receiver;
125     Object*** argv = reinterpret_cast<Object***>(args);
126     if (FLAG_profile_deserialization) PrintDeserializedCodeInfo(function);
127     value =
128         CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv);
129   }
130
131 #ifdef VERIFY_HEAP
132   if (FLAG_verify_heap) {
133     value->ObjectVerify();
134   }
135 #endif
136
137   // Update the pending exception flag and return the value.
138   bool has_exception = value->IsException();
139   DCHECK(has_exception == isolate->has_pending_exception());
140   if (has_exception) {
141     isolate->ReportPendingMessages();
142     // Reset stepping state when script exits with uncaught exception.
143     if (isolate->debug()->is_active()) {
144       isolate->debug()->ClearStepping();
145     }
146     return MaybeHandle<Object>();
147   } else {
148     isolate->clear_pending_message();
149   }
150
151   return Handle<Object>(value, isolate);
152 }
153
154
155 MaybeHandle<Object> Execution::Call(Isolate* isolate,
156                                     Handle<Object> callable,
157                                     Handle<Object> receiver,
158                                     int argc,
159                                     Handle<Object> argv[],
160                                     bool convert_receiver) {
161   if (!callable->IsJSFunction()) {
162     ASSIGN_RETURN_ON_EXCEPTION(
163         isolate, callable, TryGetFunctionDelegate(isolate, callable), Object);
164   }
165   Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
166
167   // In sloppy mode, convert receiver.
168   if (convert_receiver && !receiver->IsJSReceiver() &&
169       !func->shared()->native() && is_sloppy(func->shared()->language_mode())) {
170     if (receiver->IsUndefined() || receiver->IsNull()) {
171       receiver = handle(func->global_proxy());
172       DCHECK(!receiver->IsJSBuiltinsObject());
173     } else {
174       ASSIGN_RETURN_ON_EXCEPTION(
175           isolate, receiver, ToObject(isolate, receiver), Object);
176     }
177   }
178
179   return Invoke(false, func, receiver, argc, argv);
180 }
181
182
183 MaybeHandle<Object> Execution::New(Handle<JSFunction> func,
184                                    int argc,
185                                    Handle<Object> argv[]) {
186   return Invoke(true, func, handle(func->global_proxy()), argc, argv);
187 }
188
189
190 MaybeHandle<Object> Execution::TryCall(Handle<JSFunction> func,
191                                        Handle<Object> receiver, int argc,
192                                        Handle<Object> args[],
193                                        MaybeHandle<Object>* exception_out) {
194   bool is_termination = false;
195   Isolate* isolate = func->GetIsolate();
196   MaybeHandle<Object> maybe_result;
197   if (exception_out != NULL) *exception_out = MaybeHandle<Object>();
198   // Enter a try-block while executing the JavaScript code. To avoid
199   // duplicate error printing it must be non-verbose.  Also, to avoid
200   // creating message objects during stack overflow we shouldn't
201   // capture messages.
202   {
203     v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
204     catcher.SetVerbose(false);
205     catcher.SetCaptureMessage(false);
206
207     maybe_result = Invoke(false, func, receiver, argc, args);
208
209     if (maybe_result.is_null()) {
210       DCHECK(catcher.HasCaught());
211       DCHECK(isolate->has_pending_exception());
212       DCHECK(isolate->external_caught_exception());
213       if (isolate->pending_exception() ==
214           isolate->heap()->termination_exception()) {
215         is_termination = true;
216       } else {
217         if (exception_out != NULL) {
218           *exception_out = v8::Utils::OpenHandle(*catcher.Exception());
219         }
220       }
221       isolate->OptionalRescheduleException(true);
222     }
223
224     DCHECK(!isolate->has_pending_exception());
225   }
226
227   // Re-request terminate execution interrupt to trigger later.
228   if (is_termination) isolate->stack_guard()->RequestTerminateExecution();
229
230   return maybe_result;
231 }
232
233
234 Handle<Object> Execution::GetFunctionDelegate(Isolate* isolate,
235                                               Handle<Object> object) {
236   DCHECK(!object->IsJSFunction());
237   Factory* factory = isolate->factory();
238
239   // If you return a function from here, it will be called when an
240   // attempt is made to call the given object as a function.
241
242   // If object is a function proxy, get its handler. Iterate if necessary.
243   Object* fun = *object;
244   while (fun->IsJSFunctionProxy()) {
245     fun = JSFunctionProxy::cast(fun)->call_trap();
246   }
247   if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
248
249   // Objects created through the API can have an instance-call handler
250   // that should be used when calling the object as a function.
251   if (fun->IsHeapObject() &&
252       HeapObject::cast(fun)->map()->has_instance_call_handler()) {
253     return Handle<JSFunction>(
254         isolate->native_context()->call_as_function_delegate());
255   }
256
257   return factory->undefined_value();
258 }
259
260
261 MaybeHandle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate,
262                                                       Handle<Object> object) {
263   DCHECK(!object->IsJSFunction());
264
265   // If object is a function proxy, get its handler. Iterate if necessary.
266   Object* fun = *object;
267   while (fun->IsJSFunctionProxy()) {
268     fun = JSFunctionProxy::cast(fun)->call_trap();
269   }
270   if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
271
272   // Objects created through the API can have an instance-call handler
273   // that should be used when calling the object as a function.
274   if (fun->IsHeapObject() &&
275       HeapObject::cast(fun)->map()->has_instance_call_handler()) {
276     return Handle<JSFunction>(
277         isolate->native_context()->call_as_function_delegate());
278   }
279
280   // If the Object doesn't have an instance-call handler we should
281   // throw a non-callable exception.
282   THROW_NEW_ERROR(isolate,
283                   NewTypeError(MessageTemplate::kCalledNonCallable, object),
284                   Object);
285 }
286
287
288 Handle<Object> Execution::GetConstructorDelegate(Isolate* isolate,
289                                                  Handle<Object> object) {
290   DCHECK(!object->IsJSFunction());
291
292   // If you return a function from here, it will be called when an
293   // attempt is made to call the given object as a constructor.
294
295   // If object is a function proxies, get its handler. Iterate if necessary.
296   Object* fun = *object;
297   while (fun->IsJSFunctionProxy()) {
298     fun = JSFunctionProxy::cast(fun)->call_trap();
299   }
300   if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
301
302   // Objects created through the API can have an instance-call handler
303   // that should be used when calling the object as a function.
304   if (fun->IsHeapObject() &&
305       HeapObject::cast(fun)->map()->has_instance_call_handler()) {
306     return Handle<JSFunction>(
307         isolate->native_context()->call_as_constructor_delegate());
308   }
309
310   return isolate->factory()->undefined_value();
311 }
312
313
314 MaybeHandle<Object> Execution::TryGetConstructorDelegate(
315     Isolate* isolate, Handle<Object> object) {
316   DCHECK(!object->IsJSFunction());
317
318   // If you return a function from here, it will be called when an
319   // attempt is made to call the given object as a constructor.
320
321   // If object is a function proxies, get its handler. Iterate if necessary.
322   Object* fun = *object;
323   while (fun->IsJSFunctionProxy()) {
324     fun = JSFunctionProxy::cast(fun)->call_trap();
325   }
326   if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
327
328   // Objects created through the API can have an instance-call handler
329   // that should be used when calling the object as a function.
330   if (fun->IsHeapObject() &&
331       HeapObject::cast(fun)->map()->has_instance_call_handler()) {
332     return Handle<JSFunction>(
333         isolate->native_context()->call_as_constructor_delegate());
334   }
335
336   // If the Object doesn't have an instance-call handler we should
337   // throw a non-callable exception.
338   THROW_NEW_ERROR(isolate,
339                   NewTypeError(MessageTemplate::kCalledNonCallable, object),
340                   Object);
341 }
342
343
344 void StackGuard::SetStackLimit(uintptr_t limit) {
345   ExecutionAccess access(isolate_);
346   // If the current limits are special (e.g. due to a pending interrupt) then
347   // leave them alone.
348   uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
349   if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
350     thread_local_.set_jslimit(jslimit);
351   }
352   if (thread_local_.climit() == thread_local_.real_climit_) {
353     thread_local_.set_climit(limit);
354   }
355   thread_local_.real_climit_ = limit;
356   thread_local_.real_jslimit_ = jslimit;
357 }
358
359
360 void StackGuard::AdjustStackLimitForSimulator() {
361   ExecutionAccess access(isolate_);
362   uintptr_t climit = thread_local_.real_climit_;
363   // If the current limits are special (e.g. due to a pending interrupt) then
364   // leave them alone.
365   uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, climit);
366   if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
367     thread_local_.set_jslimit(jslimit);
368     isolate_->heap()->SetStackLimits();
369   }
370 }
371
372
373 void StackGuard::EnableInterrupts() {
374   ExecutionAccess access(isolate_);
375   if (has_pending_interrupts(access)) {
376     set_interrupt_limits(access);
377   }
378 }
379
380
381 void StackGuard::DisableInterrupts() {
382   ExecutionAccess access(isolate_);
383   reset_limits(access);
384 }
385
386
387 void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) {
388   ExecutionAccess access(isolate_);
389   // Intercept already requested interrupts.
390   int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
391   scope->intercepted_flags_ = intercepted;
392   thread_local_.interrupt_flags_ &= ~intercepted;
393   if (!has_pending_interrupts(access)) reset_limits(access);
394   // Add scope to the chain.
395   scope->prev_ = thread_local_.postpone_interrupts_;
396   thread_local_.postpone_interrupts_ = scope;
397 }
398
399
400 void StackGuard::PopPostponeInterruptsScope() {
401   ExecutionAccess access(isolate_);
402   PostponeInterruptsScope* top = thread_local_.postpone_interrupts_;
403   // Make intercepted interrupts active.
404   DCHECK((thread_local_.interrupt_flags_ & top->intercept_mask_) == 0);
405   thread_local_.interrupt_flags_ |= top->intercepted_flags_;
406   if (has_pending_interrupts(access)) set_interrupt_limits(access);
407   // Remove scope from chain.
408   thread_local_.postpone_interrupts_ = top->prev_;
409 }
410
411
412 bool StackGuard::CheckInterrupt(InterruptFlag flag) {
413   ExecutionAccess access(isolate_);
414   return thread_local_.interrupt_flags_ & flag;
415 }
416
417
418 void StackGuard::RequestInterrupt(InterruptFlag flag) {
419   ExecutionAccess access(isolate_);
420   // Check the chain of PostponeInterruptsScopes for interception.
421   if (thread_local_.postpone_interrupts_ &&
422       thread_local_.postpone_interrupts_->Intercept(flag)) {
423     return;
424   }
425
426   // Not intercepted.  Set as active interrupt flag.
427   thread_local_.interrupt_flags_ |= flag;
428   set_interrupt_limits(access);
429
430   // If this isolate is waiting in a futex, notify it to wake up.
431   isolate_->futex_wait_list_node()->NotifyWake();
432 }
433
434
435 void StackGuard::ClearInterrupt(InterruptFlag flag) {
436   ExecutionAccess access(isolate_);
437   // Clear the interrupt flag from the chain of PostponeInterruptsScopes.
438   for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_;
439        current != NULL;
440        current = current->prev_) {
441     current->intercepted_flags_ &= ~flag;
442   }
443
444   // Clear the interrupt flag from the active interrupt flags.
445   thread_local_.interrupt_flags_ &= ~flag;
446   if (!has_pending_interrupts(access)) reset_limits(access);
447 }
448
449
450 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
451   ExecutionAccess access(isolate_);
452   bool result = (thread_local_.interrupt_flags_ & flag);
453   thread_local_.interrupt_flags_ &= ~flag;
454   if (!has_pending_interrupts(access)) reset_limits(access);
455   return result;
456 }
457
458
459 char* StackGuard::ArchiveStackGuard(char* to) {
460   ExecutionAccess access(isolate_);
461   MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
462   ThreadLocal blank;
463
464   // Set the stack limits using the old thread_local_.
465   // TODO(isolates): This was the old semantics of constructing a ThreadLocal
466   //                 (as the ctor called SetStackLimits, which looked at the
467   //                 current thread_local_ from StackGuard)-- but is this
468   //                 really what was intended?
469   isolate_->heap()->SetStackLimits();
470   thread_local_ = blank;
471
472   return to + sizeof(ThreadLocal);
473 }
474
475
476 char* StackGuard::RestoreStackGuard(char* from) {
477   ExecutionAccess access(isolate_);
478   MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
479   isolate_->heap()->SetStackLimits();
480   return from + sizeof(ThreadLocal);
481 }
482
483
484 void StackGuard::FreeThreadResources() {
485   Isolate::PerIsolateThreadData* per_thread =
486       isolate_->FindOrAllocatePerThreadDataForThisThread();
487   per_thread->set_stack_limit(thread_local_.real_climit_);
488 }
489
490
491 void StackGuard::ThreadLocal::Clear() {
492   real_jslimit_ = kIllegalLimit;
493   set_jslimit(kIllegalLimit);
494   real_climit_ = kIllegalLimit;
495   set_climit(kIllegalLimit);
496   postpone_interrupts_ = NULL;
497   interrupt_flags_ = 0;
498 }
499
500
501 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
502   bool should_set_stack_limits = false;
503   if (real_climit_ == kIllegalLimit) {
504     const uintptr_t kLimitSize = FLAG_stack_size * KB;
505     DCHECK(GetCurrentStackPosition() > kLimitSize);
506     uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
507     real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
508     set_jslimit(SimulatorStack::JsLimitFromCLimit(isolate, limit));
509     real_climit_ = limit;
510     set_climit(limit);
511     should_set_stack_limits = true;
512   }
513   postpone_interrupts_ = NULL;
514   interrupt_flags_ = 0;
515   return should_set_stack_limits;
516 }
517
518
519 void StackGuard::ClearThread(const ExecutionAccess& lock) {
520   thread_local_.Clear();
521   isolate_->heap()->SetStackLimits();
522 }
523
524
525 void StackGuard::InitThread(const ExecutionAccess& lock) {
526   if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
527   Isolate::PerIsolateThreadData* per_thread =
528       isolate_->FindOrAllocatePerThreadDataForThisThread();
529   uintptr_t stored_limit = per_thread->stack_limit();
530   // You should hold the ExecutionAccess lock when you call this.
531   if (stored_limit != 0) {
532     SetStackLimit(stored_limit);
533   }
534 }
535
536
537 // --- C a l l s   t o   n a t i v e s ---
538
539 #define RETURN_NATIVE_CALL(name, args)                                         \
540   do {                                                                         \
541     Handle<Object> argv[] = args;                                              \
542     return Call(isolate, isolate->name##_fun(),                                \
543                 isolate->factory()->undefined_value(), arraysize(argv), argv); \
544   } while (false)
545
546
547 MaybeHandle<Object> Execution::ToNumber(
548     Isolate* isolate, Handle<Object> obj) {
549   RETURN_NATIVE_CALL(to_number, { obj });
550 }
551
552
553 MaybeHandle<Object> Execution::ToString(
554     Isolate* isolate, Handle<Object> obj) {
555   RETURN_NATIVE_CALL(to_string, { obj });
556 }
557
558
559 MaybeHandle<Object> Execution::ToDetailString(
560     Isolate* isolate, Handle<Object> obj) {
561   RETURN_NATIVE_CALL(to_detail_string, { obj });
562 }
563
564
565 MaybeHandle<Object> Execution::ToInteger(
566     Isolate* isolate, Handle<Object> obj) {
567   RETURN_NATIVE_CALL(to_integer, { obj });
568 }
569
570
571 MaybeHandle<Object> Execution::ToLength(
572     Isolate* isolate, Handle<Object> obj) {
573   RETURN_NATIVE_CALL(to_length, { obj });
574 }
575
576
577 MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
578   Handle<Object> time_obj = isolate->factory()->NewNumber(time);
579   RETURN_NATIVE_CALL(create_date, { time_obj });
580 }
581
582
583 #undef RETURN_NATIVE_CALL
584
585
586 MaybeHandle<Object> Execution::ToInt32(Isolate* isolate, Handle<Object> obj) {
587   ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, Execution::ToNumber(isolate, obj),
588                              Object);
589   return isolate->factory()->NewNumberFromInt(DoubleToInt32(obj->Number()));
590 }
591
592
593 MaybeHandle<Object> Execution::ToObject(Isolate* isolate, Handle<Object> obj) {
594   Handle<JSReceiver> receiver;
595   if (JSReceiver::ToObject(isolate, obj).ToHandle(&receiver)) {
596     return receiver;
597   }
598   THROW_NEW_ERROR(
599       isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject), Object);
600 }
601
602
603 MaybeHandle<Object> Execution::ToUint32(Isolate* isolate, Handle<Object> obj) {
604   ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, Execution::ToNumber(isolate, obj),
605                              Object);
606   return isolate->factory()->NewNumberFromUint(DoubleToUint32(obj->Number()));
607 }
608
609
610 MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
611                                              Handle<String> flags) {
612   Isolate* isolate = pattern->GetIsolate();
613   Handle<JSFunction> function = Handle<JSFunction>(
614       isolate->native_context()->regexp_function());
615   Handle<Object> re_obj;
616   ASSIGN_RETURN_ON_EXCEPTION(
617       isolate, re_obj,
618       RegExpImpl::CreateRegExpLiteral(function, pattern, flags),
619       JSRegExp);
620   return Handle<JSRegExp>::cast(re_obj);
621 }
622
623
624 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
625                                             Handle<JSFunction> fun,
626                                             Handle<Object> pos,
627                                             Handle<Object> is_global) {
628   Isolate* isolate = fun->GetIsolate();
629   Handle<Object> args[] = { recv, fun, pos, is_global };
630   MaybeHandle<Object> maybe_result =
631       TryCall(isolate->get_stack_trace_line_fun(),
632               isolate->factory()->undefined_value(), arraysize(args), args);
633   Handle<Object> result;
634   if (!maybe_result.ToHandle(&result) || !result->IsString()) {
635     return isolate->factory()->empty_string();
636   }
637
638   return Handle<String>::cast(result);
639 }
640
641
642 void StackGuard::HandleGCInterrupt() {
643   if (CheckAndClearInterrupt(GC_REQUEST)) {
644     isolate_->heap()->HandleGCRequest();
645   }
646 }
647
648
649 Object* StackGuard::HandleInterrupts() {
650   if (CheckAndClearInterrupt(GC_REQUEST)) {
651     isolate_->heap()->HandleGCRequest();
652   }
653
654   if (CheckDebugBreak() || CheckDebugCommand()) {
655     isolate_->debug()->HandleDebugBreak();
656   }
657
658   if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
659     return isolate_->TerminateExecution();
660   }
661
662   if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
663     isolate_->heap()->DeoptMarkedAllocationSites();
664   }
665
666   if (CheckAndClearInterrupt(INSTALL_CODE)) {
667     DCHECK(isolate_->concurrent_recompilation_enabled());
668     isolate_->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
669   }
670
671   if (CheckAndClearInterrupt(API_INTERRUPT)) {
672     // Callbacks must be invoked outside of ExecusionAccess lock.
673     isolate_->InvokeApiInterruptCallbacks();
674   }
675
676   isolate_->counters()->stack_interrupts()->Increment();
677   isolate_->counters()->runtime_profiler_ticks()->Increment();
678   isolate_->runtime_profiler()->OptimizeNow();
679
680   return isolate_->heap()->undefined_value();
681 }
682
683 }  // namespace internal
684 }  // namespace v8