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