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