deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / 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/isolate-inl.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_.jslimit_ = kInterruptLimit;
24   thread_local_.climit_ = kInterruptLimit;
25   isolate_->heap()->SetStackLimits();
26 }
27
28
29 void StackGuard::reset_limits(const ExecutionAccess& lock) {
30   DCHECK(isolate_ != NULL);
31   thread_local_.jslimit_ = thread_local_.real_jslimit_;
32   thread_local_.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;
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, NewTypeError("called_non_callable",
283                                         i::HandleVector<i::Object>(&object, 1)),
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, NewTypeError("called_non_callable",
339                                         i::HandleVector<i::Object>(&object, 1)),
340                   Object);
341 }
342
343
344 void StackGuard::EnableInterrupts() {
345   ExecutionAccess access(isolate_);
346   if (has_pending_interrupts(access)) {
347     set_interrupt_limits(access);
348   }
349 }
350
351
352 void StackGuard::SetStackLimit(uintptr_t limit) {
353   ExecutionAccess access(isolate_);
354   // If the current limits are special (e.g. due to a pending interrupt) then
355   // leave them alone.
356   uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
357   if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
358     thread_local_.jslimit_ = jslimit;
359   }
360   if (thread_local_.climit_ == thread_local_.real_climit_) {
361     thread_local_.climit_ = limit;
362   }
363   thread_local_.real_climit_ = limit;
364   thread_local_.real_jslimit_ = jslimit;
365 }
366
367
368 void StackGuard::DisableInterrupts() {
369   ExecutionAccess access(isolate_);
370   reset_limits(access);
371 }
372
373
374 void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) {
375   ExecutionAccess access(isolate_);
376   // Intercept already requested interrupts.
377   int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
378   scope->intercepted_flags_ = intercepted;
379   thread_local_.interrupt_flags_ &= ~intercepted;
380   if (!has_pending_interrupts(access)) reset_limits(access);
381   // Add scope to the chain.
382   scope->prev_ = thread_local_.postpone_interrupts_;
383   thread_local_.postpone_interrupts_ = scope;
384 }
385
386
387 void StackGuard::PopPostponeInterruptsScope() {
388   ExecutionAccess access(isolate_);
389   PostponeInterruptsScope* top = thread_local_.postpone_interrupts_;
390   // Make intercepted interrupts active.
391   DCHECK((thread_local_.interrupt_flags_ & top->intercept_mask_) == 0);
392   thread_local_.interrupt_flags_ |= top->intercepted_flags_;
393   if (has_pending_interrupts(access)) set_interrupt_limits(access);
394   // Remove scope from chain.
395   thread_local_.postpone_interrupts_ = top->prev_;
396 }
397
398
399 bool StackGuard::CheckInterrupt(InterruptFlag flag) {
400   ExecutionAccess access(isolate_);
401   return thread_local_.interrupt_flags_ & flag;
402 }
403
404
405 void StackGuard::RequestInterrupt(InterruptFlag flag) {
406   ExecutionAccess access(isolate_);
407   // Check the chain of PostponeInterruptsScopes for interception.
408   if (thread_local_.postpone_interrupts_ &&
409       thread_local_.postpone_interrupts_->Intercept(flag)) {
410     return;
411   }
412
413   // Not intercepted.  Set as active interrupt flag.
414   thread_local_.interrupt_flags_ |= flag;
415   set_interrupt_limits(access);
416 }
417
418
419 void StackGuard::ClearInterrupt(InterruptFlag flag) {
420   ExecutionAccess access(isolate_);
421   // Clear the interrupt flag from the chain of PostponeInterruptsScopes.
422   for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_;
423        current != NULL;
424        current = current->prev_) {
425     current->intercepted_flags_ &= ~flag;
426   }
427
428   // Clear the interrupt flag from the active interrupt flags.
429   thread_local_.interrupt_flags_ &= ~flag;
430   if (!has_pending_interrupts(access)) reset_limits(access);
431 }
432
433
434 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
435   ExecutionAccess access(isolate_);
436   bool result = (thread_local_.interrupt_flags_ & flag);
437   thread_local_.interrupt_flags_ &= ~flag;
438   if (!has_pending_interrupts(access)) reset_limits(access);
439   return result;
440 }
441
442
443 char* StackGuard::ArchiveStackGuard(char* to) {
444   ExecutionAccess access(isolate_);
445   MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
446   ThreadLocal blank;
447
448   // Set the stack limits using the old thread_local_.
449   // TODO(isolates): This was the old semantics of constructing a ThreadLocal
450   //                 (as the ctor called SetStackLimits, which looked at the
451   //                 current thread_local_ from StackGuard)-- but is this
452   //                 really what was intended?
453   isolate_->heap()->SetStackLimits();
454   thread_local_ = blank;
455
456   return to + sizeof(ThreadLocal);
457 }
458
459
460 char* StackGuard::RestoreStackGuard(char* from) {
461   ExecutionAccess access(isolate_);
462   MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
463   isolate_->heap()->SetStackLimits();
464   return from + sizeof(ThreadLocal);
465 }
466
467
468 void StackGuard::FreeThreadResources() {
469   Isolate::PerIsolateThreadData* per_thread =
470       isolate_->FindOrAllocatePerThreadDataForThisThread();
471   per_thread->set_stack_limit(thread_local_.real_climit_);
472 }
473
474
475 void StackGuard::ThreadLocal::Clear() {
476   real_jslimit_ = kIllegalLimit;
477   jslimit_ = kIllegalLimit;
478   real_climit_ = kIllegalLimit;
479   climit_ = kIllegalLimit;
480   postpone_interrupts_ = NULL;
481   interrupt_flags_ = 0;
482 }
483
484
485 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
486   bool should_set_stack_limits = false;
487   if (real_climit_ == kIllegalLimit) {
488     const uintptr_t kLimitSize = FLAG_stack_size * KB;
489     DCHECK(GetCurrentStackPosition() > kLimitSize);
490     uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
491     real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
492     jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
493     real_climit_ = limit;
494     climit_ = limit;
495     should_set_stack_limits = true;
496   }
497   postpone_interrupts_ = NULL;
498   interrupt_flags_ = 0;
499   return should_set_stack_limits;
500 }
501
502
503 void StackGuard::ClearThread(const ExecutionAccess& lock) {
504   thread_local_.Clear();
505   isolate_->heap()->SetStackLimits();
506 }
507
508
509 void StackGuard::InitThread(const ExecutionAccess& lock) {
510   if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
511   Isolate::PerIsolateThreadData* per_thread =
512       isolate_->FindOrAllocatePerThreadDataForThisThread();
513   uintptr_t stored_limit = per_thread->stack_limit();
514   // You should hold the ExecutionAccess lock when you call this.
515   if (stored_limit != 0) {
516     SetStackLimit(stored_limit);
517   }
518 }
519
520
521 // --- C a l l s   t o   n a t i v e s ---
522
523 #define RETURN_NATIVE_CALL(name, args)                                  \
524   do {                                                                  \
525     Handle<Object> argv[] = args;                                       \
526     return Call(isolate,                                                \
527                 isolate->name##_fun(),                                  \
528                 isolate->js_builtins_object(),                          \
529                 arraysize(argv), argv);                                \
530   } while (false)
531
532
533 MaybeHandle<Object> Execution::ToNumber(
534     Isolate* isolate, Handle<Object> obj) {
535   RETURN_NATIVE_CALL(to_number, { obj });
536 }
537
538
539 MaybeHandle<Object> Execution::ToString(
540     Isolate* isolate, Handle<Object> obj) {
541   RETURN_NATIVE_CALL(to_string, { obj });
542 }
543
544
545 MaybeHandle<Object> Execution::ToDetailString(
546     Isolate* isolate, Handle<Object> obj) {
547   RETURN_NATIVE_CALL(to_detail_string, { obj });
548 }
549
550
551 MaybeHandle<Object> Execution::ToObject(
552     Isolate* isolate, Handle<Object> obj) {
553   if (obj->IsSpecObject()) return obj;
554   RETURN_NATIVE_CALL(to_object, { obj });
555 }
556
557
558 MaybeHandle<Object> Execution::ToInteger(
559     Isolate* isolate, Handle<Object> obj) {
560   RETURN_NATIVE_CALL(to_integer, { obj });
561 }
562
563
564 MaybeHandle<Object> Execution::ToUint32(
565     Isolate* isolate, Handle<Object> obj) {
566   RETURN_NATIVE_CALL(to_uint32, { obj });
567 }
568
569
570 MaybeHandle<Object> Execution::ToInt32(
571     Isolate* isolate, Handle<Object> obj) {
572   RETURN_NATIVE_CALL(to_int32, { obj });
573 }
574
575
576 MaybeHandle<Object> Execution::ToLength(
577     Isolate* isolate, Handle<Object> obj) {
578   RETURN_NATIVE_CALL(to_length, { obj });
579 }
580
581
582 MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
583   Handle<Object> time_obj = isolate->factory()->NewNumber(time);
584   RETURN_NATIVE_CALL(create_date, { time_obj });
585 }
586
587
588 #undef RETURN_NATIVE_CALL
589
590
591 MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
592                                              Handle<String> flags) {
593   Isolate* isolate = pattern->GetIsolate();
594   Handle<JSFunction> function = Handle<JSFunction>(
595       isolate->native_context()->regexp_function());
596   Handle<Object> re_obj;
597   ASSIGN_RETURN_ON_EXCEPTION(
598       isolate, re_obj,
599       RegExpImpl::CreateRegExpLiteral(function, pattern, flags),
600       JSRegExp);
601   return Handle<JSRegExp>::cast(re_obj);
602 }
603
604
605 Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
606   Isolate* isolate = string->GetIsolate();
607   Factory* factory = isolate->factory();
608
609   int int_index = static_cast<int>(index);
610   if (int_index < 0 || int_index >= string->length()) {
611     return factory->undefined_value();
612   }
613
614   Handle<Object> char_at = Object::GetProperty(
615       isolate->js_builtins_object(),
616       factory->char_at_string()).ToHandleChecked();
617   if (!char_at->IsJSFunction()) {
618     return factory->undefined_value();
619   }
620
621   Handle<Object> index_object = factory->NewNumberFromInt(int_index);
622   Handle<Object> index_arg[] = { index_object };
623   Handle<Object> result;
624   if (!TryCall(Handle<JSFunction>::cast(char_at),
625                string,
626                arraysize(index_arg),
627                index_arg).ToHandle(&result)) {
628     return factory->undefined_value();
629   }
630   return result;
631 }
632
633
634 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
635                                             Handle<JSFunction> fun,
636                                             Handle<Object> pos,
637                                             Handle<Object> is_global) {
638   Isolate* isolate = fun->GetIsolate();
639   Handle<Object> args[] = { recv, fun, pos, is_global };
640   MaybeHandle<Object> maybe_result =
641       TryCall(isolate->get_stack_trace_line_fun(),
642               isolate->js_builtins_object(),
643               arraysize(args),
644               args);
645   Handle<Object> result;
646   if (!maybe_result.ToHandle(&result) || !result->IsString()) {
647     return isolate->factory()->empty_string();
648   }
649
650   return Handle<String>::cast(result);
651 }
652
653
654 void StackGuard::CheckAndHandleGCInterrupt() {
655   if (CheckAndClearInterrupt(GC_REQUEST)) {
656     isolate_->heap()->HandleGCRequest();
657   }
658 }
659
660
661 Object* StackGuard::HandleInterrupts() {
662   if (CheckAndClearInterrupt(GC_REQUEST)) {
663     isolate_->heap()->HandleGCRequest();
664   }
665
666   if (CheckDebugBreak() || CheckDebugCommand()) {
667     isolate_->debug()->HandleDebugBreak();
668   }
669
670   if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
671     return isolate_->TerminateExecution();
672   }
673
674   if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
675     isolate_->heap()->DeoptMarkedAllocationSites();
676   }
677
678   if (CheckAndClearInterrupt(INSTALL_CODE)) {
679     DCHECK(isolate_->concurrent_recompilation_enabled());
680     isolate_->optimizing_compiler_thread()->InstallOptimizedFunctions();
681   }
682
683   if (CheckAndClearInterrupt(API_INTERRUPT)) {
684     // Callbacks must be invoked outside of ExecusionAccess lock.
685     isolate_->InvokeApiInterruptCallbacks();
686   }
687
688   isolate_->counters()->stack_interrupts()->Increment();
689   isolate_->counters()->runtime_profiler_ticks()->Increment();
690   isolate_->runtime_profiler()->OptimizeNow();
691
692   return isolate_->heap()->undefined_value();
693 }
694
695 } }  // namespace v8::internal