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