9dfef372bc3db56213264f5d1f64be3fa4e76903
[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 (exception_out != NULL) {
214         if (isolate->pending_exception() ==
215             isolate->heap()->termination_exception()) {
216           is_termination = true;
217         } else {
218           *exception_out = v8::Utils::OpenHandle(*catcher.Exception());
219         }
220       }
221       isolate->OptionalRescheduleException(true);
222     }
223
224     DCHECK(!isolate->has_pending_exception());
225     DCHECK(!isolate->external_caught_exception());
226   }
227   if (is_termination) isolate->TerminateExecution();
228   return maybe_result;
229 }
230
231
232 Handle<Object> Execution::GetFunctionDelegate(Isolate* isolate,
233                                               Handle<Object> object) {
234   DCHECK(!object->IsJSFunction());
235   Factory* factory = isolate->factory();
236
237   // If you return a function from here, it will be called when an
238   // attempt is made to call the given object as a function.
239
240   // If object is a function proxy, get its handler. Iterate if necessary.
241   Object* fun = *object;
242   while (fun->IsJSFunctionProxy()) {
243     fun = JSFunctionProxy::cast(fun)->call_trap();
244   }
245   if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
246
247   // Objects created through the API can have an instance-call handler
248   // that should be used when calling the object as a function.
249   if (fun->IsHeapObject() &&
250       HeapObject::cast(fun)->map()->has_instance_call_handler()) {
251     return Handle<JSFunction>(
252         isolate->native_context()->call_as_function_delegate());
253   }
254
255   return factory->undefined_value();
256 }
257
258
259 MaybeHandle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate,
260                                                       Handle<Object> object) {
261   DCHECK(!object->IsJSFunction());
262
263   // If object is a function proxy, get its handler. Iterate if necessary.
264   Object* fun = *object;
265   while (fun->IsJSFunctionProxy()) {
266     fun = JSFunctionProxy::cast(fun)->call_trap();
267   }
268   if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
269
270   // Objects created through the API can have an instance-call handler
271   // that should be used when calling the object as a function.
272   if (fun->IsHeapObject() &&
273       HeapObject::cast(fun)->map()->has_instance_call_handler()) {
274     return Handle<JSFunction>(
275         isolate->native_context()->call_as_function_delegate());
276   }
277
278   // If the Object doesn't have an instance-call handler we should
279   // throw a non-callable exception.
280   THROW_NEW_ERROR(isolate, NewTypeError("called_non_callable",
281                                         i::HandleVector<i::Object>(&object, 1)),
282                   Object);
283 }
284
285
286 Handle<Object> Execution::GetConstructorDelegate(Isolate* isolate,
287                                                  Handle<Object> object) {
288   DCHECK(!object->IsJSFunction());
289
290   // If you return a function from here, it will be called when an
291   // attempt is made to call the given object as a constructor.
292
293   // If object is a function proxies, get its handler. Iterate if necessary.
294   Object* fun = *object;
295   while (fun->IsJSFunctionProxy()) {
296     fun = JSFunctionProxy::cast(fun)->call_trap();
297   }
298   if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
299
300   // Objects created through the API can have an instance-call handler
301   // that should be used when calling the object as a function.
302   if (fun->IsHeapObject() &&
303       HeapObject::cast(fun)->map()->has_instance_call_handler()) {
304     return Handle<JSFunction>(
305         isolate->native_context()->call_as_constructor_delegate());
306   }
307
308   return isolate->factory()->undefined_value();
309 }
310
311
312 MaybeHandle<Object> Execution::TryGetConstructorDelegate(
313     Isolate* isolate, Handle<Object> object) {
314   DCHECK(!object->IsJSFunction());
315
316   // If you return a function from here, it will be called when an
317   // attempt is made to call the given object as a constructor.
318
319   // If object is a function proxies, get its handler. Iterate if necessary.
320   Object* fun = *object;
321   while (fun->IsJSFunctionProxy()) {
322     fun = JSFunctionProxy::cast(fun)->call_trap();
323   }
324   if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
325
326   // Objects created through the API can have an instance-call handler
327   // that should be used when calling the object as a function.
328   if (fun->IsHeapObject() &&
329       HeapObject::cast(fun)->map()->has_instance_call_handler()) {
330     return Handle<JSFunction>(
331         isolate->native_context()->call_as_constructor_delegate());
332   }
333
334   // If the Object doesn't have an instance-call handler we should
335   // throw a non-callable exception.
336   THROW_NEW_ERROR(isolate, NewTypeError("called_non_callable",
337                                         i::HandleVector<i::Object>(&object, 1)),
338                   Object);
339 }
340
341
342 void StackGuard::EnableInterrupts() {
343   ExecutionAccess access(isolate_);
344   if (has_pending_interrupts(access)) {
345     set_interrupt_limits(access);
346   }
347 }
348
349
350 void StackGuard::SetStackLimit(uintptr_t limit) {
351   ExecutionAccess access(isolate_);
352   // If the current limits are special (e.g. due to a pending interrupt) then
353   // leave them alone.
354   uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
355   if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
356     thread_local_.jslimit_ = jslimit;
357   }
358   if (thread_local_.climit_ == thread_local_.real_climit_) {
359     thread_local_.climit_ = limit;
360   }
361   thread_local_.real_climit_ = limit;
362   thread_local_.real_jslimit_ = jslimit;
363 }
364
365
366 void StackGuard::DisableInterrupts() {
367   ExecutionAccess access(isolate_);
368   reset_limits(access);
369 }
370
371
372 void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) {
373   ExecutionAccess access(isolate_);
374   // Intercept already requested interrupts.
375   int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
376   scope->intercepted_flags_ = intercepted;
377   thread_local_.interrupt_flags_ &= ~intercepted;
378   if (!has_pending_interrupts(access)) reset_limits(access);
379   // Add scope to the chain.
380   scope->prev_ = thread_local_.postpone_interrupts_;
381   thread_local_.postpone_interrupts_ = scope;
382 }
383
384
385 void StackGuard::PopPostponeInterruptsScope() {
386   ExecutionAccess access(isolate_);
387   PostponeInterruptsScope* top = thread_local_.postpone_interrupts_;
388   // Make intercepted interrupts active.
389   DCHECK((thread_local_.interrupt_flags_ & top->intercept_mask_) == 0);
390   thread_local_.interrupt_flags_ |= top->intercepted_flags_;
391   if (has_pending_interrupts(access)) set_interrupt_limits(access);
392   // Remove scope from chain.
393   thread_local_.postpone_interrupts_ = top->prev_;
394 }
395
396
397 bool StackGuard::CheckInterrupt(InterruptFlag flag) {
398   ExecutionAccess access(isolate_);
399   return thread_local_.interrupt_flags_ & flag;
400 }
401
402
403 void StackGuard::RequestInterrupt(InterruptFlag flag) {
404   ExecutionAccess access(isolate_);
405   // Check the chain of PostponeInterruptsScopes for interception.
406   if (thread_local_.postpone_interrupts_ &&
407       thread_local_.postpone_interrupts_->Intercept(flag)) {
408     return;
409   }
410
411   // Not intercepted.  Set as active interrupt flag.
412   thread_local_.interrupt_flags_ |= flag;
413   set_interrupt_limits(access);
414 }
415
416
417 void StackGuard::ClearInterrupt(InterruptFlag flag) {
418   ExecutionAccess access(isolate_);
419   // Clear the interrupt flag from the chain of PostponeInterruptsScopes.
420   for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_;
421        current != NULL;
422        current = current->prev_) {
423     current->intercepted_flags_ &= ~flag;
424   }
425
426   // Clear the interrupt flag from the active interrupt flags.
427   thread_local_.interrupt_flags_ &= ~flag;
428   if (!has_pending_interrupts(access)) reset_limits(access);
429 }
430
431
432 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
433   ExecutionAccess access(isolate_);
434   bool result = (thread_local_.interrupt_flags_ & flag);
435   thread_local_.interrupt_flags_ &= ~flag;
436   if (!has_pending_interrupts(access)) reset_limits(access);
437   return result;
438 }
439
440
441 char* StackGuard::ArchiveStackGuard(char* to) {
442   ExecutionAccess access(isolate_);
443   MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
444   ThreadLocal blank;
445
446   // Set the stack limits using the old thread_local_.
447   // TODO(isolates): This was the old semantics of constructing a ThreadLocal
448   //                 (as the ctor called SetStackLimits, which looked at the
449   //                 current thread_local_ from StackGuard)-- but is this
450   //                 really what was intended?
451   isolate_->heap()->SetStackLimits();
452   thread_local_ = blank;
453
454   return to + sizeof(ThreadLocal);
455 }
456
457
458 char* StackGuard::RestoreStackGuard(char* from) {
459   ExecutionAccess access(isolate_);
460   MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
461   isolate_->heap()->SetStackLimits();
462   return from + sizeof(ThreadLocal);
463 }
464
465
466 void StackGuard::FreeThreadResources() {
467   Isolate::PerIsolateThreadData* per_thread =
468       isolate_->FindOrAllocatePerThreadDataForThisThread();
469   per_thread->set_stack_limit(thread_local_.real_climit_);
470 }
471
472
473 void StackGuard::ThreadLocal::Clear() {
474   real_jslimit_ = kIllegalLimit;
475   jslimit_ = kIllegalLimit;
476   real_climit_ = kIllegalLimit;
477   climit_ = kIllegalLimit;
478   postpone_interrupts_ = NULL;
479   interrupt_flags_ = 0;
480 }
481
482
483 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
484   bool should_set_stack_limits = false;
485   if (real_climit_ == kIllegalLimit) {
486     const uintptr_t kLimitSize = FLAG_stack_size * KB;
487     DCHECK(GetCurrentStackPosition() > kLimitSize);
488     uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
489     real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
490     jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
491     real_climit_ = limit;
492     climit_ = limit;
493     should_set_stack_limits = true;
494   }
495   postpone_interrupts_ = NULL;
496   interrupt_flags_ = 0;
497   return should_set_stack_limits;
498 }
499
500
501 void StackGuard::ClearThread(const ExecutionAccess& lock) {
502   thread_local_.Clear();
503   isolate_->heap()->SetStackLimits();
504 }
505
506
507 void StackGuard::InitThread(const ExecutionAccess& lock) {
508   if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
509   Isolate::PerIsolateThreadData* per_thread =
510       isolate_->FindOrAllocatePerThreadDataForThisThread();
511   uintptr_t stored_limit = per_thread->stack_limit();
512   // You should hold the ExecutionAccess lock when you call this.
513   if (stored_limit != 0) {
514     SetStackLimit(stored_limit);
515   }
516 }
517
518
519 // --- C a l l s   t o   n a t i v e s ---
520
521 #define RETURN_NATIVE_CALL(name, args)                                  \
522   do {                                                                  \
523     Handle<Object> argv[] = args;                                       \
524     return Call(isolate,                                                \
525                 isolate->name##_fun(),                                  \
526                 isolate->js_builtins_object(),                          \
527                 arraysize(argv), argv);                                \
528   } while (false)
529
530
531 MaybeHandle<Object> Execution::ToNumber(
532     Isolate* isolate, Handle<Object> obj) {
533   RETURN_NATIVE_CALL(to_number, { obj });
534 }
535
536
537 MaybeHandle<Object> Execution::ToString(
538     Isolate* isolate, Handle<Object> obj) {
539   RETURN_NATIVE_CALL(to_string, { obj });
540 }
541
542
543 MaybeHandle<Object> Execution::ToDetailString(
544     Isolate* isolate, Handle<Object> obj) {
545   RETURN_NATIVE_CALL(to_detail_string, { obj });
546 }
547
548
549 MaybeHandle<Object> Execution::ToObject(
550     Isolate* isolate, Handle<Object> obj) {
551   if (obj->IsSpecObject()) return obj;
552   RETURN_NATIVE_CALL(to_object, { obj });
553 }
554
555
556 MaybeHandle<Object> Execution::ToInteger(
557     Isolate* isolate, Handle<Object> obj) {
558   RETURN_NATIVE_CALL(to_integer, { obj });
559 }
560
561
562 MaybeHandle<Object> Execution::ToUint32(
563     Isolate* isolate, Handle<Object> obj) {
564   RETURN_NATIVE_CALL(to_uint32, { obj });
565 }
566
567
568 MaybeHandle<Object> Execution::ToInt32(
569     Isolate* isolate, Handle<Object> obj) {
570   RETURN_NATIVE_CALL(to_int32, { obj });
571 }
572
573
574 MaybeHandle<Object> Execution::ToLength(
575     Isolate* isolate, Handle<Object> obj) {
576   RETURN_NATIVE_CALL(to_length, { obj });
577 }
578
579
580 MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
581   Handle<Object> time_obj = isolate->factory()->NewNumber(time);
582   RETURN_NATIVE_CALL(create_date, { time_obj });
583 }
584
585
586 #undef RETURN_NATIVE_CALL
587
588
589 MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
590                                              Handle<String> flags) {
591   Isolate* isolate = pattern->GetIsolate();
592   Handle<JSFunction> function = Handle<JSFunction>(
593       isolate->native_context()->regexp_function());
594   Handle<Object> re_obj;
595   ASSIGN_RETURN_ON_EXCEPTION(
596       isolate, re_obj,
597       RegExpImpl::CreateRegExpLiteral(function, pattern, flags),
598       JSRegExp);
599   return Handle<JSRegExp>::cast(re_obj);
600 }
601
602
603 Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
604   Isolate* isolate = string->GetIsolate();
605   Factory* factory = isolate->factory();
606
607   int int_index = static_cast<int>(index);
608   if (int_index < 0 || int_index >= string->length()) {
609     return factory->undefined_value();
610   }
611
612   Handle<Object> char_at = Object::GetProperty(
613       isolate->js_builtins_object(),
614       factory->char_at_string()).ToHandleChecked();
615   if (!char_at->IsJSFunction()) {
616     return factory->undefined_value();
617   }
618
619   Handle<Object> index_object = factory->NewNumberFromInt(int_index);
620   Handle<Object> index_arg[] = { index_object };
621   Handle<Object> result;
622   if (!TryCall(Handle<JSFunction>::cast(char_at),
623                string,
624                arraysize(index_arg),
625                index_arg).ToHandle(&result)) {
626     return factory->undefined_value();
627   }
628   return result;
629 }
630
631
632 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
633                                             Handle<JSFunction> fun,
634                                             Handle<Object> pos,
635                                             Handle<Object> is_global) {
636   Isolate* isolate = fun->GetIsolate();
637   Handle<Object> args[] = { recv, fun, pos, is_global };
638   MaybeHandle<Object> maybe_result =
639       TryCall(isolate->get_stack_trace_line_fun(),
640               isolate->js_builtins_object(),
641               arraysize(args),
642               args);
643   Handle<Object> result;
644   if (!maybe_result.ToHandle(&result) || !result->IsString()) {
645     return isolate->factory()->empty_string();
646   }
647
648   return Handle<String>::cast(result);
649 }
650
651
652 Object* StackGuard::HandleInterrupts() {
653   if (CheckAndClearInterrupt(GC_REQUEST)) {
654     isolate_->heap()->HandleGCRequest();
655   }
656
657   if (CheckDebugBreak() || CheckDebugCommand()) {
658     isolate_->debug()->HandleDebugBreak();
659   }
660
661   if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
662     return isolate_->TerminateExecution();
663   }
664
665   if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
666     isolate_->heap()->DeoptMarkedAllocationSites();
667   }
668
669   if (CheckAndClearInterrupt(INSTALL_CODE)) {
670     DCHECK(isolate_->concurrent_recompilation_enabled());
671     isolate_->optimizing_compiler_thread()->InstallOptimizedFunctions();
672   }
673
674   if (CheckAndClearInterrupt(API_INTERRUPT)) {
675     // Callbacks must be invoked outside of ExecusionAccess lock.
676     isolate_->InvokeApiInterruptCallbacks();
677   }
678
679   isolate_->counters()->stack_interrupts()->Increment();
680   isolate_->counters()->runtime_profiler_ticks()->Increment();
681   isolate_->runtime_profiler()->OptimizeNow();
682
683   return isolate_->heap()->undefined_value();
684 }
685
686 } }  // namespace v8::internal