1 // Copyright 2012 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/isolate.h"
6 
7 #include <stdlib.h>
8 
9 #include <fstream>  // NOLINT(readability/streams)
10 #include <sstream>
11 
12 #include "src/ast/context-slot-cache.h"
13 #include "src/base/hashmap.h"
14 #include "src/base/platform/platform.h"
15 #include "src/base/sys-info.h"
16 #include "src/base/utils/random-number-generator.h"
17 #include "src/basic-block-profiler.h"
18 #include "src/bootstrapper.h"
19 #include "src/cancelable-task.h"
20 #include "src/codegen.h"
21 #include "src/compilation-cache.h"
22 #include "src/compilation-statistics.h"
23 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
24 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
25 #include "src/crankshaft/hydrogen.h"
26 #include "src/debug/debug.h"
27 #include "src/deoptimizer.h"
28 #include "src/elements.h"
29 #include "src/external-reference-table.h"
30 #include "src/frames-inl.h"
31 #include "src/ic/access-compiler-data.h"
32 #include "src/ic/stub-cache.h"
33 #include "src/interface-descriptors.h"
34 #include "src/interpreter/interpreter.h"
35 #include "src/isolate-inl.h"
36 #include "src/libsampler/sampler.h"
37 #include "src/log.h"
38 #include "src/messages.h"
39 #include "src/profiler/cpu-profiler.h"
40 #include "src/prototype.h"
41 #include "src/regexp/regexp-stack.h"
42 #include "src/runtime-profiler.h"
43 #include "src/simulator.h"
44 #include "src/snapshot/deserializer.h"
45 #include "src/tracing/tracing-category-observer.h"
46 #include "src/v8.h"
47 #include "src/version.h"
48 #include "src/vm-state-inl.h"
49 #include "src/wasm/wasm-module.h"
50 #include "src/zone/accounting-allocator.h"
51 
52 namespace v8 {
53 namespace internal {
54 
55 base::Atomic32 ThreadId::highest_thread_id_ = 0;
56 
AllocateThreadId()57 int ThreadId::AllocateThreadId() {
58   int new_id = base::NoBarrier_AtomicIncrement(&highest_thread_id_, 1);
59   return new_id;
60 }
61 
62 
GetCurrentThreadId()63 int ThreadId::GetCurrentThreadId() {
64   int thread_id = base::Thread::GetThreadLocalInt(Isolate::thread_id_key_);
65   if (thread_id == 0) {
66     thread_id = AllocateThreadId();
67     base::Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id);
68   }
69   return thread_id;
70 }
71 
72 
ThreadLocalTop()73 ThreadLocalTop::ThreadLocalTop() {
74   InitializeInternal();
75 }
76 
77 
InitializeInternal()78 void ThreadLocalTop::InitializeInternal() {
79   c_entry_fp_ = 0;
80   c_function_ = 0;
81   handler_ = 0;
82 #ifdef USE_SIMULATOR
83   simulator_ = NULL;
84 #endif
85   js_entry_sp_ = NULL;
86   external_callback_scope_ = NULL;
87   current_vm_state_ = EXTERNAL;
88   try_catch_handler_ = NULL;
89   context_ = NULL;
90   thread_id_ = ThreadId::Invalid();
91   external_caught_exception_ = false;
92   failed_access_check_callback_ = NULL;
93   save_context_ = NULL;
94   promise_on_stack_ = NULL;
95 
96   // These members are re-initialized later after deserialization
97   // is complete.
98   pending_exception_ = NULL;
99   rethrowing_message_ = false;
100   pending_message_obj_ = NULL;
101   scheduled_exception_ = NULL;
102 }
103 
104 
Initialize()105 void ThreadLocalTop::Initialize() {
106   InitializeInternal();
107 #ifdef USE_SIMULATOR
108   simulator_ = Simulator::current(isolate_);
109 #endif
110   thread_id_ = ThreadId::Current();
111 }
112 
113 
Free()114 void ThreadLocalTop::Free() {
115   // Match unmatched PopPromise calls.
116   while (promise_on_stack_) isolate_->PopPromise();
117 }
118 
119 
120 base::Thread::LocalStorageKey Isolate::isolate_key_;
121 base::Thread::LocalStorageKey Isolate::thread_id_key_;
122 base::Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
123 base::LazyMutex Isolate::thread_data_table_mutex_ = LAZY_MUTEX_INITIALIZER;
124 Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
125 base::Atomic32 Isolate::isolate_counter_ = 0;
126 #if DEBUG
127 base::Atomic32 Isolate::isolate_key_created_ = 0;
128 #endif
129 
130 Isolate::PerIsolateThreadData*
FindOrAllocatePerThreadDataForThisThread()131     Isolate::FindOrAllocatePerThreadDataForThisThread() {
132   ThreadId thread_id = ThreadId::Current();
133   PerIsolateThreadData* per_thread = NULL;
134   {
135     base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
136     per_thread = thread_data_table_->Lookup(this, thread_id);
137     if (per_thread == NULL) {
138       per_thread = new PerIsolateThreadData(this, thread_id);
139       thread_data_table_->Insert(per_thread);
140     }
141     DCHECK(thread_data_table_->Lookup(this, thread_id) == per_thread);
142   }
143   return per_thread;
144 }
145 
146 
DiscardPerThreadDataForThisThread()147 void Isolate::DiscardPerThreadDataForThisThread() {
148   int thread_id_int = base::Thread::GetThreadLocalInt(Isolate::thread_id_key_);
149   if (thread_id_int) {
150     ThreadId thread_id = ThreadId(thread_id_int);
151     DCHECK(!thread_manager_->mutex_owner_.Equals(thread_id));
152     base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
153     PerIsolateThreadData* per_thread =
154         thread_data_table_->Lookup(this, thread_id);
155     if (per_thread) {
156       DCHECK(!per_thread->thread_state_);
157       thread_data_table_->Remove(per_thread);
158     }
159   }
160 }
161 
162 
FindPerThreadDataForThisThread()163 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() {
164   ThreadId thread_id = ThreadId::Current();
165   return FindPerThreadDataForThread(thread_id);
166 }
167 
168 
FindPerThreadDataForThread(ThreadId thread_id)169 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThread(
170     ThreadId thread_id) {
171   PerIsolateThreadData* per_thread = NULL;
172   {
173     base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
174     per_thread = thread_data_table_->Lookup(this, thread_id);
175   }
176   return per_thread;
177 }
178 
179 
InitializeOncePerProcess()180 void Isolate::InitializeOncePerProcess() {
181   base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
182   CHECK(thread_data_table_ == NULL);
183   isolate_key_ = base::Thread::CreateThreadLocalKey();
184 #if DEBUG
185   base::NoBarrier_Store(&isolate_key_created_, 1);
186 #endif
187   thread_id_key_ = base::Thread::CreateThreadLocalKey();
188   per_isolate_thread_data_key_ = base::Thread::CreateThreadLocalKey();
189   thread_data_table_ = new Isolate::ThreadDataTable();
190 }
191 
192 
get_address_from_id(Isolate::AddressId id)193 Address Isolate::get_address_from_id(Isolate::AddressId id) {
194   return isolate_addresses_[id];
195 }
196 
197 
Iterate(ObjectVisitor * v,char * thread_storage)198 char* Isolate::Iterate(ObjectVisitor* v, char* thread_storage) {
199   ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage);
200   Iterate(v, thread);
201   return thread_storage + sizeof(ThreadLocalTop);
202 }
203 
204 
IterateThread(ThreadVisitor * v,char * t)205 void Isolate::IterateThread(ThreadVisitor* v, char* t) {
206   ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
207   v->VisitThread(this, thread);
208 }
209 
210 
Iterate(ObjectVisitor * v,ThreadLocalTop * thread)211 void Isolate::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
212   // Visit the roots from the top for a given thread.
213   v->VisitPointer(&thread->pending_exception_);
214   v->VisitPointer(&(thread->pending_message_obj_));
215   v->VisitPointer(bit_cast<Object**>(&(thread->context_)));
216   v->VisitPointer(&thread->scheduled_exception_);
217 
218   for (v8::TryCatch* block = thread->try_catch_handler();
219        block != NULL;
220        block = block->next_) {
221     v->VisitPointer(bit_cast<Object**>(&(block->exception_)));
222     v->VisitPointer(bit_cast<Object**>(&(block->message_obj_)));
223   }
224 
225   // Iterate over pointers on native execution stack.
226   for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) {
227     it.frame()->Iterate(v);
228   }
229 }
230 
231 
Iterate(ObjectVisitor * v)232 void Isolate::Iterate(ObjectVisitor* v) {
233   ThreadLocalTop* current_t = thread_local_top();
234   Iterate(v, current_t);
235 }
236 
237 
IterateDeferredHandles(ObjectVisitor * visitor)238 void Isolate::IterateDeferredHandles(ObjectVisitor* visitor) {
239   for (DeferredHandles* deferred = deferred_handles_head_;
240        deferred != NULL;
241        deferred = deferred->next_) {
242     deferred->Iterate(visitor);
243   }
244 }
245 
246 
247 #ifdef DEBUG
IsDeferredHandle(Object ** handle)248 bool Isolate::IsDeferredHandle(Object** handle) {
249   // Each DeferredHandles instance keeps the handles to one job in the
250   // concurrent recompilation queue, containing a list of blocks.  Each block
251   // contains kHandleBlockSize handles except for the first block, which may
252   // not be fully filled.
253   // We iterate through all the blocks to see whether the argument handle
254   // belongs to one of the blocks.  If so, it is deferred.
255   for (DeferredHandles* deferred = deferred_handles_head_;
256        deferred != NULL;
257        deferred = deferred->next_) {
258     List<Object**>* blocks = &deferred->blocks_;
259     for (int i = 0; i < blocks->length(); i++) {
260       Object** block_limit = (i == 0) ? deferred->first_block_limit_
261                                       : blocks->at(i) + kHandleBlockSize;
262       if (blocks->at(i) <= handle && handle < block_limit) return true;
263     }
264   }
265   return false;
266 }
267 #endif  // DEBUG
268 
269 
RegisterTryCatchHandler(v8::TryCatch * that)270 void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) {
271   thread_local_top()->set_try_catch_handler(that);
272 }
273 
274 
UnregisterTryCatchHandler(v8::TryCatch * that)275 void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) {
276   DCHECK(thread_local_top()->try_catch_handler() == that);
277   thread_local_top()->set_try_catch_handler(that->next_);
278 }
279 
280 
StackTraceString()281 Handle<String> Isolate::StackTraceString() {
282   if (stack_trace_nesting_level_ == 0) {
283     stack_trace_nesting_level_++;
284     HeapStringAllocator allocator;
285     StringStream::ClearMentionedObjectCache(this);
286     StringStream accumulator(&allocator);
287     incomplete_message_ = &accumulator;
288     PrintStack(&accumulator);
289     Handle<String> stack_trace = accumulator.ToString(this);
290     incomplete_message_ = NULL;
291     stack_trace_nesting_level_ = 0;
292     return stack_trace;
293   } else if (stack_trace_nesting_level_ == 1) {
294     stack_trace_nesting_level_++;
295     base::OS::PrintError(
296       "\n\nAttempt to print stack while printing stack (double fault)\n");
297     base::OS::PrintError(
298       "If you are lucky you may find a partial stack dump on stdout.\n\n");
299     incomplete_message_->OutputToStdOut();
300     return factory()->empty_string();
301   } else {
302     base::OS::Abort();
303     // Unreachable
304     return factory()->empty_string();
305   }
306 }
307 
308 
PushStackTraceAndDie(unsigned int magic,void * ptr1,void * ptr2,unsigned int magic2)309 void Isolate::PushStackTraceAndDie(unsigned int magic, void* ptr1, void* ptr2,
310                                    unsigned int magic2) {
311   const int kMaxStackTraceSize = 32 * KB;
312   Handle<String> trace = StackTraceString();
313   uint8_t buffer[kMaxStackTraceSize];
314   int length = Min(kMaxStackTraceSize - 1, trace->length());
315   String::WriteToFlat(*trace, buffer, 0, length);
316   buffer[length] = '\0';
317   // TODO(dcarney): convert buffer to utf8?
318   base::OS::PrintError("Stacktrace (%x-%x) %p %p: %s\n", magic, magic2, ptr1,
319                        ptr2, reinterpret_cast<char*>(buffer));
320   base::OS::Abort();
321 }
322 
323 namespace {
324 
325 class StackTraceHelper {
326  public:
StackTraceHelper(Isolate * isolate,FrameSkipMode mode,Handle<Object> caller)327   StackTraceHelper(Isolate* isolate, FrameSkipMode mode, Handle<Object> caller)
328       : isolate_(isolate),
329         mode_(mode),
330         caller_(caller),
331         skip_next_frame_(true) {
332     switch (mode_) {
333       case SKIP_FIRST:
334         skip_next_frame_ = true;
335         break;
336       case SKIP_UNTIL_SEEN:
337         DCHECK(caller_->IsJSFunction());
338         skip_next_frame_ = true;
339         break;
340       case SKIP_NONE:
341         skip_next_frame_ = false;
342         break;
343     }
344     encountered_strict_function_ = false;
345   }
346 
347   // Poison stack frames below the first strict mode frame.
348   // The stack trace API should not expose receivers and function
349   // objects on frames deeper than the top-most one with a strict mode
350   // function.
IsStrictFrame(JSFunction * fun)351   bool IsStrictFrame(JSFunction* fun) {
352     if (!encountered_strict_function_) {
353       encountered_strict_function_ = is_strict(fun->shared()->language_mode());
354     }
355     return encountered_strict_function_;
356   }
357 
358   // Determines whether the given stack frame should be displayed in a stack
359   // trace.
IsVisibleInStackTrace(JSFunction * fun)360   bool IsVisibleInStackTrace(JSFunction* fun) {
361     return ShouldIncludeFrame(fun) && IsNotInNativeScript(fun) &&
362            IsInSameSecurityContext(fun);
363   }
364 
365  private:
366   // This mechanism excludes a number of uninteresting frames from the stack
367   // trace. This can be be the first frame (which will be a builtin-exit frame
368   // for the error constructor builtin) or every frame until encountering a
369   // user-specified function.
ShouldIncludeFrame(JSFunction * fun)370   bool ShouldIncludeFrame(JSFunction* fun) {
371     switch (mode_) {
372       case SKIP_NONE:
373         return true;
374       case SKIP_FIRST:
375         if (!skip_next_frame_) return true;
376         skip_next_frame_ = false;
377         return false;
378       case SKIP_UNTIL_SEEN:
379         if (skip_next_frame_ && (fun == *caller_)) {
380           skip_next_frame_ = false;
381           return false;
382         }
383         return !skip_next_frame_;
384     }
385     UNREACHABLE();
386     return false;
387   }
388 
IsNotInNativeScript(JSFunction * fun)389   bool IsNotInNativeScript(JSFunction* fun) {
390     // Functions defined in native scripts are not visible unless directly
391     // exposed, in which case the native flag is set.
392     // The --builtins-in-stack-traces command line flag allows including
393     // internal call sites in the stack trace for debugging purposes.
394     if (!FLAG_builtins_in_stack_traces && fun->shared()->IsBuiltin()) {
395       return fun->shared()->native();
396     }
397     return true;
398   }
399 
IsInSameSecurityContext(JSFunction * fun)400   bool IsInSameSecurityContext(JSFunction* fun) {
401     return isolate_->context()->HasSameSecurityTokenAs(fun->context());
402   }
403 
404   Isolate* isolate_;
405 
406   const FrameSkipMode mode_;
407   const Handle<Object> caller_;
408   bool skip_next_frame_;
409 
410   bool encountered_strict_function_;
411 };
412 
413 // TODO(jgruber): Fix all cases in which frames give us a hole value (e.g. the
414 // receiver in RegExp constructor frames.
TheHoleToUndefined(Isolate * isolate,Handle<Object> in)415 Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) {
416   return (in->IsTheHole(isolate))
417              ? Handle<Object>::cast(isolate->factory()->undefined_value())
418              : in;
419 }
420 
GetStackTraceLimit(Isolate * isolate,int * result)421 bool GetStackTraceLimit(Isolate* isolate, int* result) {
422   Handle<JSObject> error = isolate->error_function();
423 
424   Handle<String> key = isolate->factory()->stackTraceLimit_string();
425   Handle<Object> stack_trace_limit = JSReceiver::GetDataProperty(error, key);
426   if (!stack_trace_limit->IsNumber()) return false;
427 
428   // Ensure that limit is not negative.
429   *result = Max(FastD2IChecked(stack_trace_limit->Number()), 0);
430   return true;
431 }
432 
433 }  // namespace
434 
CaptureSimpleStackTrace(Handle<JSReceiver> error_object,FrameSkipMode mode,Handle<Object> caller)435 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
436                                                 FrameSkipMode mode,
437                                                 Handle<Object> caller) {
438   DisallowJavascriptExecution no_js(this);
439 
440   int limit;
441   if (!GetStackTraceLimit(this, &limit)) return factory()->undefined_value();
442 
443   const int initial_size = Min(limit, 10);
444   Handle<FrameArray> elements = factory()->NewFrameArray(initial_size);
445 
446   StackTraceHelper helper(this, mode, caller);
447 
448   for (StackFrameIterator iter(this);
449        !iter.done() && elements->FrameCount() < limit; iter.Advance()) {
450     StackFrame* frame = iter.frame();
451 
452     switch (frame->type()) {
453       case StackFrame::JAVA_SCRIPT:
454       case StackFrame::OPTIMIZED:
455       case StackFrame::INTERPRETED:
456       case StackFrame::BUILTIN: {
457         JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
458         // Set initial size to the maximum inlining level + 1 for the outermost
459         // function.
460         List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
461         js_frame->Summarize(&frames);
462         for (int i = frames.length() - 1; i >= 0; i--) {
463           Handle<JSFunction> fun = frames[i].function();
464 
465           // Filter out internal frames that we do not want to show.
466           if (!helper.IsVisibleInStackTrace(*fun)) continue;
467 
468           Handle<Object> recv = frames[i].receiver();
469           Handle<AbstractCode> abstract_code = frames[i].abstract_code();
470           const int offset = frames[i].code_offset();
471 
472           bool force_constructor = false;
473           if (frame->type() == StackFrame::BUILTIN) {
474             // Help CallSite::IsConstructor correctly detect hand-written
475             // construct stubs.
476             if (Code::cast(*abstract_code)->is_construct_stub()) {
477               force_constructor = true;
478             }
479           }
480 
481           int flags = 0;
482           if (helper.IsStrictFrame(*fun)) flags |= FrameArray::kIsStrict;
483           if (force_constructor) flags |= FrameArray::kForceConstructor;
484 
485           elements = FrameArray::AppendJSFrame(
486               elements, TheHoleToUndefined(this, recv), fun, abstract_code,
487               offset, flags);
488         }
489       } break;
490 
491       case StackFrame::BUILTIN_EXIT: {
492         BuiltinExitFrame* exit_frame = BuiltinExitFrame::cast(frame);
493         Handle<JSFunction> fun = handle(exit_frame->function(), this);
494 
495         // Filter out internal frames that we do not want to show.
496         if (!helper.IsVisibleInStackTrace(*fun)) continue;
497 
498         Handle<Object> recv(exit_frame->receiver(), this);
499         Handle<Code> code(exit_frame->LookupCode(), this);
500         const int offset =
501             static_cast<int>(exit_frame->pc() - code->instruction_start());
502 
503         int flags = 0;
504         if (helper.IsStrictFrame(*fun)) flags |= FrameArray::kIsStrict;
505         if (exit_frame->IsConstructor()) flags |= FrameArray::kForceConstructor;
506 
507         elements = FrameArray::AppendJSFrame(elements, recv, fun,
508                                              Handle<AbstractCode>::cast(code),
509                                              offset, flags);
510       } break;
511 
512       case StackFrame::WASM: {
513         WasmFrame* wasm_frame = WasmFrame::cast(frame);
514         Handle<Object> instance(wasm_frame->wasm_instance(), this);
515         const int wasm_function_index = wasm_frame->function_index();
516         Code* code = wasm_frame->unchecked_code();
517         Handle<AbstractCode> abstract_code(AbstractCode::cast(code), this);
518         const int offset =
519             static_cast<int>(wasm_frame->pc() - code->instruction_start());
520 
521         // TODO(wasm): The wasm object returned by the WasmFrame should always
522         //             be a wasm object.
523         DCHECK(wasm::IsWasmInstance(*instance) || instance->IsUndefined(this));
524 
525         int flags = wasm::WasmIsAsmJs(*instance, this)
526                         ? FrameArray::kIsAsmJsWasmFrame
527                         : FrameArray::kIsWasmFrame;
528 
529         elements =
530             FrameArray::AppendWasmFrame(elements, instance, wasm_function_index,
531                                         abstract_code, offset, flags);
532       } break;
533 
534       default:
535         break;
536     }
537   }
538 
539   elements->ShrinkToFit();
540 
541   // TODO(yangguo): Queue this structured stack trace for preprocessing on GC.
542   return factory()->NewJSArrayWithElements(elements);
543 }
544 
CaptureAndSetDetailedStackTrace(Handle<JSReceiver> error_object)545 MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace(
546     Handle<JSReceiver> error_object) {
547   if (capture_stack_trace_for_uncaught_exceptions_) {
548     // Capture stack trace for a detailed exception message.
549     Handle<Name> key = factory()->detailed_stack_trace_symbol();
550     Handle<JSArray> stack_trace = CaptureCurrentStackTrace(
551         stack_trace_for_uncaught_exceptions_frame_limit_,
552         stack_trace_for_uncaught_exceptions_options_);
553     RETURN_ON_EXCEPTION(
554         this, JSReceiver::SetProperty(error_object, key, stack_trace, STRICT),
555         JSReceiver);
556   }
557   return error_object;
558 }
559 
CaptureAndSetSimpleStackTrace(Handle<JSReceiver> error_object,FrameSkipMode mode,Handle<Object> caller)560 MaybeHandle<JSReceiver> Isolate::CaptureAndSetSimpleStackTrace(
561     Handle<JSReceiver> error_object, FrameSkipMode mode,
562     Handle<Object> caller) {
563   // Capture stack trace for simple stack trace string formatting.
564   Handle<Name> key = factory()->stack_trace_symbol();
565   Handle<Object> stack_trace =
566       CaptureSimpleStackTrace(error_object, mode, caller);
567   RETURN_ON_EXCEPTION(
568       this, JSReceiver::SetProperty(error_object, key, stack_trace, STRICT),
569       JSReceiver);
570   return error_object;
571 }
572 
573 
GetDetailedStackTrace(Handle<JSObject> error_object)574 Handle<JSArray> Isolate::GetDetailedStackTrace(Handle<JSObject> error_object) {
575   Handle<Name> key_detailed = factory()->detailed_stack_trace_symbol();
576   Handle<Object> stack_trace =
577       JSReceiver::GetDataProperty(error_object, key_detailed);
578   if (stack_trace->IsJSArray()) return Handle<JSArray>::cast(stack_trace);
579   return Handle<JSArray>();
580 }
581 
582 
583 class CaptureStackTraceHelper {
584  public:
CaptureStackTraceHelper(Isolate * isolate,StackTrace::StackTraceOptions options)585   CaptureStackTraceHelper(Isolate* isolate,
586                           StackTrace::StackTraceOptions options)
587       : isolate_(isolate) {
588     if (options & StackTrace::kColumnOffset) {
589       column_key_ =
590           factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("column"));
591     }
592     if (options & StackTrace::kLineNumber) {
593       line_key_ =
594           factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("lineNumber"));
595     }
596     if (options & StackTrace::kScriptId) {
597       script_id_key_ =
598           factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("scriptId"));
599     }
600     if (options & StackTrace::kScriptName) {
601       script_name_key_ =
602           factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("scriptName"));
603     }
604     if (options & StackTrace::kScriptNameOrSourceURL) {
605       script_name_or_source_url_key_ = factory()->InternalizeOneByteString(
606           STATIC_CHAR_VECTOR("scriptNameOrSourceURL"));
607     }
608     if (options & StackTrace::kFunctionName) {
609       function_key_ = factory()->InternalizeOneByteString(
610           STATIC_CHAR_VECTOR("functionName"));
611     }
612     if (options & StackTrace::kIsEval) {
613       eval_key_ =
614           factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("isEval"));
615     }
616     if (options & StackTrace::kIsConstructor) {
617       constructor_key_ = factory()->InternalizeOneByteString(
618           STATIC_CHAR_VECTOR("isConstructor"));
619     }
620   }
621 
NewStackFrameObject(FrameSummary & summ)622   Handle<JSObject> NewStackFrameObject(FrameSummary& summ) {
623     int position = summ.abstract_code()->SourcePosition(summ.code_offset());
624     return NewStackFrameObject(summ.function(), position,
625                                summ.is_constructor());
626   }
627 
NewStackFrameObject(Handle<JSFunction> fun,int position,bool is_constructor)628   Handle<JSObject> NewStackFrameObject(Handle<JSFunction> fun, int position,
629                                        bool is_constructor) {
630     Handle<JSObject> stack_frame =
631         factory()->NewJSObject(isolate_->object_function());
632     Handle<Script> script(Script::cast(fun->shared()->script()), isolate_);
633 
634     if (!line_key_.is_null()) {
635       Script::PositionInfo info;
636       bool valid_pos =
637           Script::GetPositionInfo(script, position, &info, Script::WITH_OFFSET);
638 
639       if (!column_key_.is_null() && valid_pos) {
640         JSObject::AddProperty(stack_frame, column_key_,
641                               handle(Smi::FromInt(info.column + 1), isolate_),
642                               NONE);
643       }
644       JSObject::AddProperty(stack_frame, line_key_,
645                             handle(Smi::FromInt(info.line + 1), isolate_),
646                             NONE);
647     }
648 
649     if (!script_id_key_.is_null()) {
650       JSObject::AddProperty(stack_frame, script_id_key_,
651                             handle(Smi::FromInt(script->id()), isolate_), NONE);
652     }
653 
654     if (!script_name_key_.is_null()) {
655       JSObject::AddProperty(stack_frame, script_name_key_,
656                             handle(script->name(), isolate_), NONE);
657     }
658 
659     if (!script_name_or_source_url_key_.is_null()) {
660       Handle<Object> result = Script::GetNameOrSourceURL(script);
661       JSObject::AddProperty(stack_frame, script_name_or_source_url_key_, result,
662                             NONE);
663     }
664 
665     if (!eval_key_.is_null()) {
666       Handle<Object> is_eval = factory()->ToBoolean(
667           script->compilation_type() == Script::COMPILATION_TYPE_EVAL);
668       JSObject::AddProperty(stack_frame, eval_key_, is_eval, NONE);
669     }
670 
671     if (!function_key_.is_null()) {
672       Handle<Object> fun_name = JSFunction::GetDebugName(fun);
673       JSObject::AddProperty(stack_frame, function_key_, fun_name, NONE);
674     }
675 
676     if (!constructor_key_.is_null()) {
677       Handle<Object> is_constructor_obj = factory()->ToBoolean(is_constructor);
678       JSObject::AddProperty(stack_frame, constructor_key_, is_constructor_obj,
679                             NONE);
680     }
681     return stack_frame;
682   }
683 
NewStackFrameObject(BuiltinExitFrame * frame)684   Handle<JSObject> NewStackFrameObject(BuiltinExitFrame* frame) {
685     Handle<JSObject> stack_frame =
686         factory()->NewJSObject(isolate_->object_function());
687     Handle<JSFunction> fun = handle(frame->function(), isolate_);
688     if (!function_key_.is_null()) {
689       Handle<Object> fun_name = JSFunction::GetDebugName(fun);
690       JSObject::AddProperty(stack_frame, function_key_, fun_name, NONE);
691     }
692 
693     // We don't have a script and hence cannot set line and col positions.
694     DCHECK(!fun->shared()->script()->IsScript());
695 
696     return stack_frame;
697   }
698 
NewStackFrameObject(WasmFrame * frame)699   Handle<JSObject> NewStackFrameObject(WasmFrame* frame) {
700     Handle<JSObject> stack_frame =
701         factory()->NewJSObject(isolate_->object_function());
702 
703     if (!function_key_.is_null()) {
704       Handle<String> name = wasm::GetWasmFunctionName(
705           isolate_, handle(frame->wasm_instance(), isolate_),
706           frame->function_index());
707       JSObject::AddProperty(stack_frame, function_key_, name, NONE);
708     }
709     // Encode the function index as line number (1-based).
710     if (!line_key_.is_null()) {
711       JSObject::AddProperty(
712           stack_frame, line_key_,
713           isolate_->factory()->NewNumberFromInt(frame->function_index() + 1),
714           NONE);
715     }
716     // Encode the byte offset as column (1-based).
717     if (!column_key_.is_null()) {
718       Code* code = frame->LookupCode();
719       int offset = static_cast<int>(frame->pc() - code->instruction_start());
720       int position = AbstractCode::cast(code)->SourcePosition(offset);
721       // Make position 1-based.
722       if (position >= 0) ++position;
723       JSObject::AddProperty(stack_frame, column_key_,
724                             isolate_->factory()->NewNumberFromInt(position),
725                             NONE);
726     }
727     if (!script_id_key_.is_null()) {
728       int script_id = frame->script()->id();
729       JSObject::AddProperty(stack_frame, script_id_key_,
730                             handle(Smi::FromInt(script_id), isolate_), NONE);
731     }
732 
733     return stack_frame;
734   }
735 
736  private:
factory()737   inline Factory* factory() { return isolate_->factory(); }
738 
739   Isolate* isolate_;
740   Handle<String> column_key_;
741   Handle<String> line_key_;
742   Handle<String> script_id_key_;
743   Handle<String> script_name_key_;
744   Handle<String> script_name_or_source_url_key_;
745   Handle<String> function_key_;
746   Handle<String> eval_key_;
747   Handle<String> constructor_key_;
748 };
749 
CaptureCurrentStackTrace(int frame_limit,StackTrace::StackTraceOptions options)750 Handle<JSArray> Isolate::CaptureCurrentStackTrace(
751     int frame_limit, StackTrace::StackTraceOptions options) {
752   DisallowJavascriptExecution no_js(this);
753   CaptureStackTraceHelper helper(this, options);
754 
755   // Ensure no negative values.
756   int limit = Max(frame_limit, 0);
757   Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit);
758   Handle<FixedArray> stack_trace_elems(
759       FixedArray::cast(stack_trace->elements()), this);
760 
761   int frames_seen = 0;
762   for (StackTraceFrameIterator it(this); !it.done() && (frames_seen < limit);
763        it.Advance()) {
764     StandardFrame* frame = it.frame();
765     if (frame->is_java_script()) {
766       // Set initial size to the maximum inlining level + 1 for the outermost
767       // function.
768       List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
769       JavaScriptFrame::cast(frame)->Summarize(&frames);
770       for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) {
771         Handle<JSFunction> fun = frames[i].function();
772         // Filter frames from other security contexts.
773         if (!(options & StackTrace::kExposeFramesAcrossSecurityOrigins) &&
774             !this->context()->HasSameSecurityTokenAs(fun->context()))
775           continue;
776         Handle<JSObject> new_frame_obj = helper.NewStackFrameObject(frames[i]);
777         stack_trace_elems->set(frames_seen, *new_frame_obj);
778         frames_seen++;
779       }
780     } else {
781       DCHECK(frame->is_wasm());
782       WasmFrame* wasm_frame = WasmFrame::cast(frame);
783       Handle<JSObject> new_frame_obj = helper.NewStackFrameObject(wasm_frame);
784       stack_trace_elems->set(frames_seen, *new_frame_obj);
785       frames_seen++;
786     }
787   }
788 
789   stack_trace->set_length(Smi::FromInt(frames_seen));
790   return stack_trace;
791 }
792 
793 
PrintStack(FILE * out,PrintStackMode mode)794 void Isolate::PrintStack(FILE* out, PrintStackMode mode) {
795   if (stack_trace_nesting_level_ == 0) {
796     stack_trace_nesting_level_++;
797     StringStream::ClearMentionedObjectCache(this);
798     HeapStringAllocator allocator;
799     StringStream accumulator(&allocator);
800     incomplete_message_ = &accumulator;
801     PrintStack(&accumulator, mode);
802     accumulator.OutputToFile(out);
803     InitializeLoggingAndCounters();
804     accumulator.Log(this);
805     incomplete_message_ = NULL;
806     stack_trace_nesting_level_ = 0;
807   } else if (stack_trace_nesting_level_ == 1) {
808     stack_trace_nesting_level_++;
809     base::OS::PrintError(
810       "\n\nAttempt to print stack while printing stack (double fault)\n");
811     base::OS::PrintError(
812       "If you are lucky you may find a partial stack dump on stdout.\n\n");
813     incomplete_message_->OutputToFile(out);
814   }
815 }
816 
817 
PrintFrames(Isolate * isolate,StringStream * accumulator,StackFrame::PrintMode mode)818 static void PrintFrames(Isolate* isolate,
819                         StringStream* accumulator,
820                         StackFrame::PrintMode mode) {
821   StackFrameIterator it(isolate);
822   for (int i = 0; !it.done(); it.Advance()) {
823     it.frame()->Print(accumulator, mode, i++);
824   }
825 }
826 
827 
PrintStack(StringStream * accumulator,PrintStackMode mode)828 void Isolate::PrintStack(StringStream* accumulator, PrintStackMode mode) {
829   // The MentionedObjectCache is not GC-proof at the moment.
830   DisallowHeapAllocation no_gc;
831   HandleScope scope(this);
832   DCHECK(accumulator->IsMentionedObjectCacheClear(this));
833 
834   // Avoid printing anything if there are no frames.
835   if (c_entry_fp(thread_local_top()) == 0) return;
836 
837   accumulator->Add(
838       "\n==== JS stack trace =========================================\n\n");
839   PrintFrames(this, accumulator, StackFrame::OVERVIEW);
840   if (mode == kPrintStackVerbose) {
841     accumulator->Add(
842         "\n==== Details ================================================\n\n");
843     PrintFrames(this, accumulator, StackFrame::DETAILS);
844     accumulator->PrintMentionedObjectCache(this);
845   }
846   accumulator->Add("=====================\n\n");
847 }
848 
849 
SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback)850 void Isolate::SetFailedAccessCheckCallback(
851     v8::FailedAccessCheckCallback callback) {
852   thread_local_top()->failed_access_check_callback_ = callback;
853 }
854 
855 
ReportFailedAccessCheck(Handle<JSObject> receiver)856 void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver) {
857   if (!thread_local_top()->failed_access_check_callback_) {
858     return ScheduleThrow(*factory()->NewTypeError(MessageTemplate::kNoAccess));
859   }
860 
861   DCHECK(receiver->IsAccessCheckNeeded());
862   DCHECK(context());
863 
864   // Get the data object from access check info.
865   HandleScope scope(this);
866   Handle<Object> data;
867   { DisallowHeapAllocation no_gc;
868     AccessCheckInfo* access_check_info = AccessCheckInfo::Get(this, receiver);
869     if (!access_check_info) {
870       AllowHeapAllocation doesnt_matter_anymore;
871       return ScheduleThrow(
872           *factory()->NewTypeError(MessageTemplate::kNoAccess));
873     }
874     data = handle(access_check_info->data(), this);
875   }
876 
877   // Leaving JavaScript.
878   VMState<EXTERNAL> state(this);
879   thread_local_top()->failed_access_check_callback_(
880       v8::Utils::ToLocal(receiver), v8::ACCESS_HAS, v8::Utils::ToLocal(data));
881 }
882 
883 
MayAccess(Handle<Context> accessing_context,Handle<JSObject> receiver)884 bool Isolate::MayAccess(Handle<Context> accessing_context,
885                         Handle<JSObject> receiver) {
886   DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded());
887 
888   // Check for compatibility between the security tokens in the
889   // current lexical context and the accessed object.
890 
891   // During bootstrapping, callback functions are not enabled yet.
892   if (bootstrapper()->IsActive()) return true;
893   {
894     DisallowHeapAllocation no_gc;
895 
896     if (receiver->IsJSGlobalProxy()) {
897       Object* receiver_context =
898           JSGlobalProxy::cast(*receiver)->native_context();
899       if (!receiver_context->IsContext()) return false;
900 
901       // Get the native context of current top context.
902       // avoid using Isolate::native_context() because it uses Handle.
903       Context* native_context =
904           accessing_context->global_object()->native_context();
905       if (receiver_context == native_context) return true;
906 
907       if (Context::cast(receiver_context)->security_token() ==
908           native_context->security_token())
909         return true;
910     }
911   }
912 
913   HandleScope scope(this);
914   Handle<Object> data;
915   v8::AccessCheckCallback callback = nullptr;
916   { DisallowHeapAllocation no_gc;
917     AccessCheckInfo* access_check_info = AccessCheckInfo::Get(this, receiver);
918     if (!access_check_info) return false;
919     Object* fun_obj = access_check_info->callback();
920     callback = v8::ToCData<v8::AccessCheckCallback>(fun_obj);
921     data = handle(access_check_info->data(), this);
922   }
923 
924   LOG(this, ApiSecurityCheck());
925 
926   {
927     // Leaving JavaScript.
928     VMState<EXTERNAL> state(this);
929     return callback(v8::Utils::ToLocal(accessing_context),
930                     v8::Utils::ToLocal(receiver), v8::Utils::ToLocal(data));
931   }
932 }
933 
934 
StackOverflow()935 Object* Isolate::StackOverflow() {
936   if (FLAG_abort_on_stack_overflow) {
937     FATAL("Aborting on stack overflow");
938   }
939 
940   DisallowJavascriptExecution no_js(this);
941   HandleScope scope(this);
942 
943   Handle<JSFunction> fun = range_error_function();
944   Handle<Object> msg = factory()->NewStringFromAsciiChecked(
945       MessageTemplate::TemplateString(MessageTemplate::kStackOverflow));
946   Handle<Object> no_caller;
947   Handle<Object> exception;
948   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
949       this, exception,
950       ErrorUtils::Construct(this, fun, fun, msg, SKIP_NONE, no_caller, true));
951 
952   Throw(*exception, nullptr);
953 
954 #ifdef VERIFY_HEAP
955   if (FLAG_verify_heap && FLAG_stress_compaction) {
956     heap()->CollectAllGarbage(Heap::kNoGCFlags,
957                               GarbageCollectionReason::kTesting);
958   }
959 #endif  // VERIFY_HEAP
960 
961   return heap()->exception();
962 }
963 
964 
TerminateExecution()965 Object* Isolate::TerminateExecution() {
966   return Throw(heap_.termination_exception(), nullptr);
967 }
968 
969 
CancelTerminateExecution()970 void Isolate::CancelTerminateExecution() {
971   if (try_catch_handler()) {
972     try_catch_handler()->has_terminated_ = false;
973   }
974   if (has_pending_exception() &&
975       pending_exception() == heap_.termination_exception()) {
976     thread_local_top()->external_caught_exception_ = false;
977     clear_pending_exception();
978   }
979   if (has_scheduled_exception() &&
980       scheduled_exception() == heap_.termination_exception()) {
981     thread_local_top()->external_caught_exception_ = false;
982     clear_scheduled_exception();
983   }
984 }
985 
986 
RequestInterrupt(InterruptCallback callback,void * data)987 void Isolate::RequestInterrupt(InterruptCallback callback, void* data) {
988   ExecutionAccess access(this);
989   api_interrupts_queue_.push(InterruptEntry(callback, data));
990   stack_guard()->RequestApiInterrupt();
991 }
992 
993 
InvokeApiInterruptCallbacks()994 void Isolate::InvokeApiInterruptCallbacks() {
995   RuntimeCallTimerScope runtimeTimer(
996       this, &RuntimeCallStats::InvokeApiInterruptCallbacks);
997   // Note: callback below should be called outside of execution access lock.
998   while (true) {
999     InterruptEntry entry;
1000     {
1001       ExecutionAccess access(this);
1002       if (api_interrupts_queue_.empty()) return;
1003       entry = api_interrupts_queue_.front();
1004       api_interrupts_queue_.pop();
1005     }
1006     VMState<EXTERNAL> state(this);
1007     HandleScope handle_scope(this);
1008     entry.first(reinterpret_cast<v8::Isolate*>(this), entry.second);
1009   }
1010 }
1011 
1012 
ReportBootstrappingException(Handle<Object> exception,MessageLocation * location)1013 void ReportBootstrappingException(Handle<Object> exception,
1014                                   MessageLocation* location) {
1015   base::OS::PrintError("Exception thrown during bootstrapping\n");
1016   if (location == NULL || location->script().is_null()) return;
1017   // We are bootstrapping and caught an error where the location is set
1018   // and we have a script for the location.
1019   // In this case we could have an extension (or an internal error
1020   // somewhere) and we print out the line number at which the error occured
1021   // to the console for easier debugging.
1022   int line_number =
1023       location->script()->GetLineNumber(location->start_pos()) + 1;
1024   if (exception->IsString() && location->script()->name()->IsString()) {
1025     base::OS::PrintError(
1026         "Extension or internal compilation error: %s in %s at line %d.\n",
1027         String::cast(*exception)->ToCString().get(),
1028         String::cast(location->script()->name())->ToCString().get(),
1029         line_number);
1030   } else if (location->script()->name()->IsString()) {
1031     base::OS::PrintError(
1032         "Extension or internal compilation error in %s at line %d.\n",
1033         String::cast(location->script()->name())->ToCString().get(),
1034         line_number);
1035   } else if (exception->IsString()) {
1036     base::OS::PrintError("Extension or internal compilation error: %s.\n",
1037                          String::cast(*exception)->ToCString().get());
1038   } else {
1039     base::OS::PrintError("Extension or internal compilation error.\n");
1040   }
1041 #ifdef OBJECT_PRINT
1042   // Since comments and empty lines have been stripped from the source of
1043   // builtins, print the actual source here so that line numbers match.
1044   if (location->script()->source()->IsString()) {
1045     Handle<String> src(String::cast(location->script()->source()));
1046     PrintF("Failing script:");
1047     int len = src->length();
1048     if (len == 0) {
1049       PrintF(" <not available>\n");
1050     } else {
1051       PrintF("\n");
1052       int line_number = 1;
1053       PrintF("%5d: ", line_number);
1054       for (int i = 0; i < len; i++) {
1055         uint16_t character = src->Get(i);
1056         PrintF("%c", character);
1057         if (character == '\n' && i < len - 2) {
1058           PrintF("%5d: ", ++line_number);
1059         }
1060       }
1061       PrintF("\n");
1062     }
1063   }
1064 #endif
1065 }
1066 
1067 
Throw(Object * exception,MessageLocation * location)1068 Object* Isolate::Throw(Object* exception, MessageLocation* location) {
1069   DCHECK(!has_pending_exception());
1070 
1071   HandleScope scope(this);
1072   Handle<Object> exception_handle(exception, this);
1073 
1074   if (FLAG_print_all_exceptions) {
1075     printf("=========================================================\n");
1076     printf("Exception thrown:\n");
1077     if (location) {
1078       Handle<Script> script = location->script();
1079       Handle<Object> name = Script::GetNameOrSourceURL(script);
1080       printf("at ");
1081       if (name->IsString() && String::cast(*name)->length() > 0)
1082         String::cast(*name)->PrintOn(stdout);
1083       else
1084         printf("<anonymous>");
1085 // Script::GetLineNumber and Script::GetColumnNumber can allocate on the heap to
1086 // initialize the line_ends array, so be careful when calling them.
1087 #ifdef DEBUG
1088       if (AllowHeapAllocation::IsAllowed()) {
1089 #else
1090       if (false) {
1091 #endif
1092         printf(", %d:%d - %d:%d\n",
1093                Script::GetLineNumber(script, location->start_pos()) + 1,
1094                Script::GetColumnNumber(script, location->start_pos()),
1095                Script::GetLineNumber(script, location->end_pos()) + 1,
1096                Script::GetColumnNumber(script, location->end_pos()));
1097       } else {
1098         printf(", line %d\n", script->GetLineNumber(location->start_pos()) + 1);
1099       }
1100     }
1101     exception->Print();
1102     printf("Stack Trace:\n");
1103     PrintStack(stdout);
1104     printf("=========================================================\n");
1105   }
1106 
1107   // Determine whether a message needs to be created for the given exception
1108   // depending on the following criteria:
1109   // 1) External v8::TryCatch missing: Always create a message because any
1110   //    JavaScript handler for a finally-block might re-throw to top-level.
1111   // 2) External v8::TryCatch exists: Only create a message if the handler
1112   //    captures messages or is verbose (which reports despite the catch).
1113   // 3) ReThrow from v8::TryCatch: The message from a previous throw still
1114   //    exists and we preserve it instead of creating a new message.
1115   bool requires_message = try_catch_handler() == nullptr ||
1116                           try_catch_handler()->is_verbose_ ||
1117                           try_catch_handler()->capture_message_;
1118   bool rethrowing_message = thread_local_top()->rethrowing_message_;
1119 
1120   thread_local_top()->rethrowing_message_ = false;
1121 
1122   // Notify debugger of exception.
1123   if (is_catchable_by_javascript(exception)) {
1124     debug()->OnThrow(exception_handle);
1125   }
1126 
1127   // Generate the message if required.
1128   if (requires_message && !rethrowing_message) {
1129     MessageLocation computed_location;
1130     // If no location was specified we try to use a computed one instead.
1131     if (location == NULL && ComputeLocation(&computed_location)) {
1132       location = &computed_location;
1133     }
1134 
1135     if (bootstrapper()->IsActive()) {
1136       // It's not safe to try to make message objects or collect stack traces
1137       // while the bootstrapper is active since the infrastructure may not have
1138       // been properly initialized.
1139       ReportBootstrappingException(exception_handle, location);
1140     } else {
1141       Handle<Object> message_obj = CreateMessage(exception_handle, location);
1142       thread_local_top()->pending_message_obj_ = *message_obj;
1143 
1144       // For any exception not caught by JavaScript, even when an external
1145       // handler is present:
1146       // If the abort-on-uncaught-exception flag is specified, and if the
1147       // embedder didn't specify a custom uncaught exception callback,
1148       // or if the custom callback determined that V8 should abort, then
1149       // abort.
1150       if (FLAG_abort_on_uncaught_exception) {
1151         CatchType prediction = PredictExceptionCatcher();
1152         if ((prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) &&
1153             (!abort_on_uncaught_exception_callback_ ||
1154              abort_on_uncaught_exception_callback_(
1155                  reinterpret_cast<v8::Isolate*>(this)))) {
1156           // Prevent endless recursion.
1157           FLAG_abort_on_uncaught_exception = false;
1158           // This flag is intended for use by JavaScript developers, so
1159           // print a user-friendly stack trace (not an internal one).
1160           PrintF(stderr, "%s\n\nFROM\n",
1161                  MessageHandler::GetLocalizedMessage(this, message_obj).get());
1162           PrintCurrentStackTrace(stderr);
1163           base::OS::Abort();
1164         }
1165       }
1166     }
1167   }
1168 
1169   // Set the exception being thrown.
1170   set_pending_exception(*exception_handle);
1171   return heap()->exception();
1172 }
1173 
1174 
1175 Object* Isolate::ReThrow(Object* exception) {
1176   DCHECK(!has_pending_exception());
1177 
1178   // Set the exception being re-thrown.
1179   set_pending_exception(exception);
1180   return heap()->exception();
1181 }
1182 
1183 
1184 Object* Isolate::UnwindAndFindHandler() {
1185   Object* exception = pending_exception();
1186 
1187   Code* code = nullptr;
1188   Context* context = nullptr;
1189   intptr_t offset = 0;
1190   Address handler_sp = nullptr;
1191   Address handler_fp = nullptr;
1192 
1193   // Special handling of termination exceptions, uncatchable by JavaScript and
1194   // Wasm code, we unwind the handlers until the top ENTRY handler is found.
1195   bool catchable_by_js = is_catchable_by_javascript(exception);
1196 
1197   // Compute handler and stack unwinding information by performing a full walk
1198   // over the stack and dispatching according to the frame type.
1199   for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) {
1200     StackFrame* frame = iter.frame();
1201 
1202     // For JSEntryStub frames we always have a handler.
1203     if (frame->is_entry() || frame->is_entry_construct()) {
1204       StackHandler* handler = frame->top_handler();
1205 
1206       // Restore the next handler.
1207       thread_local_top()->handler_ = handler->next()->address();
1208 
1209       // Gather information from the handler.
1210       code = frame->LookupCode();
1211       handler_sp = handler->address() + StackHandlerConstants::kSize;
1212       offset = Smi::cast(code->handler_table()->get(0))->value();
1213       break;
1214     }
1215 
1216     if (FLAG_wasm_eh_prototype) {
1217       if (frame->is_wasm() && is_catchable_by_wasm(exception)) {
1218         int stack_slots = 0;  // Will contain stack slot count of frame.
1219         WasmFrame* wasm_frame = static_cast<WasmFrame*>(frame);
1220         offset = wasm_frame->LookupExceptionHandlerInTable(&stack_slots);
1221         if (offset >= 0) {
1222           // Compute the stack pointer from the frame pointer. This ensures that
1223           // argument slots on the stack are dropped as returning would.
1224           Address return_sp = frame->fp() +
1225                               StandardFrameConstants::kFixedFrameSizeAboveFp -
1226                               stack_slots * kPointerSize;
1227 
1228           // Gather information from the frame.
1229           code = frame->LookupCode();
1230 
1231           handler_sp = return_sp;
1232           handler_fp = frame->fp();
1233           break;
1234         }
1235       }
1236     }
1237 
1238     // For optimized frames we perform a lookup in the handler table.
1239     if (frame->is_optimized() && catchable_by_js) {
1240       OptimizedFrame* js_frame = static_cast<OptimizedFrame*>(frame);
1241       int stack_slots = 0;  // Will contain stack slot count of frame.
1242       offset = js_frame->LookupExceptionHandlerInTable(&stack_slots, nullptr);
1243       if (offset >= 0) {
1244         // Compute the stack pointer from the frame pointer. This ensures that
1245         // argument slots on the stack are dropped as returning would.
1246         Address return_sp = frame->fp() +
1247                             StandardFrameConstants::kFixedFrameSizeAboveFp -
1248                             stack_slots * kPointerSize;
1249 
1250         // Gather information from the frame.
1251         code = frame->LookupCode();
1252 
1253         // TODO(bmeurer): Turbofanned BUILTIN frames appear as OPTIMIZED, but
1254         // do not have a code kind of OPTIMIZED_FUNCTION.
1255         if (code->kind() == Code::OPTIMIZED_FUNCTION &&
1256             code->marked_for_deoptimization()) {
1257           // If the target code is lazy deoptimized, we jump to the original
1258           // return address, but we make a note that we are throwing, so that
1259           // the deoptimizer can do the right thing.
1260           offset = static_cast<int>(frame->pc() - code->entry());
1261           set_deoptimizer_lazy_throw(true);
1262         }
1263         handler_sp = return_sp;
1264         handler_fp = frame->fp();
1265         break;
1266       }
1267     }
1268 
1269     // For interpreted frame we perform a range lookup in the handler table.
1270     if (frame->is_interpreted() && catchable_by_js) {
1271       InterpretedFrame* js_frame = static_cast<InterpretedFrame*>(frame);
1272       int register_slots = js_frame->GetBytecodeArray()->register_count();
1273       int context_reg = 0;  // Will contain register index holding context.
1274       offset = js_frame->LookupExceptionHandlerInTable(&context_reg, nullptr);
1275       if (offset >= 0) {
1276         // Compute the stack pointer from the frame pointer. This ensures that
1277         // argument slots on the stack are dropped as returning would.
1278         // Note: This is only needed for interpreted frames that have been
1279         //       materialized by the deoptimizer. If there is a handler frame
1280         //       in between then {frame->sp()} would already be correct.
1281         Address return_sp = frame->fp() -
1282                             InterpreterFrameConstants::kFixedFrameSizeFromFp -
1283                             register_slots * kPointerSize;
1284 
1285         // Patch the bytecode offset in the interpreted frame to reflect the
1286         // position of the exception handler. The special builtin below will
1287         // take care of continuing to dispatch at that position. Also restore
1288         // the correct context for the handler from the interpreter register.
1289         context = Context::cast(js_frame->ReadInterpreterRegister(context_reg));
1290         js_frame->PatchBytecodeOffset(static_cast<int>(offset));
1291         offset = 0;
1292 
1293         // Gather information from the frame.
1294         code = *builtins()->InterpreterEnterBytecodeDispatch();
1295         handler_sp = return_sp;
1296         handler_fp = frame->fp();
1297         break;
1298       }
1299     }
1300 
1301     // For JavaScript frames we perform a range lookup in the handler table.
1302     if (frame->is_java_script() && catchable_by_js) {
1303       JavaScriptFrame* js_frame = static_cast<JavaScriptFrame*>(frame);
1304       int stack_depth = 0;  // Will contain operand stack depth of handler.
1305       offset = js_frame->LookupExceptionHandlerInTable(&stack_depth, nullptr);
1306       if (offset >= 0) {
1307         // Compute the stack pointer from the frame pointer. This ensures that
1308         // operand stack slots are dropped for nested statements. Also restore
1309         // correct context for the handler which is pushed within the try-block.
1310         Address return_sp = frame->fp() -
1311                             StandardFrameConstants::kFixedFrameSizeFromFp -
1312                             stack_depth * kPointerSize;
1313         STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1314         context = Context::cast(Memory::Object_at(return_sp - kPointerSize));
1315 
1316         // Gather information from the frame.
1317         code = frame->LookupCode();
1318         handler_sp = return_sp;
1319         handler_fp = frame->fp();
1320         break;
1321       }
1322     }
1323 
1324     RemoveMaterializedObjectsOnUnwind(frame);
1325   }
1326 
1327   // Handler must exist.
1328   CHECK(code != nullptr);
1329 
1330   // Store information to be consumed by the CEntryStub.
1331   thread_local_top()->pending_handler_context_ = context;
1332   thread_local_top()->pending_handler_code_ = code;
1333   thread_local_top()->pending_handler_offset_ = offset;
1334   thread_local_top()->pending_handler_fp_ = handler_fp;
1335   thread_local_top()->pending_handler_sp_ = handler_sp;
1336 
1337   // Return and clear pending exception.
1338   clear_pending_exception();
1339   return exception;
1340 }
1341 
1342 namespace {
1343 HandlerTable::CatchPrediction PredictException(JavaScriptFrame* frame) {
1344   HandlerTable::CatchPrediction prediction;
1345   if (frame->is_optimized()) {
1346     if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) {
1347       // This optimized frame will catch. It's handler table does not include
1348       // exception prediction, and we need to use the corresponding handler
1349       // tables on the unoptimized code objects.
1350       List<FrameSummary> summaries;
1351       frame->Summarize(&summaries);
1352       for (const FrameSummary& summary : summaries) {
1353         Handle<AbstractCode> code = summary.abstract_code();
1354         if (code->kind() == AbstractCode::OPTIMIZED_FUNCTION) {
1355           DCHECK(summary.function()->shared()->asm_function());
1356           DCHECK(!FLAG_turbo_asm_deoptimization);
1357           // asm code cannot contain try-catch.
1358           continue;
1359         }
1360         int code_offset = summary.code_offset();
1361         int index =
1362             code->LookupRangeInHandlerTable(code_offset, nullptr, &prediction);
1363         if (index <= 0) continue;
1364         if (prediction == HandlerTable::UNCAUGHT) continue;
1365         return prediction;
1366       }
1367     }
1368   } else if (frame->LookupExceptionHandlerInTable(nullptr, &prediction) > 0) {
1369     return prediction;
1370   }
1371   return HandlerTable::UNCAUGHT;
1372 }
1373 }  // anonymous namespace
1374 
1375 Isolate::CatchType Isolate::PredictExceptionCatcher() {
1376   Address external_handler = thread_local_top()->try_catch_handler_address();
1377   Address entry_handler = Isolate::handler(thread_local_top());
1378   if (IsExternalHandlerOnTop(nullptr)) return CAUGHT_BY_EXTERNAL;
1379 
1380   // Search for an exception handler by performing a full walk over the stack.
1381   for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) {
1382     StackFrame* frame = iter.frame();
1383 
1384     // For JSEntryStub frames we update the JS_ENTRY handler.
1385     if (frame->is_entry() || frame->is_entry_construct()) {
1386       entry_handler = frame->top_handler()->next()->address();
1387     }
1388 
1389     // For JavaScript frames we perform a lookup in the handler table.
1390     if (frame->is_java_script()) {
1391       JavaScriptFrame* js_frame = static_cast<JavaScriptFrame*>(frame);
1392       HandlerTable::CatchPrediction prediction = PredictException(js_frame);
1393       if (prediction == HandlerTable::DESUGARING) return CAUGHT_BY_DESUGARING;
1394       if (prediction == HandlerTable::ASYNC_AWAIT) return CAUGHT_BY_ASYNC_AWAIT;
1395       if (prediction == HandlerTable::PROMISE) return CAUGHT_BY_PROMISE;
1396       if (prediction != HandlerTable::UNCAUGHT) return CAUGHT_BY_JAVASCRIPT;
1397     }
1398 
1399     // The exception has been externally caught if and only if there is an
1400     // external handler which is on top of the top-most JS_ENTRY handler.
1401     if (external_handler != nullptr && !try_catch_handler()->is_verbose_) {
1402       if (entry_handler == nullptr || entry_handler > external_handler) {
1403         return CAUGHT_BY_EXTERNAL;
1404       }
1405     }
1406   }
1407 
1408   // Handler not found.
1409   return NOT_CAUGHT;
1410 }
1411 
1412 
1413 void Isolate::RemoveMaterializedObjectsOnUnwind(StackFrame* frame) {
1414   if (frame->is_optimized()) {
1415     bool removed = materialized_object_store_->Remove(frame->fp());
1416     USE(removed);
1417     // If there were any materialized objects, the code should be
1418     // marked for deopt.
1419     DCHECK(!removed || frame->LookupCode()->marked_for_deoptimization());
1420   }
1421 }
1422 
1423 
1424 Object* Isolate::ThrowIllegalOperation() {
1425   if (FLAG_stack_trace_on_illegal) PrintStack(stdout);
1426   return Throw(heap()->illegal_access_string());
1427 }
1428 
1429 
1430 void Isolate::ScheduleThrow(Object* exception) {
1431   // When scheduling a throw we first throw the exception to get the
1432   // error reporting if it is uncaught before rescheduling it.
1433   Throw(exception);
1434   PropagatePendingExceptionToExternalTryCatch();
1435   if (has_pending_exception()) {
1436     thread_local_top()->scheduled_exception_ = pending_exception();
1437     thread_local_top()->external_caught_exception_ = false;
1438     clear_pending_exception();
1439   }
1440 }
1441 
1442 
1443 void Isolate::RestorePendingMessageFromTryCatch(v8::TryCatch* handler) {
1444   DCHECK(handler == try_catch_handler());
1445   DCHECK(handler->HasCaught());
1446   DCHECK(handler->rethrow_);
1447   DCHECK(handler->capture_message_);
1448   Object* message = reinterpret_cast<Object*>(handler->message_obj_);
1449   DCHECK(message->IsJSMessageObject() || message->IsTheHole(this));
1450   thread_local_top()->pending_message_obj_ = message;
1451 }
1452 
1453 
1454 void Isolate::CancelScheduledExceptionFromTryCatch(v8::TryCatch* handler) {
1455   DCHECK(has_scheduled_exception());
1456   if (scheduled_exception() == handler->exception_) {
1457     DCHECK(scheduled_exception() != heap()->termination_exception());
1458     clear_scheduled_exception();
1459   }
1460 }
1461 
1462 
1463 Object* Isolate::PromoteScheduledException() {
1464   Object* thrown = scheduled_exception();
1465   clear_scheduled_exception();
1466   // Re-throw the exception to avoid getting repeated error reporting.
1467   return ReThrow(thrown);
1468 }
1469 
1470 
1471 void Isolate::PrintCurrentStackTrace(FILE* out) {
1472   for (StackTraceFrameIterator it(this); !it.done(); it.Advance()) {
1473     if (!it.is_javascript()) continue;
1474 
1475     HandleScope scope(this);
1476     JavaScriptFrame* frame = it.javascript_frame();
1477 
1478     Handle<Object> receiver(frame->receiver(), this);
1479     Handle<JSFunction> function(frame->function(), this);
1480     Handle<AbstractCode> code(AbstractCode::cast(frame->LookupCode()), this);
1481     const int offset =
1482         static_cast<int>(frame->pc() - code->instruction_start());
1483 
1484     JSStackFrame site(this, receiver, function, code, offset);
1485     Handle<String> line = site.ToString().ToHandleChecked();
1486     if (line->length() > 0) {
1487       line->PrintOn(out);
1488       PrintF(out, "\n");
1489     }
1490   }
1491 }
1492 
1493 bool Isolate::ComputeLocation(MessageLocation* target) {
1494   StackTraceFrameIterator it(this);
1495   if (it.done()) return false;
1496   StandardFrame* frame = it.frame();
1497   // TODO(clemensh): handle wasm frames
1498   if (!frame->is_java_script()) return false;
1499   JSFunction* fun = JavaScriptFrame::cast(frame)->function();
1500   Object* script = fun->shared()->script();
1501   if (!script->IsScript() ||
1502       (Script::cast(script)->source()->IsUndefined(this))) {
1503     return false;
1504   }
1505   Handle<Script> casted_script(Script::cast(script), this);
1506   // Compute the location from the function and the relocation info of the
1507   // baseline code. For optimized code this will use the deoptimization
1508   // information to get canonical location information.
1509   List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
1510   JavaScriptFrame::cast(frame)->Summarize(&frames);
1511   FrameSummary& summary = frames.last();
1512   int pos = summary.abstract_code()->SourcePosition(summary.code_offset());
1513   *target = MessageLocation(casted_script, pos, pos + 1, handle(fun, this));
1514   return true;
1515 }
1516 
1517 bool Isolate::ComputeLocationFromException(MessageLocation* target,
1518                                            Handle<Object> exception) {
1519   if (!exception->IsJSObject()) return false;
1520 
1521   Handle<Name> start_pos_symbol = factory()->error_start_pos_symbol();
1522   Handle<Object> start_pos = JSReceiver::GetDataProperty(
1523       Handle<JSObject>::cast(exception), start_pos_symbol);
1524   if (!start_pos->IsSmi()) return false;
1525   int start_pos_value = Handle<Smi>::cast(start_pos)->value();
1526 
1527   Handle<Name> end_pos_symbol = factory()->error_end_pos_symbol();
1528   Handle<Object> end_pos = JSReceiver::GetDataProperty(
1529       Handle<JSObject>::cast(exception), end_pos_symbol);
1530   if (!end_pos->IsSmi()) return false;
1531   int end_pos_value = Handle<Smi>::cast(end_pos)->value();
1532 
1533   Handle<Name> script_symbol = factory()->error_script_symbol();
1534   Handle<Object> script = JSReceiver::GetDataProperty(
1535       Handle<JSObject>::cast(exception), script_symbol);
1536   if (!script->IsScript()) return false;
1537 
1538   Handle<Script> cast_script(Script::cast(*script));
1539   *target = MessageLocation(cast_script, start_pos_value, end_pos_value);
1540   return true;
1541 }
1542 
1543 
1544 bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target,
1545                                             Handle<Object> exception) {
1546   if (!exception->IsJSObject()) return false;
1547   Handle<Name> key = factory()->stack_trace_symbol();
1548   Handle<Object> property =
1549       JSReceiver::GetDataProperty(Handle<JSObject>::cast(exception), key);
1550   if (!property->IsJSArray()) return false;
1551   Handle<JSArray> simple_stack_trace = Handle<JSArray>::cast(property);
1552 
1553   Handle<FrameArray> elements(FrameArray::cast(simple_stack_trace->elements()));
1554 
1555   const int frame_count = elements->FrameCount();
1556   for (int i = 0; i < frame_count; i++) {
1557     if (elements->IsWasmFrame(i)) {
1558       // TODO(clemensh): handle wasm frames
1559       return false;
1560     }
1561 
1562     Handle<JSFunction> fun = handle(elements->Function(i), this);
1563     if (!fun->shared()->IsSubjectToDebugging()) continue;
1564 
1565     Object* script = fun->shared()->script();
1566     if (script->IsScript() &&
1567         !(Script::cast(script)->source()->IsUndefined(this))) {
1568       AbstractCode* abstract_code = elements->Code(i);
1569       const int code_offset = elements->Offset(i)->value();
1570       const int pos = abstract_code->SourcePosition(code_offset);
1571 
1572       Handle<Script> casted_script(Script::cast(script));
1573       *target = MessageLocation(casted_script, pos, pos + 1);
1574       return true;
1575     }
1576   }
1577   return false;
1578 }
1579 
1580 
1581 Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception,
1582                                                MessageLocation* location) {
1583   Handle<JSArray> stack_trace_object;
1584   if (capture_stack_trace_for_uncaught_exceptions_) {
1585     if (exception->IsJSError()) {
1586       // We fetch the stack trace that corresponds to this error object.
1587       // If the lookup fails, the exception is probably not a valid Error
1588       // object. In that case, we fall through and capture the stack trace
1589       // at this throw site.
1590       stack_trace_object =
1591           GetDetailedStackTrace(Handle<JSObject>::cast(exception));
1592     }
1593     if (stack_trace_object.is_null()) {
1594       // Not an error object, we capture stack and location at throw site.
1595       stack_trace_object = CaptureCurrentStackTrace(
1596           stack_trace_for_uncaught_exceptions_frame_limit_,
1597           stack_trace_for_uncaught_exceptions_options_);
1598     }
1599   }
1600   MessageLocation computed_location;
1601   if (location == NULL &&
1602       (ComputeLocationFromException(&computed_location, exception) ||
1603        ComputeLocationFromStackTrace(&computed_location, exception) ||
1604        ComputeLocation(&computed_location))) {
1605     location = &computed_location;
1606   }
1607 
1608   return MessageHandler::MakeMessageObject(
1609       this, MessageTemplate::kUncaughtException, location, exception,
1610       stack_trace_object);
1611 }
1612 
1613 
1614 bool Isolate::IsJavaScriptHandlerOnTop(Object* exception) {
1615   DCHECK_NE(heap()->the_hole_value(), exception);
1616 
1617   // For uncatchable exceptions, the JavaScript handler cannot be on top.
1618   if (!is_catchable_by_javascript(exception)) return false;
1619 
1620   // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
1621   Address entry_handler = Isolate::handler(thread_local_top());
1622   if (entry_handler == nullptr) return false;
1623 
1624   // Get the address of the external handler so we can compare the address to
1625   // determine which one is closer to the top of the stack.
1626   Address external_handler = thread_local_top()->try_catch_handler_address();
1627   if (external_handler == nullptr) return true;
1628 
1629   // The exception has been externally caught if and only if there is an
1630   // external handler which is on top of the top-most JS_ENTRY handler.
1631   //
1632   // Note, that finally clauses would re-throw an exception unless it's aborted
1633   // by jumps in control flow (like return, break, etc.) and we'll have another
1634   // chance to set proper v8::TryCatch later.
1635   return (entry_handler < external_handler);
1636 }
1637 
1638 
1639 bool Isolate::IsExternalHandlerOnTop(Object* exception) {
1640   DCHECK_NE(heap()->the_hole_value(), exception);
1641 
1642   // Get the address of the external handler so we can compare the address to
1643   // determine which one is closer to the top of the stack.
1644   Address external_handler = thread_local_top()->try_catch_handler_address();
1645   if (external_handler == nullptr) return false;
1646 
1647   // For uncatchable exceptions, the external handler is always on top.
1648   if (!is_catchable_by_javascript(exception)) return true;
1649 
1650   // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist.
1651   Address entry_handler = Isolate::handler(thread_local_top());
1652   if (entry_handler == nullptr) return true;
1653 
1654   // The exception has been externally caught if and only if there is an
1655   // external handler which is on top of the top-most JS_ENTRY handler.
1656   //
1657   // Note, that finally clauses would re-throw an exception unless it's aborted
1658   // by jumps in control flow (like return, break, etc.) and we'll have another
1659   // chance to set proper v8::TryCatch later.
1660   return (entry_handler > external_handler);
1661 }
1662 
1663 
1664 void Isolate::ReportPendingMessages() {
1665   Object* exception = pending_exception();
1666 
1667   // Try to propagate the exception to an external v8::TryCatch handler. If
1668   // propagation was unsuccessful, then we will get another chance at reporting
1669   // the pending message if the exception is re-thrown.
1670   bool has_been_propagated = PropagatePendingExceptionToExternalTryCatch();
1671   if (!has_been_propagated) return;
1672 
1673   // Clear the pending message object early to avoid endless recursion.
1674   Object* message_obj = thread_local_top_.pending_message_obj_;
1675   clear_pending_message();
1676 
1677   // For uncatchable exceptions we do nothing. If needed, the exception and the
1678   // message have already been propagated to v8::TryCatch.
1679   if (!is_catchable_by_javascript(exception)) return;
1680 
1681   // Determine whether the message needs to be reported to all message handlers
1682   // depending on whether and external v8::TryCatch or an internal JavaScript
1683   // handler is on top.
1684   bool should_report_exception;
1685   if (IsExternalHandlerOnTop(exception)) {
1686     // Only report the exception if the external handler is verbose.
1687     should_report_exception = try_catch_handler()->is_verbose_;
1688   } else {
1689     // Report the exception if it isn't caught by JavaScript code.
1690     should_report_exception = !IsJavaScriptHandlerOnTop(exception);
1691   }
1692 
1693   // Actually report the pending message to all message handlers.
1694   if (!message_obj->IsTheHole(this) && should_report_exception) {
1695     HandleScope scope(this);
1696     Handle<JSMessageObject> message(JSMessageObject::cast(message_obj), this);
1697     Handle<JSValue> script_wrapper(JSValue::cast(message->script()), this);
1698     Handle<Script> script(Script::cast(script_wrapper->value()), this);
1699     int start_pos = message->start_position();
1700     int end_pos = message->end_position();
1701     MessageLocation location(script, start_pos, end_pos);
1702     MessageHandler::ReportMessage(this, &location, message);
1703   }
1704 }
1705 
1706 
1707 MessageLocation Isolate::GetMessageLocation() {
1708   DCHECK(has_pending_exception());
1709 
1710   if (thread_local_top_.pending_exception_ != heap()->termination_exception() &&
1711       !thread_local_top_.pending_message_obj_->IsTheHole(this)) {
1712     Handle<JSMessageObject> message_obj(
1713         JSMessageObject::cast(thread_local_top_.pending_message_obj_), this);
1714     Handle<JSValue> script_wrapper(JSValue::cast(message_obj->script()), this);
1715     Handle<Script> script(Script::cast(script_wrapper->value()), this);
1716     int start_pos = message_obj->start_position();
1717     int end_pos = message_obj->end_position();
1718     return MessageLocation(script, start_pos, end_pos);
1719   }
1720 
1721   return MessageLocation();
1722 }
1723 
1724 
1725 bool Isolate::OptionalRescheduleException(bool is_bottom_call) {
1726   DCHECK(has_pending_exception());
1727   PropagatePendingExceptionToExternalTryCatch();
1728 
1729   bool is_termination_exception =
1730       pending_exception() == heap_.termination_exception();
1731 
1732   // Do not reschedule the exception if this is the bottom call.
1733   bool clear_exception = is_bottom_call;
1734 
1735   if (is_termination_exception) {
1736     if (is_bottom_call) {
1737       thread_local_top()->external_caught_exception_ = false;
1738       clear_pending_exception();
1739       return false;
1740     }
1741   } else if (thread_local_top()->external_caught_exception_) {
1742     // If the exception is externally caught, clear it if there are no
1743     // JavaScript frames on the way to the C++ frame that has the
1744     // external handler.
1745     DCHECK(thread_local_top()->try_catch_handler_address() != NULL);
1746     Address external_handler_address =
1747         thread_local_top()->try_catch_handler_address();
1748     JavaScriptFrameIterator it(this);
1749     if (it.done() || (it.frame()->sp() > external_handler_address)) {
1750       clear_exception = true;
1751     }
1752   }
1753 
1754   // Clear the exception if needed.
1755   if (clear_exception) {
1756     thread_local_top()->external_caught_exception_ = false;
1757     clear_pending_exception();
1758     return false;
1759   }
1760 
1761   // Reschedule the exception.
1762   thread_local_top()->scheduled_exception_ = pending_exception();
1763   clear_pending_exception();
1764   return true;
1765 }
1766 
1767 void Isolate::PushPromise(Handle<JSObject> promise) {
1768   ThreadLocalTop* tltop = thread_local_top();
1769   PromiseOnStack* prev = tltop->promise_on_stack_;
1770   Handle<JSObject> global_promise =
1771       Handle<JSObject>::cast(global_handles()->Create(*promise));
1772   tltop->promise_on_stack_ = new PromiseOnStack(global_promise, prev);
1773 }
1774 
1775 
1776 void Isolate::PopPromise() {
1777   ThreadLocalTop* tltop = thread_local_top();
1778   if (tltop->promise_on_stack_ == NULL) return;
1779   PromiseOnStack* prev = tltop->promise_on_stack_->prev();
1780   Handle<Object> global_promise = tltop->promise_on_stack_->promise();
1781   delete tltop->promise_on_stack_;
1782   tltop->promise_on_stack_ = prev;
1783   global_handles()->Destroy(global_promise.location());
1784 }
1785 
1786 bool Isolate::PromiseHasUserDefinedRejectHandler(Handle<Object> promise) {
1787   Handle<JSFunction> fun = promise_has_user_defined_reject_handler();
1788   Handle<Object> has_reject_handler;
1789   // If we are, e.g., overflowing the stack, don't try to call out to JS
1790   if (!AllowJavascriptExecution::IsAllowed(this)) return false;
1791   // Call the registered function to check for a handler
1792   if (Execution::TryCall(this, fun, promise, 0, NULL)
1793           .ToHandle(&has_reject_handler)) {
1794     return has_reject_handler->IsTrue(this);
1795   }
1796   // If an exception is thrown in the course of execution of this built-in
1797   // function, it indicates either a bug, or a synthetic uncatchable
1798   // exception in the shutdown path. In either case, it's OK to predict either
1799   // way in DevTools.
1800   return false;
1801 }
1802 
1803 Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
1804   Handle<Object> undefined = factory()->undefined_value();
1805   ThreadLocalTop* tltop = thread_local_top();
1806   if (tltop->promise_on_stack_ == NULL) return undefined;
1807   // Find the top-most try-catch or try-finally handler.
1808   CatchType prediction = PredictExceptionCatcher();
1809   if (prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) {
1810     return undefined;
1811   }
1812   Handle<Object> retval = undefined;
1813   PromiseOnStack* promise_on_stack = tltop->promise_on_stack_;
1814   for (JavaScriptFrameIterator it(this); !it.done(); it.Advance()) {
1815     switch (PredictException(it.frame())) {
1816       case HandlerTable::UNCAUGHT:
1817         continue;
1818       case HandlerTable::CAUGHT:
1819       case HandlerTable::DESUGARING:
1820         if (retval->IsJSObject()) {
1821           // Caught the result of an inner async/await invocation.
1822           // Mark the inner promise as caught in the "synchronous case" so
1823           // that Debug::OnException will see. In the synchronous case,
1824           // namely in the code in an async function before the first
1825           // await, the function which has this exception event has not yet
1826           // returned, so the generated Promise has not yet been marked
1827           // by AsyncFunctionAwaitCaught with promiseHandledHintSymbol.
1828           Handle<Symbol> key = factory()->promise_handled_hint_symbol();
1829           JSObject::SetProperty(Handle<JSObject>::cast(retval), key,
1830                                 factory()->true_value(), STRICT)
1831               .Assert();
1832         }
1833         return retval;
1834       case HandlerTable::PROMISE:
1835         return promise_on_stack
1836                    ? Handle<Object>::cast(promise_on_stack->promise())
1837                    : undefined;
1838       case HandlerTable::ASYNC_AWAIT: {
1839         // If in the initial portion of async/await, continue the loop to pop up
1840         // successive async/await stack frames until an asynchronous one with
1841         // dependents is found, or a non-async stack frame is encountered, in
1842         // order to handle the synchronous async/await catch prediction case:
1843         // assume that async function calls are awaited.
1844         if (!promise_on_stack) return retval;
1845         retval = promise_on_stack->promise();
1846         if (PromiseHasUserDefinedRejectHandler(retval)) {
1847           return retval;
1848         }
1849         promise_on_stack = promise_on_stack->prev();
1850         continue;
1851       }
1852     }
1853   }
1854   return retval;
1855 }
1856 
1857 
1858 void Isolate::SetCaptureStackTraceForUncaughtExceptions(
1859       bool capture,
1860       int frame_limit,
1861       StackTrace::StackTraceOptions options) {
1862   capture_stack_trace_for_uncaught_exceptions_ = capture;
1863   stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit;
1864   stack_trace_for_uncaught_exceptions_options_ = options;
1865 }
1866 
1867 
1868 void Isolate::SetAbortOnUncaughtExceptionCallback(
1869     v8::Isolate::AbortOnUncaughtExceptionCallback callback) {
1870   abort_on_uncaught_exception_callback_ = callback;
1871 }
1872 
1873 
1874 Handle<Context> Isolate::GetCallingNativeContext() {
1875   JavaScriptFrameIterator it(this);
1876   if (debug_->in_debug_scope()) {
1877     while (!it.done()) {
1878       JavaScriptFrame* frame = it.frame();
1879       Context* context = Context::cast(frame->context());
1880       if (context->native_context() == *debug_->debug_context()) {
1881         it.Advance();
1882       } else {
1883         break;
1884       }
1885     }
1886   }
1887   if (it.done()) return Handle<Context>::null();
1888   JavaScriptFrame* frame = it.frame();
1889   Context* context = Context::cast(frame->context());
1890   return Handle<Context>(context->native_context(), this);
1891 }
1892 
1893 
1894 char* Isolate::ArchiveThread(char* to) {
1895   MemCopy(to, reinterpret_cast<char*>(thread_local_top()),
1896           sizeof(ThreadLocalTop));
1897   InitializeThreadLocal();
1898   clear_pending_exception();
1899   clear_pending_message();
1900   clear_scheduled_exception();
1901   return to + sizeof(ThreadLocalTop);
1902 }
1903 
1904 
1905 char* Isolate::RestoreThread(char* from) {
1906   MemCopy(reinterpret_cast<char*>(thread_local_top()), from,
1907           sizeof(ThreadLocalTop));
1908 // This might be just paranoia, but it seems to be needed in case a
1909 // thread_local_top_ is restored on a separate OS thread.
1910 #ifdef USE_SIMULATOR
1911   thread_local_top()->simulator_ = Simulator::current(this);
1912 #endif
1913   DCHECK(context() == NULL || context()->IsContext());
1914   return from + sizeof(ThreadLocalTop);
1915 }
1916 
1917 
1918 Isolate::ThreadDataTable::ThreadDataTable()
1919     : list_(NULL) {
1920 }
1921 
1922 
1923 Isolate::ThreadDataTable::~ThreadDataTable() {
1924   // TODO(svenpanne) The assertion below would fire if an embedder does not
1925   // cleanly dispose all Isolates before disposing v8, so we are conservative
1926   // and leave it out for now.
1927   // DCHECK_NULL(list_);
1928 }
1929 
1930 
1931 Isolate::PerIsolateThreadData::~PerIsolateThreadData() {
1932 #if defined(USE_SIMULATOR)
1933   delete simulator_;
1934 #endif
1935 }
1936 
1937 
1938 Isolate::PerIsolateThreadData*
1939     Isolate::ThreadDataTable::Lookup(Isolate* isolate,
1940                                      ThreadId thread_id) {
1941   for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) {
1942     if (data->Matches(isolate, thread_id)) return data;
1943   }
1944   return NULL;
1945 }
1946 
1947 
1948 void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) {
1949   if (list_ != NULL) list_->prev_ = data;
1950   data->next_ = list_;
1951   list_ = data;
1952 }
1953 
1954 
1955 void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
1956   if (list_ == data) list_ = data->next_;
1957   if (data->next_ != NULL) data->next_->prev_ = data->prev_;
1958   if (data->prev_ != NULL) data->prev_->next_ = data->next_;
1959   delete data;
1960 }
1961 
1962 
1963 void Isolate::ThreadDataTable::RemoveAllThreads(Isolate* isolate) {
1964   PerIsolateThreadData* data = list_;
1965   while (data != NULL) {
1966     PerIsolateThreadData* next = data->next_;
1967     if (data->isolate() == isolate) Remove(data);
1968     data = next;
1969   }
1970 }
1971 
1972 
1973 #ifdef DEBUG
1974 #define TRACE_ISOLATE(tag)                                              \
1975   do {                                                                  \
1976     if (FLAG_trace_isolates) {                                          \
1977       PrintF("Isolate %p (id %d)" #tag "\n",                            \
1978              reinterpret_cast<void*>(this), id());                      \
1979     }                                                                   \
1980   } while (false)
1981 #else
1982 #define TRACE_ISOLATE(tag)
1983 #endif
1984 
1985 class VerboseAccountingAllocator : public AccountingAllocator {
1986  public:
1987   VerboseAccountingAllocator(Heap* heap, size_t allocation_sample_bytes,
1988                              size_t pool_sample_bytes)
1989       : heap_(heap),
1990         last_memory_usage_(0),
1991         last_pool_size_(0),
1992         nesting_deepth_(0),
1993         allocation_sample_bytes_(allocation_sample_bytes),
1994         pool_sample_bytes_(pool_sample_bytes) {}
1995 
1996   v8::internal::Segment* GetSegment(size_t size) override {
1997     v8::internal::Segment* memory = AccountingAllocator::GetSegment(size);
1998     if (memory) {
1999       size_t malloced_current = GetCurrentMemoryUsage();
2000       size_t pooled_current = GetCurrentPoolSize();
2001 
2002       if (last_memory_usage_.Value() + allocation_sample_bytes_ <
2003               malloced_current ||
2004           last_pool_size_.Value() + pool_sample_bytes_ < pooled_current) {
2005         PrintMemoryJSON(malloced_current, pooled_current);
2006         last_memory_usage_.SetValue(malloced_current);
2007         last_pool_size_.SetValue(pooled_current);
2008       }
2009     }
2010     return memory;
2011   }
2012 
2013   void ReturnSegment(v8::internal::Segment* memory) override {
2014     AccountingAllocator::ReturnSegment(memory);
2015     size_t malloced_current = GetCurrentMemoryUsage();
2016     size_t pooled_current = GetCurrentPoolSize();
2017 
2018     if (malloced_current + allocation_sample_bytes_ <
2019             last_memory_usage_.Value() ||
2020         pooled_current + pool_sample_bytes_ < last_pool_size_.Value()) {
2021       PrintMemoryJSON(malloced_current, pooled_current);
2022       last_memory_usage_.SetValue(malloced_current);
2023       last_pool_size_.SetValue(pooled_current);
2024     }
2025   }
2026 
2027   void ZoneCreation(const Zone* zone) override {
2028     double time = heap_->isolate()->time_millis_since_init();
2029     PrintF(
2030         "{"
2031         "\"type\": \"zonecreation\", "
2032         "\"isolate\": \"%p\", "
2033         "\"time\": %f, "
2034         "\"ptr\": \"%p\", "
2035         "\"name\": \"%s\","
2036         "\"nesting\": %zu"
2037         "}\n",
2038         reinterpret_cast<void*>(heap_->isolate()), time,
2039         reinterpret_cast<const void*>(zone), zone->name(),
2040         nesting_deepth_.Value());
2041     nesting_deepth_.Increment(1);
2042   }
2043 
2044   void ZoneDestruction(const Zone* zone) override {
2045     nesting_deepth_.Decrement(1);
2046     double time = heap_->isolate()->time_millis_since_init();
2047     PrintF(
2048         "{"
2049         "\"type\": \"zonedestruction\", "
2050         "\"isolate\": \"%p\", "
2051         "\"time\": %f, "
2052         "\"ptr\": \"%p\", "
2053         "\"name\": \"%s\", "
2054         "\"size\": %zu,"
2055         "\"nesting\": %zu"
2056         "}\n",
2057         reinterpret_cast<void*>(heap_->isolate()), time,
2058         reinterpret_cast<const void*>(zone), zone->name(),
2059         zone->allocation_size(), nesting_deepth_.Value());
2060   }
2061 
2062  private:
2063   void PrintMemoryJSON(size_t malloced, size_t pooled) {
2064     // Note: Neither isolate, nor heap is locked, so be careful with accesses
2065     // as the allocator is potentially used on a concurrent thread.
2066     double time = heap_->isolate()->time_millis_since_init();
2067     PrintF(
2068         "{"
2069         "\"type\": \"zone\", "
2070         "\"isolate\": \"%p\", "
2071         "\"time\": %f, "
2072         "\"allocated\": %zu,"
2073         "\"pooled\": %zu"
2074         "}\n",
2075         reinterpret_cast<void*>(heap_->isolate()), time, malloced, pooled);
2076   }
2077 
2078   Heap* heap_;
2079   base::AtomicNumber<size_t> last_memory_usage_;
2080   base::AtomicNumber<size_t> last_pool_size_;
2081   base::AtomicNumber<size_t> nesting_deepth_;
2082   size_t allocation_sample_bytes_, pool_sample_bytes_;
2083 };
2084 
2085 Isolate::Isolate(bool enable_serializer)
2086     : embedder_data_(),
2087       entry_stack_(NULL),
2088       stack_trace_nesting_level_(0),
2089       incomplete_message_(NULL),
2090       bootstrapper_(NULL),
2091       runtime_profiler_(NULL),
2092       compilation_cache_(NULL),
2093       counters_(NULL),
2094       logger_(NULL),
2095       stats_table_(NULL),
2096       load_stub_cache_(NULL),
2097       store_stub_cache_(NULL),
2098       code_aging_helper_(NULL),
2099       deoptimizer_data_(NULL),
2100       deoptimizer_lazy_throw_(false),
2101       materialized_object_store_(NULL),
2102       capture_stack_trace_for_uncaught_exceptions_(false),
2103       stack_trace_for_uncaught_exceptions_frame_limit_(0),
2104       stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview),
2105       context_slot_cache_(NULL),
2106       descriptor_lookup_cache_(NULL),
2107       handle_scope_implementer_(NULL),
2108       unicode_cache_(NULL),
2109       allocator_(FLAG_trace_gc_object_stats ? new VerboseAccountingAllocator(
2110                                                   &heap_, 256 * KB, 128 * KB)
2111                                             : new AccountingAllocator()),
2112       inner_pointer_to_code_cache_(NULL),
2113       global_handles_(NULL),
2114       eternal_handles_(NULL),
2115       thread_manager_(NULL),
2116       has_installed_extensions_(false),
2117       regexp_stack_(NULL),
2118       date_cache_(NULL),
2119       call_descriptor_data_(NULL),
2120       // TODO(bmeurer) Initialized lazily because it depends on flags; can
2121       // be fixed once the default isolate cleanup is done.
2122       random_number_generator_(NULL),
2123       rail_mode_(PERFORMANCE_ANIMATION),
2124       serializer_enabled_(enable_serializer),
2125       has_fatal_error_(false),
2126       initialized_from_snapshot_(false),
2127       is_tail_call_elimination_enabled_(true),
2128       is_isolate_in_background_(false),
2129       cpu_profiler_(NULL),
2130       heap_profiler_(NULL),
2131       code_event_dispatcher_(new CodeEventDispatcher()),
2132       function_entry_hook_(NULL),
2133       deferred_handles_head_(NULL),
2134       optimizing_compile_dispatcher_(NULL),
2135       stress_deopt_count_(0),
2136       next_optimization_id_(0),
2137 #if TRACE_MAPS
2138       next_unique_sfi_id_(0),
2139 #endif
2140       is_running_microtasks_(false),
2141       use_counter_callback_(NULL),
2142       basic_block_profiler_(NULL),
2143       cancelable_task_manager_(new CancelableTaskManager()),
2144       abort_on_uncaught_exception_callback_(NULL) {
2145   {
2146     base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
2147     CHECK(thread_data_table_);
2148   }
2149   id_ = base::NoBarrier_AtomicIncrement(&isolate_counter_, 1);
2150   TRACE_ISOLATE(constructor);
2151 
2152   memset(isolate_addresses_, 0,
2153       sizeof(isolate_addresses_[0]) * (kIsolateAddressCount + 1));
2154 
2155   heap_.isolate_ = this;
2156   stack_guard_.isolate_ = this;
2157 
2158   // ThreadManager is initialized early to support locking an isolate
2159   // before it is entered.
2160   thread_manager_ = new ThreadManager();
2161   thread_manager_->isolate_ = this;
2162 
2163 #ifdef DEBUG
2164   // heap_histograms_ initializes itself.
2165   memset(&js_spill_information_, 0, sizeof(js_spill_information_));
2166 #endif
2167 
2168   handle_scope_data_.Initialize();
2169 
2170 #define ISOLATE_INIT_EXECUTE(type, name, initial_value)                        \
2171   name##_ = (initial_value);
2172   ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE)
2173 #undef ISOLATE_INIT_EXECUTE
2174 
2175 #define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length)                         \
2176   memset(name##_, 0, sizeof(type) * length);
2177   ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE)
2178 #undef ISOLATE_INIT_ARRAY_EXECUTE
2179 
2180   InitializeLoggingAndCounters();
2181   debug_ = new Debug(this);
2182 
2183   init_memcopy_functions(this);
2184 }
2185 
2186 
2187 void Isolate::TearDown() {
2188   TRACE_ISOLATE(tear_down);
2189 
2190   // Temporarily set this isolate as current so that various parts of
2191   // the isolate can access it in their destructors without having a
2192   // direct pointer. We don't use Enter/Exit here to avoid
2193   // initializing the thread data.
2194   PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData();
2195   DCHECK(base::NoBarrier_Load(&isolate_key_created_) == 1);
2196   Isolate* saved_isolate =
2197       reinterpret_cast<Isolate*>(base::Thread::GetThreadLocal(isolate_key_));
2198   SetIsolateThreadLocals(this, NULL);
2199 
2200   Deinit();
2201 
2202   {
2203     base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
2204     thread_data_table_->RemoveAllThreads(this);
2205   }
2206 
2207   delete this;
2208 
2209   // Restore the previous current isolate.
2210   SetIsolateThreadLocals(saved_isolate, saved_data);
2211 }
2212 
2213 
2214 void Isolate::GlobalTearDown() {
2215   delete thread_data_table_;
2216   thread_data_table_ = NULL;
2217 }
2218 
2219 
2220 void Isolate::ClearSerializerData() {
2221   delete external_reference_table_;
2222   external_reference_table_ = NULL;
2223   delete external_reference_map_;
2224   external_reference_map_ = NULL;
2225 }
2226 
2227 
2228 void Isolate::Deinit() {
2229   TRACE_ISOLATE(deinit);
2230 
2231   debug()->Unload();
2232 
2233   FreeThreadResources();
2234 
2235   if (concurrent_recompilation_enabled()) {
2236     optimizing_compile_dispatcher_->Stop();
2237     delete optimizing_compile_dispatcher_;
2238     optimizing_compile_dispatcher_ = NULL;
2239   }
2240 
2241   if (heap_.mark_compact_collector()->sweeping_in_progress()) {
2242     heap_.mark_compact_collector()->EnsureSweepingCompleted();
2243   }
2244 
2245   DumpAndResetCompilationStats();
2246 
2247   if (FLAG_print_deopt_stress) {
2248     PrintF(stdout, "=== Stress deopt counter: %u\n", stress_deopt_count_);
2249   }
2250 
2251   if (cpu_profiler_) {
2252     cpu_profiler_->DeleteAllProfiles();
2253   }
2254 
2255   // We must stop the logger before we tear down other components.
2256   sampler::Sampler* sampler = logger_->sampler();
2257   if (sampler && sampler->IsActive()) sampler->Stop();
2258 
2259   delete deoptimizer_data_;
2260   deoptimizer_data_ = NULL;
2261   builtins_.TearDown();
2262   bootstrapper_->TearDown();
2263 
2264   if (runtime_profiler_ != NULL) {
2265     delete runtime_profiler_;
2266     runtime_profiler_ = NULL;
2267   }
2268 
2269   delete basic_block_profiler_;
2270   basic_block_profiler_ = NULL;
2271 
2272   delete heap_profiler_;
2273   heap_profiler_ = NULL;
2274 
2275   cancelable_task_manager()->CancelAndWait();
2276 
2277   heap_.TearDown();
2278   logger_->TearDown();
2279 
2280   delete interpreter_;
2281   interpreter_ = NULL;
2282 
2283   delete compiler_dispatcher_tracer_;
2284   compiler_dispatcher_tracer_ = nullptr;
2285 
2286   delete cpu_profiler_;
2287   cpu_profiler_ = NULL;
2288 
2289   code_event_dispatcher_.reset();
2290 
2291   delete root_index_map_;
2292   root_index_map_ = NULL;
2293 
2294   ClearSerializerData();
2295 }
2296 
2297 
2298 void Isolate::SetIsolateThreadLocals(Isolate* isolate,
2299                                      PerIsolateThreadData* data) {
2300   base::Thread::SetThreadLocal(isolate_key_, isolate);
2301   base::Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
2302 }
2303 
2304 
2305 Isolate::~Isolate() {
2306   TRACE_ISOLATE(destructor);
2307 
2308   // The entry stack must be empty when we get here.
2309   DCHECK(entry_stack_ == NULL || entry_stack_->previous_item == NULL);
2310 
2311   delete entry_stack_;
2312   entry_stack_ = NULL;
2313 
2314   delete unicode_cache_;
2315   unicode_cache_ = NULL;
2316 
2317   delete date_cache_;
2318   date_cache_ = NULL;
2319 
2320   delete[] call_descriptor_data_;
2321   call_descriptor_data_ = NULL;
2322 
2323   delete access_compiler_data_;
2324   access_compiler_data_ = NULL;
2325 
2326   delete regexp_stack_;
2327   regexp_stack_ = NULL;
2328 
2329   delete descriptor_lookup_cache_;
2330   descriptor_lookup_cache_ = NULL;
2331   delete context_slot_cache_;
2332   context_slot_cache_ = NULL;
2333 
2334   delete load_stub_cache_;
2335   load_stub_cache_ = NULL;
2336   delete store_stub_cache_;
2337   store_stub_cache_ = NULL;
2338   delete code_aging_helper_;
2339   code_aging_helper_ = NULL;
2340   delete stats_table_;
2341   stats_table_ = NULL;
2342 
2343   delete materialized_object_store_;
2344   materialized_object_store_ = NULL;
2345 
2346   delete logger_;
2347   logger_ = NULL;
2348 
2349   delete counters_;
2350   counters_ = NULL;
2351 
2352   delete handle_scope_implementer_;
2353   handle_scope_implementer_ = NULL;
2354 
2355   delete code_tracer();
2356   set_code_tracer(NULL);
2357 
2358   delete compilation_cache_;
2359   compilation_cache_ = NULL;
2360   delete bootstrapper_;
2361   bootstrapper_ = NULL;
2362   delete inner_pointer_to_code_cache_;
2363   inner_pointer_to_code_cache_ = NULL;
2364 
2365   delete thread_manager_;
2366   thread_manager_ = NULL;
2367 
2368   delete global_handles_;
2369   global_handles_ = NULL;
2370   delete eternal_handles_;
2371   eternal_handles_ = NULL;
2372 
2373   delete string_stream_debug_object_cache_;
2374   string_stream_debug_object_cache_ = NULL;
2375 
2376   delete random_number_generator_;
2377   random_number_generator_ = NULL;
2378 
2379   delete debug_;
2380   debug_ = NULL;
2381 
2382   delete cancelable_task_manager_;
2383   cancelable_task_manager_ = nullptr;
2384 
2385   delete allocator_;
2386   allocator_ = nullptr;
2387 
2388 #if USE_SIMULATOR
2389   Simulator::TearDown(simulator_i_cache_, simulator_redirection_);
2390   simulator_i_cache_ = nullptr;
2391   simulator_redirection_ = nullptr;
2392 #endif
2393 }
2394 
2395 
2396 void Isolate::InitializeThreadLocal() {
2397   thread_local_top_.isolate_ = this;
2398   thread_local_top_.Initialize();
2399 }
2400 
2401 
2402 bool Isolate::PropagatePendingExceptionToExternalTryCatch() {
2403   Object* exception = pending_exception();
2404 
2405   if (IsJavaScriptHandlerOnTop(exception)) {
2406     thread_local_top_.external_caught_exception_ = false;
2407     return false;
2408   }
2409 
2410   if (!IsExternalHandlerOnTop(exception)) {
2411     thread_local_top_.external_caught_exception_ = false;
2412     return true;
2413   }
2414 
2415   thread_local_top_.external_caught_exception_ = true;
2416   if (!is_catchable_by_javascript(exception)) {
2417     try_catch_handler()->can_continue_ = false;
2418     try_catch_handler()->has_terminated_ = true;
2419     try_catch_handler()->exception_ = heap()->null_value();
2420   } else {
2421     v8::TryCatch* handler = try_catch_handler();
2422     DCHECK(thread_local_top_.pending_message_obj_->IsJSMessageObject() ||
2423            thread_local_top_.pending_message_obj_->IsTheHole(this));
2424     handler->can_continue_ = true;
2425     handler->has_terminated_ = false;
2426     handler->exception_ = pending_exception();
2427     // Propagate to the external try-catch only if we got an actual message.
2428     if (thread_local_top_.pending_message_obj_->IsTheHole(this)) return true;
2429 
2430     handler->message_obj_ = thread_local_top_.pending_message_obj_;
2431   }
2432   return true;
2433 }
2434 
2435 
2436 void Isolate::InitializeLoggingAndCounters() {
2437   if (logger_ == NULL) {
2438     logger_ = new Logger(this);
2439   }
2440   if (counters_ == NULL) {
2441     counters_ = new Counters(this);
2442   }
2443 }
2444 
2445 
2446 bool Isolate::Init(Deserializer* des) {
2447   TRACE_ISOLATE(init);
2448 
2449   stress_deopt_count_ = FLAG_deopt_every_n_times;
2450 
2451   has_fatal_error_ = false;
2452 
2453   if (function_entry_hook() != NULL) {
2454     // When function entry hooking is in effect, we have to create the code
2455     // stubs from scratch to get entry hooks, rather than loading the previously
2456     // generated stubs from disk.
2457     // If this assert fires, the initialization path has regressed.
2458     DCHECK(des == NULL);
2459   }
2460 
2461   // The initialization process does not handle memory exhaustion.
2462   AlwaysAllocateScope always_allocate(this);
2463 
2464   // Safe after setting Heap::isolate_, and initializing StackGuard
2465   heap_.SetStackLimits();
2466 
2467 #define ASSIGN_ELEMENT(CamelName, hacker_name)                  \
2468   isolate_addresses_[Isolate::k##CamelName##Address] =          \
2469       reinterpret_cast<Address>(hacker_name##_address());
2470   FOR_EACH_ISOLATE_ADDRESS_NAME(ASSIGN_ELEMENT)
2471 #undef ASSIGN_ELEMENT
2472 
2473   compilation_cache_ = new CompilationCache(this);
2474   context_slot_cache_ = new ContextSlotCache();
2475   descriptor_lookup_cache_ = new DescriptorLookupCache();
2476   unicode_cache_ = new UnicodeCache();
2477   inner_pointer_to_code_cache_ = new InnerPointerToCodeCache(this);
2478   global_handles_ = new GlobalHandles(this);
2479   eternal_handles_ = new EternalHandles();
2480   bootstrapper_ = new Bootstrapper(this);
2481   handle_scope_implementer_ = new HandleScopeImplementer(this);
2482   load_stub_cache_ = new StubCache(this, Code::LOAD_IC);
2483   store_stub_cache_ = new StubCache(this, Code::STORE_IC);
2484   materialized_object_store_ = new MaterializedObjectStore(this);
2485   regexp_stack_ = new RegExpStack();
2486   regexp_stack_->isolate_ = this;
2487   date_cache_ = new DateCache();
2488   call_descriptor_data_ =
2489       new CallInterfaceDescriptorData[CallDescriptors::NUMBER_OF_DESCRIPTORS];
2490   access_compiler_data_ = new AccessCompilerData();
2491   cpu_profiler_ = new CpuProfiler(this);
2492   heap_profiler_ = new HeapProfiler(heap());
2493   interpreter_ = new interpreter::Interpreter(this);
2494   compiler_dispatcher_tracer_ = new CompilerDispatcherTracer(this);
2495 
2496   // Enable logging before setting up the heap
2497   logger_->SetUp(this);
2498 
2499   // Initialize other runtime facilities
2500 #if defined(USE_SIMULATOR)
2501 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_MIPS || \
2502     V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390
2503   Simulator::Initialize(this);
2504 #endif
2505 #endif
2506 
2507   code_aging_helper_ = new CodeAgingHelper(this);
2508 
2509   { // NOLINT
2510     // Ensure that the thread has a valid stack guard.  The v8::Locker object
2511     // will ensure this too, but we don't have to use lockers if we are only
2512     // using one thread.
2513     ExecutionAccess lock(this);
2514     stack_guard_.InitThread(lock);
2515   }
2516 
2517   // SetUp the object heap.
2518   DCHECK(!heap_.HasBeenSetUp());
2519   if (!heap_.SetUp()) {
2520     V8::FatalProcessOutOfMemory("heap setup");
2521     return false;
2522   }
2523 
2524 // Initialize the interface descriptors ahead of time.
2525 #define INTERFACE_DESCRIPTOR(V) \
2526   { V##Descriptor(this); }
2527   INTERFACE_DESCRIPTOR_LIST(INTERFACE_DESCRIPTOR)
2528 #undef INTERFACE_DESCRIPTOR
2529 
2530   deoptimizer_data_ = new DeoptimizerData(heap()->memory_allocator());
2531 
2532   const bool create_heap_objects = (des == NULL);
2533   if (create_heap_objects && !heap_.CreateHeapObjects()) {
2534     V8::FatalProcessOutOfMemory("heap object creation");
2535     return false;
2536   }
2537 
2538   if (create_heap_objects) {
2539     // Terminate the partial snapshot cache so we can iterate.
2540     partial_snapshot_cache_.Add(heap_.undefined_value());
2541   }
2542 
2543   InitializeThreadLocal();
2544 
2545   bootstrapper_->Initialize(create_heap_objects);
2546   builtins_.SetUp(this, create_heap_objects);
2547   if (create_heap_objects) {
2548     heap_.CreateFixedStubs();
2549   }
2550 
2551   if (FLAG_log_internal_timer_events) {
2552     set_event_logger(Logger::DefaultEventLoggerSentinel);
2553   }
2554 
2555   if (FLAG_trace_hydrogen || FLAG_trace_hydrogen_stubs || FLAG_trace_turbo ||
2556       FLAG_trace_turbo_graph) {
2557     PrintF("Concurrent recompilation has been disabled for tracing.\n");
2558   } else if (OptimizingCompileDispatcher::Enabled()) {
2559     optimizing_compile_dispatcher_ = new OptimizingCompileDispatcher(this);
2560   }
2561 
2562   // Initialize runtime profiler before deserialization, because collections may
2563   // occur, clearing/updating ICs.
2564   runtime_profiler_ = new RuntimeProfiler(this);
2565 
2566   // If we are deserializing, read the state into the now-empty heap.
2567   {
2568     AlwaysAllocateScope always_allocate(this);
2569 
2570     if (!create_heap_objects) {
2571       des->Deserialize(this);
2572     }
2573     load_stub_cache_->Initialize();
2574     store_stub_cache_->Initialize();
2575     interpreter_->Initialize();
2576 
2577     heap_.NotifyDeserializationComplete();
2578   }
2579 
2580   // Finish initialization of ThreadLocal after deserialization is done.
2581   clear_pending_exception();
2582   clear_pending_message();
2583   clear_scheduled_exception();
2584 
2585   // Deserializing may put strange things in the root array's copy of the
2586   // stack guard.
2587   heap_.SetStackLimits();
2588 
2589   // Quiet the heap NaN if needed on target platform.
2590   if (!create_heap_objects) Assembler::QuietNaN(heap_.nan_value());
2591 
2592   if (FLAG_trace_turbo) {
2593     // Create an empty file.
2594     std::ofstream(GetTurboCfgFileName().c_str(), std::ios_base::trunc);
2595   }
2596 
2597   CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, embedder_data_)),
2598            Internals::kIsolateEmbedderDataOffset);
2599   CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.roots_)),
2600            Internals::kIsolateRootsOffset);
2601   CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.external_memory_)),
2602            Internals::kExternalMemoryOffset);
2603   CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.external_memory_limit_)),
2604            Internals::kExternalMemoryLimitOffset);
2605 
2606   time_millis_at_init_ = heap_.MonotonicallyIncreasingTimeInMs();
2607 
2608   if (!create_heap_objects) {
2609     // Now that the heap is consistent, it's OK to generate the code for the
2610     // deopt entry table that might have been referred to by optimized code in
2611     // the snapshot.
2612     HandleScope scope(this);
2613     Deoptimizer::EnsureCodeForDeoptimizationEntry(
2614         this, Deoptimizer::LAZY,
2615         ExternalReferenceTable::kDeoptTableSerializeEntryCount - 1);
2616   }
2617 
2618   if (!serializer_enabled()) {
2619     // Ensure that all stubs which need to be generated ahead of time, but
2620     // cannot be serialized into the snapshot have been generated.
2621     HandleScope scope(this);
2622     CodeStub::GenerateFPStubs(this);
2623     StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(this);
2624     StubFailureTrampolineStub::GenerateAheadOfTime(this);
2625   }
2626 
2627   initialized_from_snapshot_ = (des != NULL);
2628 
2629   if (!FLAG_inline_new) heap_.DisableInlineAllocation();
2630 
2631   return true;
2632 }
2633 
2634 
2635 // Initialized lazily to allow early
2636 // v8::V8::SetAddHistogramSampleFunction calls.
2637 StatsTable* Isolate::stats_table() {
2638   if (stats_table_ == NULL) {
2639     stats_table_ = new StatsTable;
2640   }
2641   return stats_table_;
2642 }
2643 
2644 
2645 void Isolate::Enter() {
2646   Isolate* current_isolate = NULL;
2647   PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
2648   if (current_data != NULL) {
2649     current_isolate = current_data->isolate_;
2650     DCHECK(current_isolate != NULL);
2651     if (current_isolate == this) {
2652       DCHECK(Current() == this);
2653       DCHECK(entry_stack_ != NULL);
2654       DCHECK(entry_stack_->previous_thread_data == NULL ||
2655              entry_stack_->previous_thread_data->thread_id().Equals(
2656                  ThreadId::Current()));
2657       // Same thread re-enters the isolate, no need to re-init anything.
2658       entry_stack_->entry_count++;
2659       return;
2660     }
2661   }
2662 
2663   PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
2664   DCHECK(data != NULL);
2665   DCHECK(data->isolate_ == this);
2666 
2667   EntryStackItem* item = new EntryStackItem(current_data,
2668                                             current_isolate,
2669                                             entry_stack_);
2670   entry_stack_ = item;
2671 
2672   SetIsolateThreadLocals(this, data);
2673 
2674   // In case it's the first time some thread enters the isolate.
2675   set_thread_id(data->thread_id());
2676 }
2677 
2678 
2679 void Isolate::Exit() {
2680   DCHECK(entry_stack_ != NULL);
2681   DCHECK(entry_stack_->previous_thread_data == NULL ||
2682          entry_stack_->previous_thread_data->thread_id().Equals(
2683              ThreadId::Current()));
2684 
2685   if (--entry_stack_->entry_count > 0) return;
2686 
2687   DCHECK(CurrentPerIsolateThreadData() != NULL);
2688   DCHECK(CurrentPerIsolateThreadData()->isolate_ == this);
2689 
2690   // Pop the stack.
2691   EntryStackItem* item = entry_stack_;
2692   entry_stack_ = item->previous_item;
2693 
2694   PerIsolateThreadData* previous_thread_data = item->previous_thread_data;
2695   Isolate* previous_isolate = item->previous_isolate;
2696 
2697   delete item;
2698 
2699   // Reinit the current thread for the isolate it was running before this one.
2700   SetIsolateThreadLocals(previous_isolate, previous_thread_data);
2701 }
2702 
2703 
2704 void Isolate::LinkDeferredHandles(DeferredHandles* deferred) {
2705   deferred->next_ = deferred_handles_head_;
2706   if (deferred_handles_head_ != NULL) {
2707     deferred_handles_head_->previous_ = deferred;
2708   }
2709   deferred_handles_head_ = deferred;
2710 }
2711 
2712 
2713 void Isolate::UnlinkDeferredHandles(DeferredHandles* deferred) {
2714 #ifdef DEBUG
2715   // In debug mode assert that the linked list is well-formed.
2716   DeferredHandles* deferred_iterator = deferred;
2717   while (deferred_iterator->previous_ != NULL) {
2718     deferred_iterator = deferred_iterator->previous_;
2719   }
2720   DCHECK(deferred_handles_head_ == deferred_iterator);
2721 #endif
2722   if (deferred_handles_head_ == deferred) {
2723     deferred_handles_head_ = deferred_handles_head_->next_;
2724   }
2725   if (deferred->next_ != NULL) {
2726     deferred->next_->previous_ = deferred->previous_;
2727   }
2728   if (deferred->previous_ != NULL) {
2729     deferred->previous_->next_ = deferred->next_;
2730   }
2731 }
2732 
2733 
2734 void Isolate::DumpAndResetCompilationStats() {
2735   if (turbo_statistics() != nullptr) {
2736     DCHECK(FLAG_turbo_stats || FLAG_turbo_stats_nvp);
2737 
2738     OFStream os(stdout);
2739     if (FLAG_turbo_stats) {
2740       AsPrintableStatistics ps = {*turbo_statistics(), false};
2741       os << ps << std::endl;
2742     }
2743     if (FLAG_turbo_stats_nvp) {
2744       AsPrintableStatistics ps = {*turbo_statistics(), true};
2745       os << ps << std::endl;
2746     }
2747   }
2748   if (hstatistics() != nullptr) hstatistics()->Print();
2749   delete turbo_statistics_;
2750   turbo_statistics_ = nullptr;
2751   delete hstatistics_;
2752   hstatistics_ = nullptr;
2753   if (V8_UNLIKELY(FLAG_runtime_stats ==
2754                   v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE)) {
2755     OFStream os(stdout);
2756     counters()->runtime_call_stats()->Print(os);
2757     counters()->runtime_call_stats()->Reset();
2758   }
2759 }
2760 
2761 
2762 HStatistics* Isolate::GetHStatistics() {
2763   if (hstatistics() == NULL) set_hstatistics(new HStatistics());
2764   return hstatistics();
2765 }
2766 
2767 
2768 CompilationStatistics* Isolate::GetTurboStatistics() {
2769   if (turbo_statistics() == NULL)
2770     set_turbo_statistics(new CompilationStatistics());
2771   return turbo_statistics();
2772 }
2773 
2774 
2775 HTracer* Isolate::GetHTracer() {
2776   if (htracer() == NULL) set_htracer(new HTracer(id()));
2777   return htracer();
2778 }
2779 
2780 
2781 CodeTracer* Isolate::GetCodeTracer() {
2782   if (code_tracer() == NULL) set_code_tracer(new CodeTracer(id()));
2783   return code_tracer();
2784 }
2785 
2786 Map* Isolate::get_initial_js_array_map(ElementsKind kind) {
2787   if (IsFastElementsKind(kind)) {
2788     DisallowHeapAllocation no_gc;
2789     Object* const initial_js_array_map =
2790         context()->native_context()->get(Context::ArrayMapIndex(kind));
2791     if (!initial_js_array_map->IsUndefined(this)) {
2792       return Map::cast(initial_js_array_map);
2793     }
2794   }
2795   return nullptr;
2796 }
2797 
2798 
2799 bool Isolate::use_crankshaft() const {
2800   return FLAG_crankshaft &&
2801          !serializer_enabled_ &&
2802          CpuFeatures::SupportsCrankshaft();
2803 }
2804 
2805 bool Isolate::IsArrayOrObjectPrototype(Object* object) {
2806   Object* context = heap()->native_contexts_list();
2807   while (!context->IsUndefined(this)) {
2808     Context* current_context = Context::cast(context);
2809     if (current_context->initial_object_prototype() == object ||
2810         current_context->initial_array_prototype() == object) {
2811       return true;
2812     }
2813     context = current_context->next_context_link();
2814   }
2815   return false;
2816 }
2817 
2818 bool Isolate::IsInAnyContext(Object* object, uint32_t index) {
2819   DisallowHeapAllocation no_gc;
2820   Object* context = heap()->native_contexts_list();
2821   while (!context->IsUndefined(this)) {
2822     Context* current_context = Context::cast(context);
2823     if (current_context->get(index) == object) {
2824       return true;
2825     }
2826     context = current_context->next_context_link();
2827   }
2828   return false;
2829 }
2830 
2831 bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
2832   PropertyCell* no_elements_cell = heap()->array_protector();
2833   bool cell_reports_intact =
2834       no_elements_cell->value()->IsSmi() &&
2835       Smi::cast(no_elements_cell->value())->value() == kProtectorValid;
2836 
2837 #ifdef DEBUG
2838   Map* root_array_map =
2839       get_initial_js_array_map(GetInitialFastElementsKind());
2840   Context* native_context = context()->native_context();
2841   JSObject* initial_array_proto = JSObject::cast(
2842       native_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
2843   JSObject* initial_object_proto = JSObject::cast(
2844       native_context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX));
2845 
2846   if (root_array_map == NULL || initial_array_proto == initial_object_proto) {
2847     // We are in the bootstrapping process, and the entire check sequence
2848     // shouldn't be performed.
2849     return cell_reports_intact;
2850   }
2851 
2852   // Check that the array prototype hasn't been altered WRT empty elements.
2853   if (root_array_map->prototype() != initial_array_proto) {
2854     DCHECK_EQ(false, cell_reports_intact);
2855     return cell_reports_intact;
2856   }
2857 
2858   FixedArrayBase* elements = initial_array_proto->elements();
2859   if (elements != heap()->empty_fixed_array() &&
2860       elements != heap()->empty_slow_element_dictionary()) {
2861     DCHECK_EQ(false, cell_reports_intact);
2862     return cell_reports_intact;
2863   }
2864 
2865   // Check that the object prototype hasn't been altered WRT empty elements.
2866   PrototypeIterator iter(this, initial_array_proto);
2867   if (iter.IsAtEnd() || iter.GetCurrent() != initial_object_proto) {
2868     DCHECK_EQ(false, cell_reports_intact);
2869     return cell_reports_intact;
2870   }
2871 
2872   elements = initial_object_proto->elements();
2873   if (elements != heap()->empty_fixed_array() &&
2874       elements != heap()->empty_slow_element_dictionary()) {
2875     DCHECK_EQ(false, cell_reports_intact);
2876     return cell_reports_intact;
2877   }
2878 
2879   iter.Advance();
2880   if (!iter.IsAtEnd()) {
2881     DCHECK_EQ(false, cell_reports_intact);
2882     return cell_reports_intact;
2883   }
2884 
2885 #endif
2886 
2887   return cell_reports_intact;
2888 }
2889 
2890 bool Isolate::IsIsConcatSpreadableLookupChainIntact() {
2891   Cell* is_concat_spreadable_cell = heap()->is_concat_spreadable_protector();
2892   bool is_is_concat_spreadable_set =
2893       Smi::cast(is_concat_spreadable_cell->value())->value() ==
2894       kProtectorInvalid;
2895 #ifdef DEBUG
2896   Map* root_array_map = get_initial_js_array_map(GetInitialFastElementsKind());
2897   if (root_array_map == NULL) {
2898     // Ignore the value of is_concat_spreadable during bootstrap.
2899     return !is_is_concat_spreadable_set;
2900   }
2901   Handle<Object> array_prototype(array_function()->prototype(), this);
2902   Handle<Symbol> key = factory()->is_concat_spreadable_symbol();
2903   Handle<Object> value;
2904   LookupIterator it(array_prototype, key);
2905   if (it.IsFound() && !JSReceiver::GetDataProperty(&it)->IsUndefined(this)) {
2906     // TODO(cbruni): Currently we do not revert if we unset the
2907     // @@isConcatSpreadable property on Array.prototype or Object.prototype
2908     // hence the reverse implication doesn't hold.
2909     DCHECK(is_is_concat_spreadable_set);
2910     return false;
2911   }
2912 #endif  // DEBUG
2913 
2914   return !is_is_concat_spreadable_set;
2915 }
2916 
2917 bool Isolate::IsIsConcatSpreadableLookupChainIntact(JSReceiver* receiver) {
2918   if (!IsIsConcatSpreadableLookupChainIntact()) return false;
2919   return !receiver->HasProxyInPrototype(this);
2920 }
2921 
2922 void Isolate::UpdateArrayProtectorOnSetElement(Handle<JSObject> object) {
2923   DisallowHeapAllocation no_gc;
2924   if (!object->map()->is_prototype_map()) return;
2925   if (!IsFastArrayConstructorPrototypeChainIntact()) return;
2926   if (!IsArrayOrObjectPrototype(*object)) return;
2927   PropertyCell::SetValueWithInvalidation(
2928       factory()->array_protector(),
2929       handle(Smi::FromInt(kProtectorInvalid), this));
2930 }
2931 
2932 void Isolate::InvalidateHasInstanceProtector() {
2933   DCHECK(factory()->has_instance_protector()->value()->IsSmi());
2934   DCHECK(IsHasInstanceLookupChainIntact());
2935   PropertyCell::SetValueWithInvalidation(
2936       factory()->has_instance_protector(),
2937       handle(Smi::FromInt(kProtectorInvalid), this));
2938   DCHECK(!IsHasInstanceLookupChainIntact());
2939 }
2940 
2941 void Isolate::InvalidateIsConcatSpreadableProtector() {
2942   DCHECK(factory()->is_concat_spreadable_protector()->value()->IsSmi());
2943   DCHECK(IsIsConcatSpreadableLookupChainIntact());
2944   factory()->is_concat_spreadable_protector()->set_value(
2945       Smi::FromInt(kProtectorInvalid));
2946   DCHECK(!IsIsConcatSpreadableLookupChainIntact());
2947 }
2948 
2949 void Isolate::InvalidateArraySpeciesProtector() {
2950   DCHECK(factory()->species_protector()->value()->IsSmi());
2951   DCHECK(IsArraySpeciesLookupChainIntact());
2952   factory()->species_protector()->set_value(Smi::FromInt(kProtectorInvalid));
2953   DCHECK(!IsArraySpeciesLookupChainIntact());
2954 }
2955 
2956 void Isolate::InvalidateStringLengthOverflowProtector() {
2957   DCHECK(factory()->string_length_protector()->value()->IsSmi());
2958   DCHECK(IsStringLengthOverflowIntact());
2959   PropertyCell::SetValueWithInvalidation(
2960       factory()->string_length_protector(),
2961       handle(Smi::FromInt(kProtectorInvalid), this));
2962   DCHECK(!IsStringLengthOverflowIntact());
2963 }
2964 
2965 void Isolate::InvalidateArrayIteratorProtector() {
2966   DCHECK(factory()->array_iterator_protector()->value()->IsSmi());
2967   DCHECK(IsArrayIteratorLookupChainIntact());
2968   factory()->array_iterator_protector()->set_value(
2969       Smi::FromInt(kProtectorInvalid));
2970   DCHECK(!IsArrayIteratorLookupChainIntact());
2971 }
2972 
2973 bool Isolate::IsAnyInitialArrayPrototype(Handle<JSArray> array) {
2974   DisallowHeapAllocation no_gc;
2975   return IsInAnyContext(*array, Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
2976 }
2977 
2978 
2979 CallInterfaceDescriptorData* Isolate::call_descriptor_data(int index) {
2980   DCHECK(0 <= index && index < CallDescriptors::NUMBER_OF_DESCRIPTORS);
2981   return &call_descriptor_data_[index];
2982 }
2983 
2984 
2985 base::RandomNumberGenerator* Isolate::random_number_generator() {
2986   if (random_number_generator_ == NULL) {
2987     if (FLAG_random_seed != 0) {
2988       random_number_generator_ =
2989           new base::RandomNumberGenerator(FLAG_random_seed);
2990     } else {
2991       random_number_generator_ = new base::RandomNumberGenerator();
2992     }
2993   }
2994   return random_number_generator_;
2995 }
2996 
2997 int Isolate::GenerateIdentityHash(uint32_t mask) {
2998   int hash;
2999   int attempts = 0;
3000   do {
3001     hash = random_number_generator()->NextInt() & mask;
3002   } while (hash == 0 && attempts++ < 30);
3003   return hash != 0 ? hash : 1;
3004 }
3005 
3006 Object* Isolate::FindCodeObject(Address a) {
3007   return inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(a);
3008 }
3009 
3010 
3011 #ifdef DEBUG
3012 #define ISOLATE_FIELD_OFFSET(type, name, ignored)                       \
3013 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_);
3014 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
3015 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
3016 #undef ISOLATE_FIELD_OFFSET
3017 #endif
3018 
3019 
3020 Handle<JSObject> Isolate::SetUpSubregistry(Handle<JSObject> registry,
3021                                            Handle<Map> map, const char* cname) {
3022   Handle<String> name = factory()->InternalizeUtf8String(cname);
3023   Handle<JSObject> obj = factory()->NewJSObjectFromMap(map);
3024   JSObject::NormalizeProperties(obj, CLEAR_INOBJECT_PROPERTIES, 0,
3025                                 "SetupSymbolRegistry");
3026   JSObject::AddProperty(registry, name, obj, NONE);
3027   return obj;
3028 }
3029 
3030 
3031 Handle<JSObject> Isolate::GetSymbolRegistry() {
3032   if (heap()->symbol_registry()->IsSmi()) {
3033     Handle<Map> map = factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
3034     Handle<JSObject> registry = factory()->NewJSObjectFromMap(map);
3035     heap()->set_symbol_registry(*registry);
3036 
3037     SetUpSubregistry(registry, map, "for");
3038     SetUpSubregistry(registry, map, "for_api");
3039     SetUpSubregistry(registry, map, "keyFor");
3040     SetUpSubregistry(registry, map, "private_api");
3041   }
3042   return Handle<JSObject>::cast(factory()->symbol_registry());
3043 }
3044 
3045 
3046 void Isolate::AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback) {
3047   for (int i = 0; i < before_call_entered_callbacks_.length(); i++) {
3048     if (callback == before_call_entered_callbacks_.at(i)) return;
3049   }
3050   before_call_entered_callbacks_.Add(callback);
3051 }
3052 
3053 
3054 void Isolate::RemoveBeforeCallEnteredCallback(
3055     BeforeCallEnteredCallback callback) {
3056   for (int i = 0; i < before_call_entered_callbacks_.length(); i++) {
3057     if (callback == before_call_entered_callbacks_.at(i)) {
3058       before_call_entered_callbacks_.Remove(i);
3059     }
3060   }
3061 }
3062 
3063 
3064 void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
3065   for (int i = 0; i < call_completed_callbacks_.length(); i++) {
3066     if (callback == call_completed_callbacks_.at(i)) return;
3067   }
3068   call_completed_callbacks_.Add(callback);
3069 }
3070 
3071 
3072 void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
3073   for (int i = 0; i < call_completed_callbacks_.length(); i++) {
3074     if (callback == call_completed_callbacks_.at(i)) {
3075       call_completed_callbacks_.Remove(i);
3076     }
3077   }
3078 }
3079 
3080 
3081 void Isolate::FireCallCompletedCallback() {
3082   if (!handle_scope_implementer()->CallDepthIsZero()) return;
3083 
3084   bool run_microtasks =
3085       pending_microtask_count() &&
3086       !handle_scope_implementer()->HasMicrotasksSuppressions() &&
3087       handle_scope_implementer()->microtasks_policy() ==
3088           v8::MicrotasksPolicy::kAuto;
3089 
3090   if (run_microtasks) RunMicrotasks();
3091   // Prevent stepping from spilling into the next call made by the embedder.
3092   if (debug()->is_active()) debug()->ClearStepping();
3093 
3094   if (call_completed_callbacks_.is_empty()) return;
3095   // Fire callbacks.  Increase call depth to prevent recursive callbacks.
3096   v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this);
3097   v8::Isolate::SuppressMicrotaskExecutionScope suppress(isolate);
3098   for (int i = 0; i < call_completed_callbacks_.length(); i++) {
3099     call_completed_callbacks_.at(i)(isolate);
3100   }
3101 }
3102 
3103 
3104 void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
3105   promise_reject_callback_ = callback;
3106 }
3107 
3108 
3109 void Isolate::ReportPromiseReject(Handle<JSObject> promise,
3110                                   Handle<Object> value,
3111                                   v8::PromiseRejectEvent event) {
3112   if (promise_reject_callback_ == NULL) return;
3113   Handle<JSArray> stack_trace;
3114   if (event == v8::kPromiseRejectWithNoHandler && value->IsJSObject()) {
3115     stack_trace = GetDetailedStackTrace(Handle<JSObject>::cast(value));
3116   }
3117   promise_reject_callback_(v8::PromiseRejectMessage(
3118       v8::Utils::PromiseToLocal(promise), event, v8::Utils::ToLocal(value),
3119       v8::Utils::StackTraceToLocal(stack_trace)));
3120 }
3121 
3122 namespace {
3123 class PromiseDebugEventScope {
3124  public:
3125   PromiseDebugEventScope(Isolate* isolate, Object* id, Object* name)
3126       : isolate_(isolate),
3127         id_(id, isolate_),
3128         name_(name, isolate_),
3129         is_debug_active_(isolate_->debug()->is_active() && id_->IsNumber() &&
3130                          name_->IsString()) {
3131     if (is_debug_active_) {
3132       isolate_->debug()->OnAsyncTaskEvent(
3133           isolate_->factory()->will_handle_string(), id_,
3134           Handle<String>::cast(name_));
3135     }
3136   }
3137 
3138   ~PromiseDebugEventScope() {
3139     if (is_debug_active_) {
3140       isolate_->debug()->OnAsyncTaskEvent(
3141           isolate_->factory()->did_handle_string(), id_,
3142           Handle<String>::cast(name_));
3143     }
3144   }
3145 
3146  private:
3147   Isolate* isolate_;
3148   Handle<Object> id_;
3149   Handle<Object> name_;
3150   bool is_debug_active_;
3151 };
3152 }  // namespace
3153 
3154 void Isolate::PromiseReactionJob(Handle<PromiseReactionJobInfo> info,
3155                                  MaybeHandle<Object>* result,
3156                                  MaybeHandle<Object>* maybe_exception) {
3157   PromiseDebugEventScope helper(this, info->debug_id(), info->debug_name());
3158 
3159   Handle<Object> value(info->value(), this);
3160   Handle<Object> tasks(info->tasks(), this);
3161   Handle<JSFunction> promise_handle_fn = promise_handle();
3162   Handle<Object> undefined = factory()->undefined_value();
3163 
3164   // If tasks is an array we have multiple onFulfilled/onRejected callbacks
3165   // associated with the promise. The deferred object for each callback
3166   // is attached to this array as well.
3167   // Otherwise, there is a single callback and the deferred object is attached
3168   // directly to PromiseReactionJobInfo.
3169   if (tasks->IsJSArray()) {
3170     Handle<JSArray> array = Handle<JSArray>::cast(tasks);
3171     DCHECK(array->length()->IsSmi());
3172     int length = Smi::cast(array->length())->value();
3173     ElementsAccessor* accessor = array->GetElementsAccessor();
3174     DCHECK(length % 2 == 0);
3175     for (int i = 0; i < length; i += 2) {
3176       DCHECK(accessor->HasElement(array, i));
3177       DCHECK(accessor->HasElement(array, i + 1));
3178       Handle<Object> argv[] = {value, accessor->Get(array, i),
3179                                accessor->Get(array, i + 1)};
3180       *result = Execution::TryCall(this, promise_handle_fn, undefined,
3181                                    arraysize(argv), argv, maybe_exception);
3182       // If execution is terminating, just bail out.
3183       if (result->is_null() && maybe_exception->is_null()) {
3184         return;
3185       }
3186     }
3187   } else {
3188     Handle<Object> deferred(info->deferred(), this);
3189     Handle<Object> argv[] = {value, tasks, deferred};
3190     *result = Execution::TryCall(this, promise_handle_fn, undefined,
3191                                  arraysize(argv), argv, maybe_exception);
3192   }
3193 }
3194 
3195 void Isolate::PromiseResolveThenableJob(
3196     Handle<PromiseResolveThenableJobInfo> info, MaybeHandle<Object>* result,
3197     MaybeHandle<Object>* maybe_exception) {
3198   PromiseDebugEventScope helper(this, info->debug_id(), info->debug_name());
3199 
3200   Handle<JSReceiver> thenable(info->thenable(), this);
3201   Handle<JSFunction> resolve(info->resolve(), this);
3202   Handle<JSFunction> reject(info->reject(), this);
3203   Handle<JSReceiver> then(info->then(), this);
3204   Handle<Object> argv[] = {resolve, reject};
3205   *result = Execution::TryCall(this, then, thenable, arraysize(argv), argv,
3206                                maybe_exception);
3207 
3208   Handle<Object> reason;
3209   if (maybe_exception->ToHandle(&reason)) {
3210     DCHECK(result->is_null());
3211     Handle<Object> reason_arg[] = {reason};
3212     *result =
3213         Execution::TryCall(this, reject, factory()->undefined_value(),
3214                            arraysize(reason_arg), reason_arg, maybe_exception);
3215   }
3216 }
3217 
3218 void Isolate::EnqueueMicrotask(Handle<Object> microtask) {
3219   DCHECK(microtask->IsJSFunction() || microtask->IsCallHandlerInfo() ||
3220          microtask->IsPromiseResolveThenableJobInfo() ||
3221          microtask->IsPromiseReactionJobInfo());
3222   Handle<FixedArray> queue(heap()->microtask_queue(), this);
3223   int num_tasks = pending_microtask_count();
3224   DCHECK(num_tasks <= queue->length());
3225   if (num_tasks == 0) {
3226     queue = factory()->NewFixedArray(8);
3227     heap()->set_microtask_queue(*queue);
3228   } else if (num_tasks == queue->length()) {
3229     queue = factory()->CopyFixedArrayAndGrow(queue, num_tasks);
3230     heap()->set_microtask_queue(*queue);
3231   }
3232   DCHECK(queue->get(num_tasks)->IsUndefined(this));
3233   queue->set(num_tasks, *microtask);
3234   set_pending_microtask_count(num_tasks + 1);
3235 }
3236 
3237 
3238 void Isolate::RunMicrotasks() {
3239   // Increase call depth to prevent recursive callbacks.
3240   v8::Isolate::SuppressMicrotaskExecutionScope suppress(
3241       reinterpret_cast<v8::Isolate*>(this));
3242   is_running_microtasks_ = true;
3243   RunMicrotasksInternal();
3244   is_running_microtasks_ = false;
3245   FireMicrotasksCompletedCallback();
3246 }
3247 
3248 
3249 void Isolate::RunMicrotasksInternal() {
3250   if (!pending_microtask_count()) return;
3251   TRACE_EVENT0("v8.execute", "RunMicrotasks");
3252   while (pending_microtask_count() > 0) {
3253     HandleScope scope(this);
3254     int num_tasks = pending_microtask_count();
3255     Handle<FixedArray> queue(heap()->microtask_queue(), this);
3256     DCHECK(num_tasks <= queue->length());
3257     set_pending_microtask_count(0);
3258     heap()->set_microtask_queue(heap()->empty_fixed_array());
3259 
3260     Isolate* isolate = this;
3261     FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < num_tasks, i++, {
3262       Handle<Object> microtask(queue->get(i), this);
3263 
3264       if (microtask->IsCallHandlerInfo()) {
3265         Handle<CallHandlerInfo> callback_info =
3266             Handle<CallHandlerInfo>::cast(microtask);
3267         v8::MicrotaskCallback callback =
3268             v8::ToCData<v8::MicrotaskCallback>(callback_info->callback());
3269         void* data = v8::ToCData<void*>(callback_info->data());
3270         callback(data);
3271       } else {
3272         SaveContext save(this);
3273         Context* context;
3274         if (microtask->IsJSFunction()) {
3275           context = Handle<JSFunction>::cast(microtask)->context();
3276         } else if (microtask->IsPromiseResolveThenableJobInfo()) {
3277           context =
3278               Handle<PromiseResolveThenableJobInfo>::cast(microtask)->context();
3279         } else {
3280           context = Handle<PromiseReactionJobInfo>::cast(microtask)->context();
3281         }
3282 
3283         set_context(context->native_context());
3284         handle_scope_implementer_->EnterMicrotaskContext(
3285             Handle<Context>(context, this));
3286 
3287         MaybeHandle<Object> result;
3288         MaybeHandle<Object> maybe_exception;
3289 
3290         if (microtask->IsJSFunction()) {
3291           Handle<JSFunction> microtask_function =
3292               Handle<JSFunction>::cast(microtask);
3293           result = Execution::TryCall(this, microtask_function,
3294                                       factory()->undefined_value(), 0, NULL,
3295                                       &maybe_exception);
3296         } else if (microtask->IsPromiseResolveThenableJobInfo()) {
3297           PromiseResolveThenableJob(
3298               Handle<PromiseResolveThenableJobInfo>::cast(microtask), &result,
3299               &maybe_exception);
3300         } else {
3301           PromiseReactionJob(Handle<PromiseReactionJobInfo>::cast(microtask),
3302                              &result, &maybe_exception);
3303         }
3304 
3305         handle_scope_implementer_->LeaveMicrotaskContext();
3306 
3307         // If execution is terminating, just bail out.
3308         if (result.is_null() && maybe_exception.is_null()) {
3309           // Clear out any remaining callbacks in the queue.
3310           heap()->set_microtask_queue(heap()->empty_fixed_array());
3311           set_pending_microtask_count(0);
3312           return;
3313         }
3314       }
3315     });
3316   }
3317 }
3318 
3319 
3320 void Isolate::AddMicrotasksCompletedCallback(
3321     MicrotasksCompletedCallback callback) {
3322   for (int i = 0; i < microtasks_completed_callbacks_.length(); i++) {
3323     if (callback == microtasks_completed_callbacks_.at(i)) return;
3324   }
3325   microtasks_completed_callbacks_.Add(callback);
3326 }
3327 
3328 
3329 void Isolate::RemoveMicrotasksCompletedCallback(
3330     MicrotasksCompletedCallback callback) {
3331   for (int i = 0; i < microtasks_completed_callbacks_.length(); i++) {
3332     if (callback == microtasks_completed_callbacks_.at(i)) {
3333       microtasks_completed_callbacks_.Remove(i);
3334     }
3335   }
3336 }
3337 
3338 
3339 void Isolate::FireMicrotasksCompletedCallback() {
3340   for (int i = 0; i < microtasks_completed_callbacks_.length(); i++) {
3341     microtasks_completed_callbacks_.at(i)(reinterpret_cast<v8::Isolate*>(this));
3342   }
3343 }
3344 
3345 
3346 void Isolate::SetUseCounterCallback(v8::Isolate::UseCounterCallback callback) {
3347   DCHECK(!use_counter_callback_);
3348   use_counter_callback_ = callback;
3349 }
3350 
3351 
3352 void Isolate::CountUsage(v8::Isolate::UseCounterFeature feature) {
3353   // The counter callback may cause the embedder to call into V8, which is not
3354   // generally possible during GC.
3355   if (heap_.gc_state() == Heap::NOT_IN_GC) {
3356     if (use_counter_callback_) {
3357       HandleScope handle_scope(this);
3358       use_counter_callback_(reinterpret_cast<v8::Isolate*>(this), feature);
3359     }
3360   } else {
3361     heap_.IncrementDeferredCount(feature);
3362   }
3363 }
3364 
3365 
3366 BasicBlockProfiler* Isolate::GetOrCreateBasicBlockProfiler() {
3367   if (basic_block_profiler_ == NULL) {
3368     basic_block_profiler_ = new BasicBlockProfiler();
3369   }
3370   return basic_block_profiler_;
3371 }
3372 
3373 
3374 std::string Isolate::GetTurboCfgFileName() {
3375   if (FLAG_trace_turbo_cfg_file == NULL) {
3376     std::ostringstream os;
3377     os << "turbo-" << base::OS::GetCurrentProcessId() << "-" << id() << ".cfg";
3378     return os.str();
3379   } else {
3380     return FLAG_trace_turbo_cfg_file;
3381   }
3382 }
3383 
3384 void Isolate::SetTailCallEliminationEnabled(bool enabled) {
3385   if (is_tail_call_elimination_enabled_ == enabled) return;
3386   is_tail_call_elimination_enabled_ = enabled;
3387   // TODO(ishell): Introduce DependencyGroup::kTailCallChangedGroup to
3388   // deoptimize only those functions that are affected by the change of this
3389   // flag.
3390   internal::Deoptimizer::DeoptimizeAll(this);
3391 }
3392 
3393 // Heap::detached_contexts tracks detached contexts as pairs
3394 // (number of GC since the context was detached, the context).
3395 void Isolate::AddDetachedContext(Handle<Context> context) {
3396   HandleScope scope(this);
3397   Handle<WeakCell> cell = factory()->NewWeakCell(context);
3398   Handle<FixedArray> detached_contexts = factory()->detached_contexts();
3399   int length = detached_contexts->length();
3400   detached_contexts = factory()->CopyFixedArrayAndGrow(detached_contexts, 2);
3401   detached_contexts->set(length, Smi::kZero);
3402   detached_contexts->set(length + 1, *cell);
3403   heap()->set_detached_contexts(*detached_contexts);
3404 }
3405 
3406 
3407 void Isolate::CheckDetachedContextsAfterGC() {
3408   HandleScope scope(this);
3409   Handle<FixedArray> detached_contexts = factory()->detached_contexts();
3410   int length = detached_contexts->length();
3411   if (length == 0) return;
3412   int new_length = 0;
3413   for (int i = 0; i < length; i += 2) {
3414     int mark_sweeps = Smi::cast(detached_contexts->get(i))->value();
3415     DCHECK(detached_contexts->get(i + 1)->IsWeakCell());
3416     WeakCell* cell = WeakCell::cast(detached_contexts->get(i + 1));
3417     if (!cell->cleared()) {
3418       detached_contexts->set(new_length, Smi::FromInt(mark_sweeps + 1));
3419       detached_contexts->set(new_length + 1, cell);
3420       new_length += 2;
3421     }
3422     counters()->detached_context_age_in_gc()->AddSample(mark_sweeps + 1);
3423   }
3424   if (FLAG_trace_detached_contexts) {
3425     PrintF("%d detached contexts are collected out of %d\n",
3426            length - new_length, length);
3427     for (int i = 0; i < new_length; i += 2) {
3428       int mark_sweeps = Smi::cast(detached_contexts->get(i))->value();
3429       DCHECK(detached_contexts->get(i + 1)->IsWeakCell());
3430       WeakCell* cell = WeakCell::cast(detached_contexts->get(i + 1));
3431       if (mark_sweeps > 3) {
3432         PrintF("detached context %p\n survived %d GCs (leak?)\n",
3433                static_cast<void*>(cell->value()), mark_sweeps);
3434       }
3435     }
3436   }
3437   if (new_length == 0) {
3438     heap()->set_detached_contexts(heap()->empty_fixed_array());
3439   } else if (new_length < length) {
3440     heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
3441         *detached_contexts, length - new_length);
3442   }
3443 }
3444 
3445 void Isolate::SetRAILMode(RAILMode rail_mode) {
3446   rail_mode_.SetValue(rail_mode);
3447   if (FLAG_trace_rail) {
3448     PrintIsolate(this, "RAIL mode: %s\n", RAILModeName(rail_mode));
3449   }
3450 }
3451 
3452 void Isolate::IsolateInBackgroundNotification() {
3453   is_isolate_in_background_ = true;
3454   heap()->ActivateMemoryReducerIfNeeded();
3455 }
3456 
3457 void Isolate::IsolateInForegroundNotification() {
3458   is_isolate_in_background_ = false;
3459 }
3460 
3461 void Isolate::PrintWithTimestamp(const char* format, ...) {
3462   base::OS::Print("[%d:%p] %8.0f ms: ", base::OS::GetCurrentProcessId(),
3463                   static_cast<void*>(this), time_millis_since_init());
3464   va_list arguments;
3465   va_start(arguments, format);
3466   base::OS::VPrint(format, arguments);
3467   va_end(arguments);
3468 }
3469 
3470 bool StackLimitCheck::JsHasOverflowed(uintptr_t gap) const {
3471   StackGuard* stack_guard = isolate_->stack_guard();
3472 #ifdef USE_SIMULATOR
3473   // The simulator uses a separate JS stack.
3474   Address jssp_address = Simulator::current(isolate_)->get_sp();
3475   uintptr_t jssp = reinterpret_cast<uintptr_t>(jssp_address);
3476   if (jssp - gap < stack_guard->real_jslimit()) return true;
3477 #endif  // USE_SIMULATOR
3478   return GetCurrentStackPosition() - gap < stack_guard->real_climit();
3479 }
3480 
3481 SaveContext::SaveContext(Isolate* isolate)
3482     : isolate_(isolate), prev_(isolate->save_context()) {
3483   if (isolate->context() != NULL) {
3484     context_ = Handle<Context>(isolate->context());
3485   }
3486   isolate->set_save_context(this);
3487 
3488   c_entry_fp_ = isolate->c_entry_fp(isolate->thread_local_top());
3489 }
3490 
3491 SaveContext::~SaveContext() {
3492   isolate_->set_context(context_.is_null() ? NULL : *context_);
3493   isolate_->set_save_context(prev_);
3494 }
3495 
3496 #ifdef DEBUG
3497 AssertNoContextChange::AssertNoContextChange(Isolate* isolate)
3498     : isolate_(isolate), context_(isolate->context(), isolate) {}
3499 #endif  // DEBUG
3500 
3501 
3502 bool PostponeInterruptsScope::Intercept(StackGuard::InterruptFlag flag) {
3503   // First check whether the previous scope intercepts.
3504   if (prev_ && prev_->Intercept(flag)) return true;
3505   // Then check whether this scope intercepts.
3506   if ((flag & intercept_mask_)) {
3507     intercepted_flags_ |= flag;
3508     return true;
3509   }
3510   return false;
3511 }
3512 
3513 }  // namespace internal
3514 }  // namespace v8
3515