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