• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/isolate.h"
6 
7 #include <stdlib.h>
8 
9 #include <fstream>  // NOLINT(readability/streams)
10 #include <sstream>
11 
12 #include "src/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 
AllocateThreadId()49 int ThreadId::AllocateThreadId() {
50   int new_id = base::NoBarrier_AtomicIncrement(&highest_thread_id_, 1);
51   return new_id;
52 }
53 
54 
GetCurrentThreadId()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 
ThreadLocalTop()65 ThreadLocalTop::ThreadLocalTop() {
66   InitializeInternal();
67 }
68 
69 
InitializeInternal()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 
Initialize()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 
Free()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*
FindOrAllocatePerThreadDataForThisThread()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 
DiscardPerThreadDataForThisThread()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 
FindPerThreadDataForThisThread()155 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() {
156   ThreadId thread_id = ThreadId::Current();
157   return FindPerThreadDataForThread(thread_id);
158 }
159 
160 
FindPerThreadDataForThread(ThreadId thread_id)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 
InitializeOncePerProcess()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 
get_address_from_id(Isolate::AddressId id)185 Address Isolate::get_address_from_id(Isolate::AddressId id) {
186   return isolate_addresses_[id];
187 }
188 
189 
Iterate(ObjectVisitor * v,char * thread_storage)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 
IterateThread(ThreadVisitor * v,char * t)197 void Isolate::IterateThread(ThreadVisitor* v, char* t) {
198   ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
199   v->VisitThread(this, thread);
200 }
201 
202 
Iterate(ObjectVisitor * v,ThreadLocalTop * thread)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 
Iterate(ObjectVisitor * v)224 void Isolate::Iterate(ObjectVisitor* v) {
225   ThreadLocalTop* current_t = thread_local_top();
226   Iterate(v, current_t);
227 }
228 
229 
IterateDeferredHandles(ObjectVisitor * visitor)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
IsDeferredHandle(Object ** handle)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 
RegisterTryCatchHandler(v8::TryCatch * that)262 void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) {
263   thread_local_top()->set_try_catch_handler(that);
264 }
265 
266 
UnregisterTryCatchHandler(v8::TryCatch * that)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 
StackTraceString()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 
PushStackTraceAndDie(unsigned int magic,void * ptr1,void * ptr2,unsigned int magic2)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.
IsVisibleInStackTrace(JSFunction * fun,Object * caller,bool * seen_caller)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 
MaybeGrow(Isolate * isolate,Handle<FixedArray> elements,int cur_position,int new_size)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 
CaptureSimpleStackTrace(Handle<JSReceiver> error_object,Handle<Object> caller)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 
CaptureAndSetDetailedStackTrace(Handle<JSReceiver> error_object)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 
CaptureAndSetSimpleStackTrace(Handle<JSReceiver> error_object,Handle<Object> caller)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 
GetDetailedStackTrace(Handle<JSObject> error_object)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:
CaptureStackTraceHelper(Isolate * isolate,StackTrace::StackTraceOptions options)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 
NewStackFrameObject(FrameSummary & summ)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 
NewStackFrameObject(Handle<JSFunction> fun,int position,bool is_constructor)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 
NewStackFrameObject(WasmFrame * frame)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:
factory()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 
PositionFromStackTrace(Handle<FixedArray> elements,int index)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 
GetDetailedFromSimpleStackTrace(Handle<JSObject> error_object)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 
CaptureCurrentStackTrace(int frame_limit,StackTrace::StackTraceOptions options)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 
PrintStack(FILE * out,PrintStackMode mode)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 
PrintFrames(Isolate * isolate,StringStream * accumulator,StackFrame::PrintMode mode)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 
PrintStack(StringStream * accumulator,PrintStackMode mode)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 
SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback)799 void Isolate::SetFailedAccessCheckCallback(
800     v8::FailedAccessCheckCallback callback) {
801   thread_local_top()->failed_access_check_callback_ = callback;
802 }
803 
804 
ReportFailedAccessCheck(Handle<JSObject> receiver)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 
MayAccess(Handle<Context> accessing_context,Handle<JSObject> receiver)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 
StackOverflow()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 
TerminateExecution()912 Object* Isolate::TerminateExecution() {
913   return Throw(heap_.termination_exception(), nullptr);
914 }
915 
916 
CancelTerminateExecution()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 
RequestInterrupt(InterruptCallback callback,void * data)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 
InvokeApiInterruptCallbacks()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 
ReportBootstrappingException(Handle<Object> exception,MessageLocation * location)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 
Throw(Object * exception,MessageLocation * location)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 
ReThrow(Object * exception)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 
UnwindAndFindHandler()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 
PredictExceptionCatcher()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 
RemoveMaterializedObjectsOnUnwind(StackFrame * frame)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 
ThrowIllegalOperation()1267 Object* Isolate::ThrowIllegalOperation() {
1268   if (FLAG_stack_trace_on_illegal) PrintStack(stdout);
1269   return Throw(heap()->illegal_access_string());
1270 }
1271 
1272 
ScheduleThrow(Object * exception)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 
RestorePendingMessageFromTryCatch(v8::TryCatch * handler)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 
CancelScheduledExceptionFromTryCatch(v8::TryCatch * handler)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 
PromoteScheduledException()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 
PrintCurrentStackTrace(FILE * out)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 
ComputeLocation(MessageLocation * target)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 
ComputeLocationFromException(MessageLocation * target,Handle<Object> exception)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 
ComputeLocationFromStackTrace(MessageLocation * target,Handle<Object> exception)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 
CreateMessage(Handle<Object> exception,MessageLocation * location)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 
IsJavaScriptHandlerOnTop(Object * exception)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 
IsExternalHandlerOnTop(Object * exception)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 
ReportPendingMessages()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 
GetMessageLocation()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 
OptionalRescheduleException(bool is_bottom_call)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 
PushPromise(Handle<JSObject> promise,Handle<JSFunction> function)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 
PopPromise()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 
GetPromiseOnStackOnThrow()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 
SetCaptureStackTraceForUncaughtExceptions(bool capture,int frame_limit,StackTrace::StackTraceOptions options)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 
SetAbortOnUncaughtExceptionCallback(v8::Isolate::AbortOnUncaughtExceptionCallback callback)1683 void Isolate::SetAbortOnUncaughtExceptionCallback(
1684     v8::Isolate::AbortOnUncaughtExceptionCallback callback) {
1685   abort_on_uncaught_exception_callback_ = callback;
1686 }
1687 
1688 
native_context()1689 Handle<Context> Isolate::native_context() {
1690   return handle(context()->native_context());
1691 }
1692 
1693 
GetCallingNativeContext()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 
ArchiveThread(char * to)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 
RestoreThread(char * from)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 
ThreadDataTable()1738 Isolate::ThreadDataTable::ThreadDataTable()
1739     : list_(NULL) {
1740 }
1741 
1742 
~ThreadDataTable()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 
~PerIsolateThreadData()1751 Isolate::PerIsolateThreadData::~PerIsolateThreadData() {
1752 #if defined(USE_SIMULATOR)
1753   delete simulator_;
1754 #endif
1755 }
1756 
1757 
1758 Isolate::PerIsolateThreadData*
Lookup(Isolate * isolate,ThreadId thread_id)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 
Insert(Isolate::PerIsolateThreadData * data)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 
Remove(PerIsolateThreadData * data)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 
RemoveAllThreads(Isolate * isolate)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 
Isolate(bool enable_serializer)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 
TearDown()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 
GlobalTearDown()1935 void Isolate::GlobalTearDown() {
1936   delete thread_data_table_;
1937   thread_data_table_ = NULL;
1938 }
1939 
1940 
ClearSerializerData()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 
Deinit()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 
SetIsolateThreadLocals(Isolate * isolate,PerIsolateThreadData * data)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 
~Isolate()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 
InitializeThreadLocal()2111 void Isolate::InitializeThreadLocal() {
2112   thread_local_top_.isolate_ = this;
2113   thread_local_top_.Initialize();
2114 }
2115 
2116 
PropagatePendingExceptionToExternalTryCatch()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 
InitializeLoggingAndCounters()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 
Init(Deserializer * des)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.
stats_table()2338 StatsTable* Isolate::stats_table() {
2339   if (stats_table_ == NULL) {
2340     stats_table_ = new StatsTable;
2341   }
2342   return stats_table_;
2343 }
2344 
2345 
Enter()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 
Exit()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 
LinkDeferredHandles(DeferredHandles * deferred)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 
UnlinkDeferredHandles(DeferredHandles * deferred)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 
DumpAndResetCompilationStats()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 
GetHStatistics()2462 HStatistics* Isolate::GetHStatistics() {
2463   if (hstatistics() == NULL) set_hstatistics(new HStatistics());
2464   return hstatistics();
2465 }
2466 
2467 
GetTurboStatistics()2468 CompilationStatistics* Isolate::GetTurboStatistics() {
2469   if (turbo_statistics() == NULL)
2470     set_turbo_statistics(new CompilationStatistics());
2471   return turbo_statistics();
2472 }
2473 
2474 
GetHTracer()2475 HTracer* Isolate::GetHTracer() {
2476   if (htracer() == NULL) set_htracer(new HTracer(id()));
2477   return htracer();
2478 }
2479 
2480 
GetCodeTracer()2481 CodeTracer* Isolate::GetCodeTracer() {
2482   if (code_tracer() == NULL) set_code_tracer(new CodeTracer(id()));
2483   return code_tracer();
2484 }
2485 
get_initial_js_array_map(ElementsKind kind)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 
use_crankshaft() const2499 bool Isolate::use_crankshaft() const {
2500   return FLAG_crankshaft &&
2501          !serializer_enabled_ &&
2502          CpuFeatures::SupportsCrankshaft();
2503 }
2504 
IsArrayOrObjectPrototype(Object * object)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 
IsInAnyContext(Object * object,uint32_t index)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 
IsFastArrayConstructorPrototypeChainIntact()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 
IsIsConcatSpreadableLookupChainIntact()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 
UpdateArrayProtectorOnSetElement(Handle<JSObject> object)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 
InvalidateHasInstanceProtector()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 
InvalidateIsConcatSpreadableProtector()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 
InvalidateArraySpeciesProtector()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 
IsAnyInitialArrayPrototype(Handle<JSArray> array)2652 bool Isolate::IsAnyInitialArrayPrototype(Handle<JSArray> array) {
2653   DisallowHeapAllocation no_gc;
2654   return IsInAnyContext(*array, Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
2655 }
2656 
2657 
call_descriptor_data(int index)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 
random_number_generator()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 
FindCodeObject(Address a)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)
ISOLATE_INIT_ARRAY_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 
GetSymbolRegistry()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 
AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback)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 
RemoveBeforeCallEnteredCallback(BeforeCallEnteredCallback callback)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 
FireBeforeCallEnteredCallback()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 
AddCallCompletedCallback(CallCompletedCallback callback)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 
RemoveCallCompletedCallback(CallCompletedCallback callback)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 
FireCallCompletedCallback()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 
SetPromiseRejectCallback(PromiseRejectCallback callback)2782 void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
2783   promise_reject_callback_ = callback;
2784 }
2785 
2786 
ReportPromiseReject(Handle<JSObject> promise,Handle<Object> value,v8::PromiseRejectEvent event)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 
EnqueueMicrotask(Handle<Object> microtask)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 
RunMicrotasks()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 
RunMicrotasksInternal()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 
AddMicrotasksCompletedCallback(MicrotasksCompletedCallback callback)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 
RemoveMicrotasksCompletedCallback(MicrotasksCompletedCallback callback)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 
FireMicrotasksCompletedCallback()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 
SetUseCounterCallback(v8::Isolate::UseCounterCallback callback)2898 void Isolate::SetUseCounterCallback(v8::Isolate::UseCounterCallback callback) {
2899   DCHECK(!use_counter_callback_);
2900   use_counter_callback_ = callback;
2901 }
2902 
2903 
CountUsage(v8::Isolate::UseCounterFeature feature)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 
GetOrCreateBasicBlockProfiler()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 
GetTurboCfgFileName()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 
SetTailCallEliminationEnabled(bool enabled)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).
AddDetachedContext(Handle<Context> 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 
CheckDetachedContextsAfterGC()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 
SetRAILMode(RAILMode rail_mode)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 
JsHasOverflowed(uintptr_t gap) const3004 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 
SaveContext(Isolate * isolate)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 
~SaveContext()3027 SaveContext::~SaveContext() {
3028   isolate_->set_context(context_.is_null() ? NULL : *context_);
3029   isolate_->set_save_context(prev_);
3030 }
3031 
3032 
3033 #ifdef DEBUG
AssertNoContextChange(Isolate * isolate)3034 AssertNoContextChange::AssertNoContextChange(Isolate* isolate)
3035     : isolate_(isolate), context_(isolate->context(), isolate) {}
3036 #endif  // DEBUG
3037 
3038 
Intercept(StackGuard::InterruptFlag flag)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