• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stdlib.h>
6 
7 #include "src/v8.h"
8 
9 #include "src/ast.h"
10 #include "src/base/platform/platform.h"
11 #include "src/base/sys-info.h"
12 #include "src/base/utils/random-number-generator.h"
13 #include "src/bootstrapper.h"
14 #include "src/codegen.h"
15 #include "src/compilation-cache.h"
16 #include "src/cpu-profiler.h"
17 #include "src/debug.h"
18 #include "src/deoptimizer.h"
19 #include "src/heap/spaces.h"
20 #include "src/heap/sweeper-thread.h"
21 #include "src/heap-profiler.h"
22 #include "src/hydrogen.h"
23 #include "src/ic/stub-cache.h"
24 #include "src/isolate-inl.h"
25 #include "src/lithium-allocator.h"
26 #include "src/log.h"
27 #include "src/messages.h"
28 #include "src/prototype.h"
29 #include "src/regexp-stack.h"
30 #include "src/runtime-profiler.h"
31 #include "src/sampler.h"
32 #include "src/scopeinfo.h"
33 #include "src/serialize.h"
34 #include "src/simulator.h"
35 #include "src/version.h"
36 #include "src/vm-state-inl.h"
37 
38 
39 namespace v8 {
40 namespace internal {
41 
42 base::Atomic32 ThreadId::highest_thread_id_ = 0;
43 
AllocateThreadId()44 int ThreadId::AllocateThreadId() {
45   int new_id = base::NoBarrier_AtomicIncrement(&highest_thread_id_, 1);
46   return new_id;
47 }
48 
49 
GetCurrentThreadId()50 int ThreadId::GetCurrentThreadId() {
51   int thread_id = base::Thread::GetThreadLocalInt(Isolate::thread_id_key_);
52   if (thread_id == 0) {
53     thread_id = AllocateThreadId();
54     base::Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id);
55   }
56   return thread_id;
57 }
58 
59 
ThreadLocalTop()60 ThreadLocalTop::ThreadLocalTop() {
61   InitializeInternal();
62 }
63 
64 
InitializeInternal()65 void ThreadLocalTop::InitializeInternal() {
66   c_entry_fp_ = 0;
67   handler_ = 0;
68 #ifdef USE_SIMULATOR
69   simulator_ = NULL;
70 #endif
71   js_entry_sp_ = NULL;
72   external_callback_scope_ = NULL;
73   current_vm_state_ = EXTERNAL;
74   try_catch_handler_ = NULL;
75   context_ = NULL;
76   thread_id_ = ThreadId::Invalid();
77   external_caught_exception_ = false;
78   failed_access_check_callback_ = NULL;
79   save_context_ = NULL;
80   catcher_ = NULL;
81   top_lookup_result_ = NULL;
82   promise_on_stack_ = NULL;
83 
84   // These members are re-initialized later after deserialization
85   // is complete.
86   pending_exception_ = NULL;
87   has_pending_message_ = false;
88   rethrowing_message_ = false;
89   pending_message_obj_ = NULL;
90   pending_message_script_ = NULL;
91   scheduled_exception_ = NULL;
92 }
93 
94 
Initialize()95 void ThreadLocalTop::Initialize() {
96   InitializeInternal();
97 #ifdef USE_SIMULATOR
98   simulator_ = Simulator::current(isolate_);
99 #endif
100   thread_id_ = ThreadId::Current();
101 }
102 
103 
Free()104 void ThreadLocalTop::Free() {
105   // Match unmatched PopPromise calls.
106   while (promise_on_stack_) isolate_->PopPromise();
107 }
108 
109 
110 base::Thread::LocalStorageKey Isolate::isolate_key_;
111 base::Thread::LocalStorageKey Isolate::thread_id_key_;
112 base::Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
113 #ifdef DEBUG
114 base::Thread::LocalStorageKey PerThreadAssertScopeBase::thread_local_key;
115 #endif  // DEBUG
116 base::LazyMutex Isolate::thread_data_table_mutex_ = LAZY_MUTEX_INITIALIZER;
117 Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
118 base::Atomic32 Isolate::isolate_counter_ = 0;
119 
120 Isolate::PerIsolateThreadData*
FindOrAllocatePerThreadDataForThisThread()121     Isolate::FindOrAllocatePerThreadDataForThisThread() {
122   ThreadId thread_id = ThreadId::Current();
123   PerIsolateThreadData* per_thread = NULL;
124   {
125     base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
126     per_thread = thread_data_table_->Lookup(this, thread_id);
127     if (per_thread == NULL) {
128       per_thread = new PerIsolateThreadData(this, thread_id);
129       thread_data_table_->Insert(per_thread);
130     }
131     DCHECK(thread_data_table_->Lookup(this, thread_id) == per_thread);
132   }
133   return per_thread;
134 }
135 
136 
FindPerThreadDataForThisThread()137 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() {
138   ThreadId thread_id = ThreadId::Current();
139   return FindPerThreadDataForThread(thread_id);
140 }
141 
142 
FindPerThreadDataForThread(ThreadId thread_id)143 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThread(
144     ThreadId thread_id) {
145   PerIsolateThreadData* per_thread = NULL;
146   {
147     base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
148     per_thread = thread_data_table_->Lookup(this, thread_id);
149   }
150   return per_thread;
151 }
152 
153 
InitializeOncePerProcess()154 void Isolate::InitializeOncePerProcess() {
155   base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
156   CHECK(thread_data_table_ == NULL);
157   isolate_key_ = base::Thread::CreateThreadLocalKey();
158   thread_id_key_ = base::Thread::CreateThreadLocalKey();
159   per_isolate_thread_data_key_ = base::Thread::CreateThreadLocalKey();
160 #ifdef DEBUG
161   PerThreadAssertScopeBase::thread_local_key =
162       base::Thread::CreateThreadLocalKey();
163 #endif  // DEBUG
164   thread_data_table_ = new Isolate::ThreadDataTable();
165 }
166 
167 
get_address_from_id(Isolate::AddressId id)168 Address Isolate::get_address_from_id(Isolate::AddressId id) {
169   return isolate_addresses_[id];
170 }
171 
172 
Iterate(ObjectVisitor * v,char * thread_storage)173 char* Isolate::Iterate(ObjectVisitor* v, char* thread_storage) {
174   ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage);
175   Iterate(v, thread);
176   return thread_storage + sizeof(ThreadLocalTop);
177 }
178 
179 
IterateThread(ThreadVisitor * v,char * t)180 void Isolate::IterateThread(ThreadVisitor* v, char* t) {
181   ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
182   v->VisitThread(this, thread);
183 }
184 
185 
Iterate(ObjectVisitor * v,ThreadLocalTop * thread)186 void Isolate::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
187   // Visit the roots from the top for a given thread.
188   v->VisitPointer(&thread->pending_exception_);
189   v->VisitPointer(&(thread->pending_message_obj_));
190   v->VisitPointer(bit_cast<Object**>(&(thread->pending_message_script_)));
191   v->VisitPointer(bit_cast<Object**>(&(thread->context_)));
192   v->VisitPointer(&thread->scheduled_exception_);
193 
194   for (v8::TryCatch* block = thread->try_catch_handler();
195        block != NULL;
196        block = block->next_) {
197     v->VisitPointer(bit_cast<Object**>(&(block->exception_)));
198     v->VisitPointer(bit_cast<Object**>(&(block->message_obj_)));
199     v->VisitPointer(bit_cast<Object**>(&(block->message_script_)));
200   }
201 
202   // Iterate over pointers on native execution stack.
203   for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) {
204     it.frame()->Iterate(v);
205   }
206 
207   // Iterate pointers in live lookup results.
208   thread->top_lookup_result_->Iterate(v);
209 }
210 
211 
Iterate(ObjectVisitor * v)212 void Isolate::Iterate(ObjectVisitor* v) {
213   ThreadLocalTop* current_t = thread_local_top();
214   Iterate(v, current_t);
215 }
216 
217 
IterateDeferredHandles(ObjectVisitor * visitor)218 void Isolate::IterateDeferredHandles(ObjectVisitor* visitor) {
219   for (DeferredHandles* deferred = deferred_handles_head_;
220        deferred != NULL;
221        deferred = deferred->next_) {
222     deferred->Iterate(visitor);
223   }
224 }
225 
226 
227 #ifdef DEBUG
IsDeferredHandle(Object ** handle)228 bool Isolate::IsDeferredHandle(Object** handle) {
229   // Each DeferredHandles instance keeps the handles to one job in the
230   // concurrent recompilation queue, containing a list of blocks.  Each block
231   // contains kHandleBlockSize handles except for the first block, which may
232   // not be fully filled.
233   // We iterate through all the blocks to see whether the argument handle
234   // belongs to one of the blocks.  If so, it is deferred.
235   for (DeferredHandles* deferred = deferred_handles_head_;
236        deferred != NULL;
237        deferred = deferred->next_) {
238     List<Object**>* blocks = &deferred->blocks_;
239     for (int i = 0; i < blocks->length(); i++) {
240       Object** block_limit = (i == 0) ? deferred->first_block_limit_
241                                       : blocks->at(i) + kHandleBlockSize;
242       if (blocks->at(i) <= handle && handle < block_limit) return true;
243     }
244   }
245   return false;
246 }
247 #endif  // DEBUG
248 
249 
RegisterTryCatchHandler(v8::TryCatch * that)250 void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) {
251   thread_local_top()->set_try_catch_handler(that);
252 }
253 
254 
UnregisterTryCatchHandler(v8::TryCatch * that)255 void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) {
256   DCHECK(thread_local_top()->try_catch_handler() == that);
257   thread_local_top()->set_try_catch_handler(that->next_);
258   thread_local_top()->catcher_ = NULL;
259 }
260 
261 
StackTraceString()262 Handle<String> Isolate::StackTraceString() {
263   if (stack_trace_nesting_level_ == 0) {
264     stack_trace_nesting_level_++;
265     HeapStringAllocator allocator;
266     StringStream::ClearMentionedObjectCache(this);
267     StringStream accumulator(&allocator);
268     incomplete_message_ = &accumulator;
269     PrintStack(&accumulator);
270     Handle<String> stack_trace = accumulator.ToString(this);
271     incomplete_message_ = NULL;
272     stack_trace_nesting_level_ = 0;
273     return stack_trace;
274   } else if (stack_trace_nesting_level_ == 1) {
275     stack_trace_nesting_level_++;
276     base::OS::PrintError(
277       "\n\nAttempt to print stack while printing stack (double fault)\n");
278     base::OS::PrintError(
279       "If you are lucky you may find a partial stack dump on stdout.\n\n");
280     incomplete_message_->OutputToStdOut();
281     return factory()->empty_string();
282   } else {
283     base::OS::Abort();
284     // Unreachable
285     return factory()->empty_string();
286   }
287 }
288 
289 
PushStackTraceAndDie(unsigned int magic,Object * object,Map * map,unsigned int magic2)290 void Isolate::PushStackTraceAndDie(unsigned int magic,
291                                    Object* object,
292                                    Map* map,
293                                    unsigned int magic2) {
294   const int kMaxStackTraceSize = 8192;
295   Handle<String> trace = StackTraceString();
296   uint8_t buffer[kMaxStackTraceSize];
297   int length = Min(kMaxStackTraceSize - 1, trace->length());
298   String::WriteToFlat(*trace, buffer, 0, length);
299   buffer[length] = '\0';
300   // TODO(dcarney): convert buffer to utf8?
301   base::OS::PrintError("Stacktrace (%x-%x) %p %p: %s\n", magic, magic2,
302                        static_cast<void*>(object), static_cast<void*>(map),
303                        reinterpret_cast<char*>(buffer));
304   base::OS::Abort();
305 }
306 
307 
308 // Determines whether the given stack frame should be displayed in
309 // a stack trace.  The caller is the error constructor that asked
310 // for the stack trace to be collected.  The first time a construct
311 // call to this function is encountered it is skipped.  The seen_caller
312 // in/out parameter is used to remember if the caller has been seen
313 // yet.
IsVisibleInStackTrace(JSFunction * fun,Object * caller,Object * receiver,bool * seen_caller)314 static bool IsVisibleInStackTrace(JSFunction* fun,
315                                   Object* caller,
316                                   Object* receiver,
317                                   bool* seen_caller) {
318   if ((fun == caller) && !(*seen_caller)) {
319     *seen_caller = true;
320     return false;
321   }
322   // Skip all frames until we've seen the caller.
323   if (!(*seen_caller)) return false;
324   // Also, skip non-visible built-in functions and any call with the builtins
325   // object as receiver, so as to not reveal either the builtins object or
326   // an internal function.
327   // The --builtins-in-stack-traces command line flag allows including
328   // internal call sites in the stack trace for debugging purposes.
329   if (!FLAG_builtins_in_stack_traces) {
330     if (receiver->IsJSBuiltinsObject()) return false;
331     if (fun->IsBuiltin()) {
332       return fun->shared()->native();
333     } else if (fun->IsFromNativeScript() || fun->IsFromExtensionScript()) {
334       return false;
335     }
336   }
337   return true;
338 }
339 
340 
CaptureSimpleStackTrace(Handle<JSObject> error_object,Handle<Object> caller)341 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object,
342                                                 Handle<Object> caller) {
343   // Get stack trace limit.
344   Handle<Object> error = Object::GetProperty(
345       this, js_builtins_object(), "$Error").ToHandleChecked();
346   if (!error->IsJSObject()) return factory()->undefined_value();
347 
348   Handle<String> stackTraceLimit =
349       factory()->InternalizeUtf8String("stackTraceLimit");
350   DCHECK(!stackTraceLimit.is_null());
351   Handle<Object> stack_trace_limit =
352       JSObject::GetDataProperty(Handle<JSObject>::cast(error),
353                                 stackTraceLimit);
354   if (!stack_trace_limit->IsNumber()) return factory()->undefined_value();
355   int limit = FastD2IChecked(stack_trace_limit->Number());
356   limit = Max(limit, 0);  // Ensure that limit is not negative.
357 
358   int initial_size = Min(limit, 10);
359   Handle<FixedArray> elements =
360       factory()->NewFixedArrayWithHoles(initial_size * 4 + 1);
361 
362   // If the caller parameter is a function we skip frames until we're
363   // under it before starting to collect.
364   bool seen_caller = !caller->IsJSFunction();
365   // First element is reserved to store the number of sloppy frames.
366   int cursor = 1;
367   int frames_seen = 0;
368   int sloppy_frames = 0;
369   bool encountered_strict_function = false;
370   for (JavaScriptFrameIterator iter(this);
371        !iter.done() && frames_seen < limit;
372        iter.Advance()) {
373     JavaScriptFrame* frame = iter.frame();
374     // Set initial size to the maximum inlining level + 1 for the outermost
375     // function.
376     List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
377     frame->Summarize(&frames);
378     for (int i = frames.length() - 1; i >= 0; i--) {
379       Handle<JSFunction> fun = frames[i].function();
380       Handle<Object> recv = frames[i].receiver();
381       // Filter out internal frames that we do not want to show.
382       if (!IsVisibleInStackTrace(*fun, *caller, *recv, &seen_caller)) continue;
383       // Filter out frames from other security contexts.
384       if (!this->context()->HasSameSecurityTokenAs(fun->context())) continue;
385       if (cursor + 4 > elements->length()) {
386         int new_capacity = JSObject::NewElementsCapacity(elements->length());
387         Handle<FixedArray> new_elements =
388             factory()->NewFixedArrayWithHoles(new_capacity);
389         for (int i = 0; i < cursor; i++) {
390           new_elements->set(i, elements->get(i));
391         }
392         elements = new_elements;
393       }
394       DCHECK(cursor + 4 <= elements->length());
395 
396 
397       Handle<Code> code = frames[i].code();
398       Handle<Smi> offset(Smi::FromInt(frames[i].offset()), this);
399       // The stack trace API should not expose receivers and function
400       // objects on frames deeper than the top-most one with a strict
401       // mode function.  The number of sloppy frames is stored as
402       // first element in the result array.
403       if (!encountered_strict_function) {
404         if (fun->shared()->strict_mode() == STRICT) {
405           encountered_strict_function = true;
406         } else {
407           sloppy_frames++;
408         }
409       }
410       elements->set(cursor++, *recv);
411       elements->set(cursor++, *fun);
412       elements->set(cursor++, *code);
413       elements->set(cursor++, *offset);
414       frames_seen++;
415     }
416   }
417   elements->set(0, Smi::FromInt(sloppy_frames));
418   Handle<JSArray> result = factory()->NewJSArrayWithElements(elements);
419   result->set_length(Smi::FromInt(cursor));
420   return result;
421 }
422 
423 
CaptureAndSetDetailedStackTrace(Handle<JSObject> error_object)424 void Isolate::CaptureAndSetDetailedStackTrace(Handle<JSObject> error_object) {
425   if (capture_stack_trace_for_uncaught_exceptions_) {
426     // Capture stack trace for a detailed exception message.
427     Handle<Name> key = factory()->detailed_stack_trace_symbol();
428     Handle<JSArray> stack_trace = CaptureCurrentStackTrace(
429         stack_trace_for_uncaught_exceptions_frame_limit_,
430         stack_trace_for_uncaught_exceptions_options_);
431     JSObject::SetProperty(error_object, key, stack_trace, STRICT).Assert();
432   }
433 }
434 
435 
CaptureAndSetSimpleStackTrace(Handle<JSObject> error_object,Handle<Object> caller)436 void Isolate::CaptureAndSetSimpleStackTrace(Handle<JSObject> error_object,
437                                             Handle<Object> caller) {
438   // Capture stack trace for simple stack trace string formatting.
439   Handle<Name> key = factory()->stack_trace_symbol();
440   Handle<Object> stack_trace = CaptureSimpleStackTrace(error_object, caller);
441   JSObject::SetProperty(error_object, key, stack_trace, STRICT).Assert();
442 }
443 
444 
CaptureCurrentStackTrace(int frame_limit,StackTrace::StackTraceOptions options)445 Handle<JSArray> Isolate::CaptureCurrentStackTrace(
446     int frame_limit, StackTrace::StackTraceOptions options) {
447   // Ensure no negative values.
448   int limit = Max(frame_limit, 0);
449   Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit);
450 
451   Handle<String> column_key =
452       factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("column"));
453   Handle<String> line_key =
454       factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("lineNumber"));
455   Handle<String> script_id_key =
456       factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("scriptId"));
457   Handle<String> script_name_key =
458       factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("scriptName"));
459   Handle<String> script_name_or_source_url_key =
460       factory()->InternalizeOneByteString(
461           STATIC_CHAR_VECTOR("scriptNameOrSourceURL"));
462   Handle<String> function_key =
463       factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("functionName"));
464   Handle<String> eval_key =
465       factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("isEval"));
466   Handle<String> constructor_key =
467       factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("isConstructor"));
468 
469   StackTraceFrameIterator it(this);
470   int frames_seen = 0;
471   while (!it.done() && (frames_seen < limit)) {
472     JavaScriptFrame* frame = it.frame();
473     // Set initial size to the maximum inlining level + 1 for the outermost
474     // function.
475     List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
476     frame->Summarize(&frames);
477     for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) {
478       Handle<JSFunction> fun = frames[i].function();
479       // Filter frames from other security contexts.
480       if (!(options & StackTrace::kExposeFramesAcrossSecurityOrigins) &&
481           !this->context()->HasSameSecurityTokenAs(fun->context())) continue;
482 
483       // Create a JSObject to hold the information for the StackFrame.
484       Handle<JSObject> stack_frame = factory()->NewJSObject(object_function());
485 
486       Handle<Script> script(Script::cast(fun->shared()->script()));
487 
488       if (options & StackTrace::kLineNumber) {
489         int script_line_offset = script->line_offset()->value();
490         int position = frames[i].code()->SourcePosition(frames[i].pc());
491         int line_number = Script::GetLineNumber(script, position);
492         // line_number is already shifted by the script_line_offset.
493         int relative_line_number = line_number - script_line_offset;
494         if (options & StackTrace::kColumnOffset && relative_line_number >= 0) {
495           Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
496           int start = (relative_line_number == 0) ? 0 :
497               Smi::cast(line_ends->get(relative_line_number - 1))->value() + 1;
498           int column_offset = position - start;
499           if (relative_line_number == 0) {
500             // For the case where the code is on the same line as the script
501             // tag.
502             column_offset += script->column_offset()->value();
503           }
504           JSObject::AddProperty(
505               stack_frame, column_key,
506               handle(Smi::FromInt(column_offset + 1), this), NONE);
507         }
508        JSObject::AddProperty(
509             stack_frame, line_key,
510             handle(Smi::FromInt(line_number + 1), this), NONE);
511       }
512 
513       if (options & StackTrace::kScriptId) {
514         JSObject::AddProperty(
515             stack_frame, script_id_key, handle(script->id(), this), NONE);
516       }
517 
518       if (options & StackTrace::kScriptName) {
519         JSObject::AddProperty(
520             stack_frame, script_name_key, handle(script->name(), this), NONE);
521       }
522 
523       if (options & StackTrace::kScriptNameOrSourceURL) {
524         Handle<Object> result = Script::GetNameOrSourceURL(script);
525         JSObject::AddProperty(
526             stack_frame, script_name_or_source_url_key, result, NONE);
527       }
528 
529       if (options & StackTrace::kFunctionName) {
530         Handle<Object> fun_name(fun->shared()->DebugName(), this);
531         JSObject::AddProperty(stack_frame, function_key, fun_name, NONE);
532       }
533 
534       if (options & StackTrace::kIsEval) {
535         Handle<Object> is_eval =
536             script->compilation_type() == Script::COMPILATION_TYPE_EVAL ?
537                 factory()->true_value() : factory()->false_value();
538         JSObject::AddProperty(stack_frame, eval_key, is_eval, NONE);
539       }
540 
541       if (options & StackTrace::kIsConstructor) {
542         Handle<Object> is_constructor = (frames[i].is_constructor()) ?
543             factory()->true_value() : factory()->false_value();
544         JSObject::AddProperty(
545             stack_frame, constructor_key, is_constructor, NONE);
546       }
547 
548       FixedArray::cast(stack_trace->elements())->set(frames_seen, *stack_frame);
549       frames_seen++;
550     }
551     it.Advance();
552   }
553 
554   stack_trace->set_length(Smi::FromInt(frames_seen));
555   return stack_trace;
556 }
557 
558 
PrintStack(FILE * out)559 void Isolate::PrintStack(FILE* out) {
560   if (stack_trace_nesting_level_ == 0) {
561     stack_trace_nesting_level_++;
562     StringStream::ClearMentionedObjectCache(this);
563     HeapStringAllocator allocator;
564     StringStream accumulator(&allocator);
565     incomplete_message_ = &accumulator;
566     PrintStack(&accumulator);
567     accumulator.OutputToFile(out);
568     InitializeLoggingAndCounters();
569     accumulator.Log(this);
570     incomplete_message_ = NULL;
571     stack_trace_nesting_level_ = 0;
572   } else if (stack_trace_nesting_level_ == 1) {
573     stack_trace_nesting_level_++;
574     base::OS::PrintError(
575       "\n\nAttempt to print stack while printing stack (double fault)\n");
576     base::OS::PrintError(
577       "If you are lucky you may find a partial stack dump on stdout.\n\n");
578     incomplete_message_->OutputToFile(out);
579   }
580 }
581 
582 
PrintFrames(Isolate * isolate,StringStream * accumulator,StackFrame::PrintMode mode)583 static void PrintFrames(Isolate* isolate,
584                         StringStream* accumulator,
585                         StackFrame::PrintMode mode) {
586   StackFrameIterator it(isolate);
587   for (int i = 0; !it.done(); it.Advance()) {
588     it.frame()->Print(accumulator, mode, i++);
589   }
590 }
591 
592 
PrintStack(StringStream * accumulator)593 void Isolate::PrintStack(StringStream* accumulator) {
594   if (!IsInitialized()) {
595     accumulator->Add(
596         "\n==== JS stack trace is not available =======================\n\n");
597     accumulator->Add(
598         "\n==== Isolate for the thread is not initialized =============\n\n");
599     return;
600   }
601   // The MentionedObjectCache is not GC-proof at the moment.
602   DisallowHeapAllocation no_gc;
603   DCHECK(StringStream::IsMentionedObjectCacheClear(this));
604 
605   // Avoid printing anything if there are no frames.
606   if (c_entry_fp(thread_local_top()) == 0) return;
607 
608   accumulator->Add(
609       "\n==== JS stack trace =========================================\n\n");
610   PrintFrames(this, accumulator, StackFrame::OVERVIEW);
611 
612   accumulator->Add(
613       "\n==== Details ================================================\n\n");
614   PrintFrames(this, accumulator, StackFrame::DETAILS);
615 
616   accumulator->PrintMentionedObjectCache(this);
617   accumulator->Add("=====================\n\n");
618 }
619 
620 
SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback)621 void Isolate::SetFailedAccessCheckCallback(
622     v8::FailedAccessCheckCallback callback) {
623   thread_local_top()->failed_access_check_callback_ = callback;
624 }
625 
626 
GetAccessCheckInfo(Isolate * isolate,Handle<JSObject> receiver)627 static inline AccessCheckInfo* GetAccessCheckInfo(Isolate* isolate,
628                                                   Handle<JSObject> receiver) {
629   JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
630   if (!constructor->shared()->IsApiFunction()) return NULL;
631 
632   Object* data_obj =
633      constructor->shared()->get_api_func_data()->access_check_info();
634   if (data_obj == isolate->heap()->undefined_value()) return NULL;
635 
636   return AccessCheckInfo::cast(data_obj);
637 }
638 
639 
ReportFailedAccessCheck(Handle<JSObject> receiver,v8::AccessType type)640 void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver,
641                                       v8::AccessType type) {
642   if (!thread_local_top()->failed_access_check_callback_) {
643     Handle<String> message = factory()->InternalizeUtf8String("no access");
644     Handle<Object> error;
645     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
646         this, error, factory()->NewTypeError(message), /* void */);
647     ScheduleThrow(*error);
648     return;
649   }
650 
651   DCHECK(receiver->IsAccessCheckNeeded());
652   DCHECK(context());
653 
654   // Get the data object from access check info.
655   HandleScope scope(this);
656   Handle<Object> data;
657   { DisallowHeapAllocation no_gc;
658     AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver);
659     if (!access_check_info) return;
660     data = handle(access_check_info->data(), this);
661   }
662 
663   // Leaving JavaScript.
664   VMState<EXTERNAL> state(this);
665   thread_local_top()->failed_access_check_callback_(
666       v8::Utils::ToLocal(receiver),
667       type,
668       v8::Utils::ToLocal(data));
669 }
670 
671 
672 enum MayAccessDecision {
673   YES, NO, UNKNOWN
674 };
675 
676 
MayAccessPreCheck(Isolate * isolate,Handle<JSObject> receiver,v8::AccessType type)677 static MayAccessDecision MayAccessPreCheck(Isolate* isolate,
678                                            Handle<JSObject> receiver,
679                                            v8::AccessType type) {
680   DisallowHeapAllocation no_gc;
681   // During bootstrapping, callback functions are not enabled yet.
682   if (isolate->bootstrapper()->IsActive()) return YES;
683 
684   if (receiver->IsJSGlobalProxy()) {
685     Object* receiver_context = JSGlobalProxy::cast(*receiver)->native_context();
686     if (!receiver_context->IsContext()) return NO;
687 
688     // Get the native context of current top context.
689     // avoid using Isolate::native_context() because it uses Handle.
690     Context* native_context =
691         isolate->context()->global_object()->native_context();
692     if (receiver_context == native_context) return YES;
693 
694     if (Context::cast(receiver_context)->security_token() ==
695         native_context->security_token())
696       return YES;
697   }
698 
699   return UNKNOWN;
700 }
701 
702 
MayNamedAccess(Handle<JSObject> receiver,Handle<Object> key,v8::AccessType type)703 bool Isolate::MayNamedAccess(Handle<JSObject> receiver,
704                              Handle<Object> key,
705                              v8::AccessType type) {
706   DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded());
707 
708   // Skip checks for hidden properties access.  Note, we do not
709   // require existence of a context in this case.
710   if (key.is_identical_to(factory()->hidden_string())) return true;
711 
712   // Check for compatibility between the security tokens in the
713   // current lexical context and the accessed object.
714   DCHECK(context());
715 
716   MayAccessDecision decision = MayAccessPreCheck(this, receiver, type);
717   if (decision != UNKNOWN) return decision == YES;
718 
719   HandleScope scope(this);
720   Handle<Object> data;
721   v8::NamedSecurityCallback callback;
722   { DisallowHeapAllocation no_gc;
723     AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver);
724     if (!access_check_info) return false;
725     Object* fun_obj = access_check_info->named_callback();
726     callback = v8::ToCData<v8::NamedSecurityCallback>(fun_obj);
727     if (!callback) return false;
728     data = handle(access_check_info->data(), this);
729   }
730 
731   LOG(this, ApiNamedSecurityCheck(*key));
732 
733   // Leaving JavaScript.
734   VMState<EXTERNAL> state(this);
735   return callback(v8::Utils::ToLocal(receiver),
736                   v8::Utils::ToLocal(key),
737                   type,
738                   v8::Utils::ToLocal(data));
739 }
740 
741 
MayIndexedAccess(Handle<JSObject> receiver,uint32_t index,v8::AccessType type)742 bool Isolate::MayIndexedAccess(Handle<JSObject> receiver,
743                                uint32_t index,
744                                v8::AccessType type) {
745   DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded());
746   // Check for compatibility between the security tokens in the
747   // current lexical context and the accessed object.
748   DCHECK(context());
749 
750   MayAccessDecision decision = MayAccessPreCheck(this, receiver, type);
751   if (decision != UNKNOWN) return decision == YES;
752 
753   HandleScope scope(this);
754   Handle<Object> data;
755   v8::IndexedSecurityCallback callback;
756   { DisallowHeapAllocation no_gc;
757     // Get named access check callback
758     AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver);
759     if (!access_check_info) return false;
760     Object* fun_obj = access_check_info->indexed_callback();
761     callback = v8::ToCData<v8::IndexedSecurityCallback>(fun_obj);
762     if (!callback) return false;
763     data = handle(access_check_info->data(), this);
764   }
765 
766   LOG(this, ApiIndexedSecurityCheck(index));
767 
768   // Leaving JavaScript.
769   VMState<EXTERNAL> state(this);
770   return callback(
771       v8::Utils::ToLocal(receiver), index, type, v8::Utils::ToLocal(data));
772 }
773 
774 
775 const char* const Isolate::kStackOverflowMessage =
776   "Uncaught RangeError: Maximum call stack size exceeded";
777 
778 
StackOverflow()779 Object* Isolate::StackOverflow() {
780   HandleScope scope(this);
781   // At this point we cannot create an Error object using its javascript
782   // constructor.  Instead, we copy the pre-constructed boilerplate and
783   // attach the stack trace as a hidden property.
784   Handle<String> key = factory()->stack_overflow_string();
785   Handle<JSObject> boilerplate = Handle<JSObject>::cast(
786       Object::GetProperty(js_builtins_object(), key).ToHandleChecked());
787   Handle<JSObject> exception = factory()->CopyJSObject(boilerplate);
788   DoThrow(*exception, NULL);
789 
790   CaptureAndSetSimpleStackTrace(exception, factory()->undefined_value());
791   return heap()->exception();
792 }
793 
794 
TerminateExecution()795 Object* Isolate::TerminateExecution() {
796   DoThrow(heap_.termination_exception(), NULL);
797   return heap()->exception();
798 }
799 
800 
CancelTerminateExecution()801 void Isolate::CancelTerminateExecution() {
802   if (try_catch_handler()) {
803     try_catch_handler()->has_terminated_ = false;
804   }
805   if (has_pending_exception() &&
806       pending_exception() == heap_.termination_exception()) {
807     thread_local_top()->external_caught_exception_ = false;
808     clear_pending_exception();
809   }
810   if (has_scheduled_exception() &&
811       scheduled_exception() == heap_.termination_exception()) {
812     thread_local_top()->external_caught_exception_ = false;
813     clear_scheduled_exception();
814   }
815 }
816 
817 
InvokeApiInterruptCallback()818 void Isolate::InvokeApiInterruptCallback() {
819   // Note: callback below should be called outside of execution access lock.
820   InterruptCallback callback = NULL;
821   void* data = NULL;
822   {
823     ExecutionAccess access(this);
824     callback = api_interrupt_callback_;
825     data = api_interrupt_callback_data_;
826     api_interrupt_callback_ = NULL;
827     api_interrupt_callback_data_ = NULL;
828   }
829 
830   if (callback != NULL) {
831     VMState<EXTERNAL> state(this);
832     HandleScope handle_scope(this);
833     callback(reinterpret_cast<v8::Isolate*>(this), data);
834   }
835 }
836 
837 
Throw(Object * exception,MessageLocation * location)838 Object* Isolate::Throw(Object* exception, MessageLocation* location) {
839   DoThrow(exception, location);
840   return heap()->exception();
841 }
842 
843 
ReThrow(Object * exception)844 Object* Isolate::ReThrow(Object* exception) {
845   bool can_be_caught_externally = false;
846   bool catchable_by_javascript = is_catchable_by_javascript(exception);
847   ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
848 
849   thread_local_top()->catcher_ = can_be_caught_externally ?
850       try_catch_handler() : NULL;
851 
852   // Set the exception being re-thrown.
853   set_pending_exception(exception);
854   return heap()->exception();
855 }
856 
857 
ThrowIllegalOperation()858 Object* Isolate::ThrowIllegalOperation() {
859   if (FLAG_stack_trace_on_illegal) PrintStack(stdout);
860   return Throw(heap_.illegal_access_string());
861 }
862 
863 
ScheduleThrow(Object * exception)864 void Isolate::ScheduleThrow(Object* exception) {
865   // When scheduling a throw we first throw the exception to get the
866   // error reporting if it is uncaught before rescheduling it.
867   Throw(exception);
868   PropagatePendingExceptionToExternalTryCatch();
869   if (has_pending_exception()) {
870     thread_local_top()->scheduled_exception_ = pending_exception();
871     thread_local_top()->external_caught_exception_ = false;
872     clear_pending_exception();
873   }
874 }
875 
876 
RestorePendingMessageFromTryCatch(v8::TryCatch * handler)877 void Isolate::RestorePendingMessageFromTryCatch(v8::TryCatch* handler) {
878   DCHECK(handler == try_catch_handler());
879   DCHECK(handler->HasCaught());
880   DCHECK(handler->rethrow_);
881   DCHECK(handler->capture_message_);
882   Object* message = reinterpret_cast<Object*>(handler->message_obj_);
883   Object* script = reinterpret_cast<Object*>(handler->message_script_);
884   DCHECK(message->IsJSMessageObject() || message->IsTheHole());
885   DCHECK(script->IsScript() || script->IsTheHole());
886   thread_local_top()->pending_message_obj_ = message;
887   thread_local_top()->pending_message_script_ = script;
888   thread_local_top()->pending_message_start_pos_ = handler->message_start_pos_;
889   thread_local_top()->pending_message_end_pos_ = handler->message_end_pos_;
890 }
891 
892 
CancelScheduledExceptionFromTryCatch(v8::TryCatch * handler)893 void Isolate::CancelScheduledExceptionFromTryCatch(v8::TryCatch* handler) {
894   DCHECK(has_scheduled_exception());
895   if (scheduled_exception() == handler->exception_) {
896     DCHECK(scheduled_exception() != heap()->termination_exception());
897     clear_scheduled_exception();
898   }
899 }
900 
901 
PromoteScheduledException()902 Object* Isolate::PromoteScheduledException() {
903   Object* thrown = scheduled_exception();
904   clear_scheduled_exception();
905   // Re-throw the exception to avoid getting repeated error reporting.
906   return ReThrow(thrown);
907 }
908 
909 
PrintCurrentStackTrace(FILE * out)910 void Isolate::PrintCurrentStackTrace(FILE* out) {
911   StackTraceFrameIterator it(this);
912   while (!it.done()) {
913     HandleScope scope(this);
914     // Find code position if recorded in relocation info.
915     JavaScriptFrame* frame = it.frame();
916     int pos = frame->LookupCode()->SourcePosition(frame->pc());
917     Handle<Object> pos_obj(Smi::FromInt(pos), this);
918     // Fetch function and receiver.
919     Handle<JSFunction> fun(frame->function());
920     Handle<Object> recv(frame->receiver(), this);
921     // Advance to the next JavaScript frame and determine if the
922     // current frame is the top-level frame.
923     it.Advance();
924     Handle<Object> is_top_level = it.done()
925         ? factory()->true_value()
926         : factory()->false_value();
927     // Generate and print stack trace line.
928     Handle<String> line =
929         Execution::GetStackTraceLine(recv, fun, pos_obj, is_top_level);
930     if (line->length() > 0) {
931       line->PrintOn(out);
932       PrintF(out, "\n");
933     }
934   }
935 }
936 
937 
ComputeLocation(MessageLocation * target)938 void Isolate::ComputeLocation(MessageLocation* target) {
939   *target = MessageLocation(Handle<Script>(heap_.empty_script()), -1, -1);
940   StackTraceFrameIterator it(this);
941   if (!it.done()) {
942     JavaScriptFrame* frame = it.frame();
943     JSFunction* fun = frame->function();
944     Object* script = fun->shared()->script();
945     if (script->IsScript() &&
946         !(Script::cast(script)->source()->IsUndefined())) {
947       int pos = frame->LookupCode()->SourcePosition(frame->pc());
948       // Compute the location from the function and the reloc info.
949       Handle<Script> casted_script(Script::cast(script));
950       *target = MessageLocation(casted_script, pos, pos + 1);
951     }
952   }
953 }
954 
955 
ShouldReportException(bool * can_be_caught_externally,bool catchable_by_javascript)956 bool Isolate::ShouldReportException(bool* can_be_caught_externally,
957                                     bool catchable_by_javascript) {
958   // Find the top-most try-catch handler.
959   StackHandler* handler =
960       StackHandler::FromAddress(Isolate::handler(thread_local_top()));
961   while (handler != NULL && !handler->is_catch()) {
962     handler = handler->next();
963   }
964 
965   // Get the address of the external handler so we can compare the address to
966   // determine which one is closer to the top of the stack.
967   Address external_handler_address =
968       thread_local_top()->try_catch_handler_address();
969 
970   // The exception has been externally caught if and only if there is
971   // an external handler which is on top of the top-most try-catch
972   // handler.
973   *can_be_caught_externally = external_handler_address != NULL &&
974       (handler == NULL || handler->address() > external_handler_address ||
975        !catchable_by_javascript);
976 
977   if (*can_be_caught_externally) {
978     // Only report the exception if the external handler is verbose.
979     return try_catch_handler()->is_verbose_;
980   } else {
981     // Report the exception if it isn't caught by JavaScript code.
982     return handler == NULL;
983   }
984 }
985 
986 
IsErrorObject(Handle<Object> obj)987 bool Isolate::IsErrorObject(Handle<Object> obj) {
988   if (!obj->IsJSObject()) return false;
989 
990   Handle<String> error_key =
991       factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("$Error"));
992   Handle<Object> error_constructor = Object::GetProperty(
993       js_builtins_object(), error_key).ToHandleChecked();
994 
995   DisallowHeapAllocation no_gc;
996   for (PrototypeIterator iter(this, *obj, PrototypeIterator::START_AT_RECEIVER);
997        !iter.IsAtEnd(); iter.Advance()) {
998     if (iter.GetCurrent()->IsJSProxy()) return false;
999     if (JSObject::cast(iter.GetCurrent())->map()->constructor() ==
1000         *error_constructor) {
1001       return true;
1002     }
1003   }
1004   return false;
1005 }
1006 
1007 static int fatal_exception_depth = 0;
1008 
DoThrow(Object * exception,MessageLocation * location)1009 void Isolate::DoThrow(Object* exception, MessageLocation* location) {
1010   DCHECK(!has_pending_exception());
1011 
1012   HandleScope scope(this);
1013   Handle<Object> exception_handle(exception, this);
1014 
1015   // Determine reporting and whether the exception is caught externally.
1016   bool catchable_by_javascript = is_catchable_by_javascript(exception);
1017   bool can_be_caught_externally = false;
1018   bool should_report_exception =
1019       ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
1020   bool report_exception = catchable_by_javascript && should_report_exception;
1021   bool try_catch_needs_message =
1022       can_be_caught_externally && try_catch_handler()->capture_message_;
1023   bool bootstrapping = bootstrapper()->IsActive();
1024   bool rethrowing_message = thread_local_top()->rethrowing_message_;
1025 
1026   thread_local_top()->rethrowing_message_ = false;
1027 
1028   // Notify debugger of exception.
1029   if (catchable_by_javascript) {
1030     debug()->OnThrow(exception_handle, report_exception);
1031   }
1032 
1033   // Generate the message if required.
1034   if (!rethrowing_message && (report_exception || try_catch_needs_message)) {
1035     MessageLocation potential_computed_location;
1036     if (location == NULL) {
1037       // If no location was specified we use a computed one instead.
1038       ComputeLocation(&potential_computed_location);
1039       location = &potential_computed_location;
1040     }
1041     // It's not safe to try to make message objects or collect stack traces
1042     // while the bootstrapper is active since the infrastructure may not have
1043     // been properly initialized.
1044     if (!bootstrapping) {
1045       Handle<JSArray> stack_trace_object;
1046       if (capture_stack_trace_for_uncaught_exceptions_) {
1047         if (IsErrorObject(exception_handle)) {
1048           // We fetch the stack trace that corresponds to this error object.
1049           Handle<Name> key = factory()->detailed_stack_trace_symbol();
1050           // Look up as own property.  If the lookup fails, the exception is
1051           // probably not a valid Error object.  In that case, we fall through
1052           // and capture the stack trace at this throw site.
1053           LookupIterator lookup(exception_handle, key,
1054                                 LookupIterator::OWN_SKIP_INTERCEPTOR);
1055           Handle<Object> stack_trace_property;
1056           if (Object::GetProperty(&lookup).ToHandle(&stack_trace_property) &&
1057               stack_trace_property->IsJSArray()) {
1058             stack_trace_object = Handle<JSArray>::cast(stack_trace_property);
1059           }
1060         }
1061         if (stack_trace_object.is_null()) {
1062           // Not an error object, we capture at throw site.
1063           stack_trace_object = CaptureCurrentStackTrace(
1064               stack_trace_for_uncaught_exceptions_frame_limit_,
1065               stack_trace_for_uncaught_exceptions_options_);
1066         }
1067       }
1068 
1069       Handle<Object> exception_arg = exception_handle;
1070       // If the exception argument is a custom object, turn it into a string
1071       // before throwing as uncaught exception.  Note that the pending
1072       // exception object to be set later must not be turned into a string.
1073       if (exception_arg->IsJSObject() && !IsErrorObject(exception_arg)) {
1074         MaybeHandle<Object> maybe_exception =
1075             Execution::ToDetailString(this, exception_arg);
1076         if (!maybe_exception.ToHandle(&exception_arg)) {
1077           exception_arg = factory()->InternalizeOneByteString(
1078               STATIC_CHAR_VECTOR("exception"));
1079         }
1080       }
1081       Handle<Object> message_obj = MessageHandler::MakeMessageObject(
1082           this,
1083           "uncaught_exception",
1084           location,
1085           HandleVector<Object>(&exception_arg, 1),
1086           stack_trace_object);
1087       thread_local_top()->pending_message_obj_ = *message_obj;
1088       if (location != NULL) {
1089         thread_local_top()->pending_message_script_ = *location->script();
1090         thread_local_top()->pending_message_start_pos_ = location->start_pos();
1091         thread_local_top()->pending_message_end_pos_ = location->end_pos();
1092       }
1093 
1094       // If the abort-on-uncaught-exception flag is specified, abort on any
1095       // exception not caught by JavaScript, even when an external handler is
1096       // present.  This flag is intended for use by JavaScript developers, so
1097       // print a user-friendly stack trace (not an internal one).
1098       if (fatal_exception_depth == 0 &&
1099           FLAG_abort_on_uncaught_exception &&
1100           (report_exception || can_be_caught_externally)) {
1101         fatal_exception_depth++;
1102         PrintF(stderr,
1103                "%s\n\nFROM\n",
1104                MessageHandler::GetLocalizedMessage(this, message_obj).get());
1105         PrintCurrentStackTrace(stderr);
1106         base::OS::Abort();
1107       }
1108     } else if (location != NULL && !location->script().is_null()) {
1109       // We are bootstrapping and caught an error where the location is set
1110       // and we have a script for the location.
1111       // In this case we could have an extension (or an internal error
1112       // somewhere) and we print out the line number at which the error occured
1113       // to the console for easier debugging.
1114       int line_number =
1115           location->script()->GetLineNumber(location->start_pos()) + 1;
1116       if (exception->IsString() && location->script()->name()->IsString()) {
1117         base::OS::PrintError(
1118             "Extension or internal compilation error: %s in %s at line %d.\n",
1119             String::cast(exception)->ToCString().get(),
1120             String::cast(location->script()->name())->ToCString().get(),
1121             line_number);
1122       } else if (location->script()->name()->IsString()) {
1123         base::OS::PrintError(
1124             "Extension or internal compilation error in %s at line %d.\n",
1125             String::cast(location->script()->name())->ToCString().get(),
1126             line_number);
1127       } else {
1128         base::OS::PrintError("Extension or internal compilation error.\n");
1129       }
1130 #ifdef OBJECT_PRINT
1131       // Since comments and empty lines have been stripped from the source of
1132       // builtins, print the actual source here so that line numbers match.
1133       if (location->script()->source()->IsString()) {
1134         Handle<String> src(String::cast(location->script()->source()));
1135         PrintF("Failing script:\n");
1136         int len = src->length();
1137         int line_number = 1;
1138         PrintF("%5d: ", line_number);
1139         for (int i = 0; i < len; i++) {
1140           uint16_t character = src->Get(i);
1141           PrintF("%c", character);
1142           if (character == '\n' && i < len - 2) {
1143             PrintF("%5d: ", ++line_number);
1144           }
1145         }
1146       }
1147 #endif
1148     }
1149   }
1150 
1151   // Save the message for reporting if the the exception remains uncaught.
1152   thread_local_top()->has_pending_message_ = report_exception;
1153 
1154   // Do not forget to clean catcher_ if currently thrown exception cannot
1155   // be caught.  If necessary, ReThrow will update the catcher.
1156   thread_local_top()->catcher_ = can_be_caught_externally ?
1157       try_catch_handler() : NULL;
1158 
1159   set_pending_exception(*exception_handle);
1160 }
1161 
1162 
HasExternalTryCatch()1163 bool Isolate::HasExternalTryCatch() {
1164   DCHECK(has_pending_exception());
1165 
1166   return (thread_local_top()->catcher_ != NULL) &&
1167       (try_catch_handler() == thread_local_top()->catcher_);
1168 }
1169 
1170 
IsFinallyOnTop()1171 bool Isolate::IsFinallyOnTop() {
1172   // Get the address of the external handler so we can compare the address to
1173   // determine which one is closer to the top of the stack.
1174   Address external_handler_address =
1175       thread_local_top()->try_catch_handler_address();
1176   DCHECK(external_handler_address != NULL);
1177 
1178   // The exception has been externally caught if and only if there is
1179   // an external handler which is on top of the top-most try-finally
1180   // handler.
1181   // There should be no try-catch blocks as they would prohibit us from
1182   // finding external catcher in the first place (see catcher_ check above).
1183   //
1184   // Note, that finally clause would rethrow an exception unless it's
1185   // aborted by jumps in control flow like return, break, etc. and we'll
1186   // have another chances to set proper v8::TryCatch.
1187   StackHandler* handler =
1188       StackHandler::FromAddress(Isolate::handler(thread_local_top()));
1189   while (handler != NULL && handler->address() < external_handler_address) {
1190     DCHECK(!handler->is_catch());
1191     if (handler->is_finally()) return true;
1192 
1193     handler = handler->next();
1194   }
1195 
1196   return false;
1197 }
1198 
1199 
ReportPendingMessages()1200 void Isolate::ReportPendingMessages() {
1201   DCHECK(has_pending_exception());
1202   bool can_clear_message = PropagatePendingExceptionToExternalTryCatch();
1203 
1204   HandleScope scope(this);
1205   if (thread_local_top_.pending_exception_ == heap()->termination_exception()) {
1206     // Do nothing: if needed, the exception has been already propagated to
1207     // v8::TryCatch.
1208   } else {
1209     if (thread_local_top_.has_pending_message_) {
1210       thread_local_top_.has_pending_message_ = false;
1211       if (!thread_local_top_.pending_message_obj_->IsTheHole()) {
1212         HandleScope scope(this);
1213         Handle<Object> message_obj(thread_local_top_.pending_message_obj_,
1214                                    this);
1215         if (!thread_local_top_.pending_message_script_->IsTheHole()) {
1216           Handle<Script> script(
1217               Script::cast(thread_local_top_.pending_message_script_));
1218           int start_pos = thread_local_top_.pending_message_start_pos_;
1219           int end_pos = thread_local_top_.pending_message_end_pos_;
1220           MessageLocation location(script, start_pos, end_pos);
1221           MessageHandler::ReportMessage(this, &location, message_obj);
1222         } else {
1223           MessageHandler::ReportMessage(this, NULL, message_obj);
1224         }
1225       }
1226     }
1227   }
1228   if (can_clear_message) clear_pending_message();
1229 }
1230 
1231 
GetMessageLocation()1232 MessageLocation Isolate::GetMessageLocation() {
1233   DCHECK(has_pending_exception());
1234 
1235   if (thread_local_top_.pending_exception_ != heap()->termination_exception() &&
1236       thread_local_top_.has_pending_message_ &&
1237       !thread_local_top_.pending_message_obj_->IsTheHole() &&
1238       !thread_local_top_.pending_message_obj_->IsTheHole()) {
1239     Handle<Script> script(
1240         Script::cast(thread_local_top_.pending_message_script_));
1241     int start_pos = thread_local_top_.pending_message_start_pos_;
1242     int end_pos = thread_local_top_.pending_message_end_pos_;
1243     return MessageLocation(script, start_pos, end_pos);
1244   }
1245 
1246   return MessageLocation();
1247 }
1248 
1249 
OptionalRescheduleException(bool is_bottom_call)1250 bool Isolate::OptionalRescheduleException(bool is_bottom_call) {
1251   DCHECK(has_pending_exception());
1252   PropagatePendingExceptionToExternalTryCatch();
1253 
1254   bool is_termination_exception =
1255       pending_exception() == heap_.termination_exception();
1256 
1257   // Do not reschedule the exception if this is the bottom call.
1258   bool clear_exception = is_bottom_call;
1259 
1260   if (is_termination_exception) {
1261     if (is_bottom_call) {
1262       thread_local_top()->external_caught_exception_ = false;
1263       clear_pending_exception();
1264       return false;
1265     }
1266   } else if (thread_local_top()->external_caught_exception_) {
1267     // If the exception is externally caught, clear it if there are no
1268     // JavaScript frames on the way to the C++ frame that has the
1269     // external handler.
1270     DCHECK(thread_local_top()->try_catch_handler_address() != NULL);
1271     Address external_handler_address =
1272         thread_local_top()->try_catch_handler_address();
1273     JavaScriptFrameIterator it(this);
1274     if (it.done() || (it.frame()->sp() > external_handler_address)) {
1275       clear_exception = true;
1276     }
1277   }
1278 
1279   // Clear the exception if needed.
1280   if (clear_exception) {
1281     thread_local_top()->external_caught_exception_ = false;
1282     clear_pending_exception();
1283     return false;
1284   }
1285 
1286   // Reschedule the exception.
1287   thread_local_top()->scheduled_exception_ = pending_exception();
1288   clear_pending_exception();
1289   return true;
1290 }
1291 
1292 
PushPromise(Handle<JSObject> promise)1293 void Isolate::PushPromise(Handle<JSObject> promise) {
1294   ThreadLocalTop* tltop = thread_local_top();
1295   PromiseOnStack* prev = tltop->promise_on_stack_;
1296   StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop));
1297   Handle<JSObject> global_handle =
1298       Handle<JSObject>::cast(global_handles()->Create(*promise));
1299   tltop->promise_on_stack_ = new PromiseOnStack(handler, global_handle, prev);
1300 }
1301 
1302 
PopPromise()1303 void Isolate::PopPromise() {
1304   ThreadLocalTop* tltop = thread_local_top();
1305   if (tltop->promise_on_stack_ == NULL) return;
1306   PromiseOnStack* prev = tltop->promise_on_stack_->prev();
1307   Handle<Object> global_handle = tltop->promise_on_stack_->promise();
1308   delete tltop->promise_on_stack_;
1309   tltop->promise_on_stack_ = prev;
1310   global_handles()->Destroy(global_handle.location());
1311 }
1312 
1313 
GetPromiseOnStackOnThrow()1314 Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
1315   Handle<Object> undefined = factory()->undefined_value();
1316   ThreadLocalTop* tltop = thread_local_top();
1317   if (tltop->promise_on_stack_ == NULL) return undefined;
1318   StackHandler* promise_try = tltop->promise_on_stack_->handler();
1319   // Find the top-most try-catch handler.
1320   StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop));
1321   do {
1322     if (handler == promise_try) {
1323       // Mark the pushed try-catch handler to prevent a later duplicate event
1324       // triggered with the following reject.
1325       return tltop->promise_on_stack_->promise();
1326     }
1327     handler = handler->next();
1328     // Throwing inside a Promise can be intercepted by an inner try-catch, so
1329     // we stop at the first try-catch handler.
1330   } while (handler != NULL && !handler->is_catch());
1331   return undefined;
1332 }
1333 
1334 
SetCaptureStackTraceForUncaughtExceptions(bool capture,int frame_limit,StackTrace::StackTraceOptions options)1335 void Isolate::SetCaptureStackTraceForUncaughtExceptions(
1336       bool capture,
1337       int frame_limit,
1338       StackTrace::StackTraceOptions options) {
1339   capture_stack_trace_for_uncaught_exceptions_ = capture;
1340   stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit;
1341   stack_trace_for_uncaught_exceptions_options_ = options;
1342 }
1343 
1344 
native_context()1345 Handle<Context> Isolate::native_context() {
1346   return handle(context()->native_context());
1347 }
1348 
1349 
global_context()1350 Handle<Context> Isolate::global_context() {
1351   return handle(context()->global_object()->global_context());
1352 }
1353 
1354 
GetCallingNativeContext()1355 Handle<Context> Isolate::GetCallingNativeContext() {
1356   JavaScriptFrameIterator it(this);
1357   if (debug_->in_debug_scope()) {
1358     while (!it.done()) {
1359       JavaScriptFrame* frame = it.frame();
1360       Context* context = Context::cast(frame->context());
1361       if (context->native_context() == *debug_->debug_context()) {
1362         it.Advance();
1363       } else {
1364         break;
1365       }
1366     }
1367   }
1368   if (it.done()) return Handle<Context>::null();
1369   JavaScriptFrame* frame = it.frame();
1370   Context* context = Context::cast(frame->context());
1371   return Handle<Context>(context->native_context());
1372 }
1373 
1374 
ArchiveThread(char * to)1375 char* Isolate::ArchiveThread(char* to) {
1376   MemCopy(to, reinterpret_cast<char*>(thread_local_top()),
1377           sizeof(ThreadLocalTop));
1378   InitializeThreadLocal();
1379   clear_pending_exception();
1380   clear_pending_message();
1381   clear_scheduled_exception();
1382   return to + sizeof(ThreadLocalTop);
1383 }
1384 
1385 
RestoreThread(char * from)1386 char* Isolate::RestoreThread(char* from) {
1387   MemCopy(reinterpret_cast<char*>(thread_local_top()), from,
1388           sizeof(ThreadLocalTop));
1389 // This might be just paranoia, but it seems to be needed in case a
1390 // thread_local_top_ is restored on a separate OS thread.
1391 #ifdef USE_SIMULATOR
1392   thread_local_top()->simulator_ = Simulator::current(this);
1393 #endif
1394   DCHECK(context() == NULL || context()->IsContext());
1395   return from + sizeof(ThreadLocalTop);
1396 }
1397 
1398 
ThreadDataTable()1399 Isolate::ThreadDataTable::ThreadDataTable()
1400     : list_(NULL) {
1401 }
1402 
1403 
~ThreadDataTable()1404 Isolate::ThreadDataTable::~ThreadDataTable() {
1405   // TODO(svenpanne) The assertion below would fire if an embedder does not
1406   // cleanly dispose all Isolates before disposing v8, so we are conservative
1407   // and leave it out for now.
1408   // DCHECK_EQ(NULL, list_);
1409 }
1410 
1411 
~PerIsolateThreadData()1412 Isolate::PerIsolateThreadData::~PerIsolateThreadData() {
1413 #if defined(USE_SIMULATOR)
1414   delete simulator_;
1415 #endif
1416 }
1417 
1418 
1419 Isolate::PerIsolateThreadData*
Lookup(Isolate * isolate,ThreadId thread_id)1420     Isolate::ThreadDataTable::Lookup(Isolate* isolate,
1421                                      ThreadId thread_id) {
1422   for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) {
1423     if (data->Matches(isolate, thread_id)) return data;
1424   }
1425   return NULL;
1426 }
1427 
1428 
Insert(Isolate::PerIsolateThreadData * data)1429 void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) {
1430   if (list_ != NULL) list_->prev_ = data;
1431   data->next_ = list_;
1432   list_ = data;
1433 }
1434 
1435 
Remove(PerIsolateThreadData * data)1436 void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
1437   if (list_ == data) list_ = data->next_;
1438   if (data->next_ != NULL) data->next_->prev_ = data->prev_;
1439   if (data->prev_ != NULL) data->prev_->next_ = data->next_;
1440   delete data;
1441 }
1442 
1443 
RemoveAllThreads(Isolate * isolate)1444 void Isolate::ThreadDataTable::RemoveAllThreads(Isolate* isolate) {
1445   PerIsolateThreadData* data = list_;
1446   while (data != NULL) {
1447     PerIsolateThreadData* next = data->next_;
1448     if (data->isolate() == isolate) Remove(data);
1449     data = next;
1450   }
1451 }
1452 
1453 
1454 #ifdef DEBUG
1455 #define TRACE_ISOLATE(tag)                                              \
1456   do {                                                                  \
1457     if (FLAG_trace_isolates) {                                          \
1458       PrintF("Isolate %p (id %d)" #tag "\n",                            \
1459              reinterpret_cast<void*>(this), id());                      \
1460     }                                                                   \
1461   } while (false)
1462 #else
1463 #define TRACE_ISOLATE(tag)
1464 #endif
1465 
1466 
Isolate()1467 Isolate::Isolate()
1468     : embedder_data_(),
1469       state_(UNINITIALIZED),
1470       entry_stack_(NULL),
1471       stack_trace_nesting_level_(0),
1472       incomplete_message_(NULL),
1473       bootstrapper_(NULL),
1474       runtime_profiler_(NULL),
1475       compilation_cache_(NULL),
1476       counters_(NULL),
1477       code_range_(NULL),
1478       logger_(NULL),
1479       stats_table_(NULL),
1480       stub_cache_(NULL),
1481       code_aging_helper_(NULL),
1482       deoptimizer_data_(NULL),
1483       materialized_object_store_(NULL),
1484       capture_stack_trace_for_uncaught_exceptions_(false),
1485       stack_trace_for_uncaught_exceptions_frame_limit_(0),
1486       stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview),
1487       memory_allocator_(NULL),
1488       keyed_lookup_cache_(NULL),
1489       context_slot_cache_(NULL),
1490       descriptor_lookup_cache_(NULL),
1491       handle_scope_implementer_(NULL),
1492       unicode_cache_(NULL),
1493       runtime_zone_(this),
1494       inner_pointer_to_code_cache_(NULL),
1495       write_iterator_(NULL),
1496       global_handles_(NULL),
1497       eternal_handles_(NULL),
1498       thread_manager_(NULL),
1499       has_installed_extensions_(false),
1500       string_tracker_(NULL),
1501       regexp_stack_(NULL),
1502       date_cache_(NULL),
1503       call_descriptor_data_(NULL),
1504       // TODO(bmeurer) Initialized lazily because it depends on flags; can
1505       // be fixed once the default isolate cleanup is done.
1506       random_number_generator_(NULL),
1507       serializer_enabled_(false),
1508       has_fatal_error_(false),
1509       initialized_from_snapshot_(false),
1510       cpu_profiler_(NULL),
1511       heap_profiler_(NULL),
1512       function_entry_hook_(NULL),
1513       deferred_handles_head_(NULL),
1514       optimizing_compiler_thread_(NULL),
1515       sweeper_thread_(NULL),
1516       num_sweeper_threads_(0),
1517       stress_deopt_count_(0),
1518       next_optimization_id_(0),
1519       use_counter_callback_(NULL) {
1520   {
1521     base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
1522     CHECK(thread_data_table_);
1523   }
1524   id_ = base::NoBarrier_AtomicIncrement(&isolate_counter_, 1);
1525   TRACE_ISOLATE(constructor);
1526 
1527   memset(isolate_addresses_, 0,
1528       sizeof(isolate_addresses_[0]) * (kIsolateAddressCount + 1));
1529 
1530   heap_.isolate_ = this;
1531   stack_guard_.isolate_ = this;
1532 
1533   // ThreadManager is initialized early to support locking an isolate
1534   // before it is entered.
1535   thread_manager_ = new ThreadManager();
1536   thread_manager_->isolate_ = this;
1537 
1538 #ifdef DEBUG
1539   // heap_histograms_ initializes itself.
1540   memset(&js_spill_information_, 0, sizeof(js_spill_information_));
1541 #endif
1542 
1543   handle_scope_data_.Initialize();
1544 
1545 #define ISOLATE_INIT_EXECUTE(type, name, initial_value)                        \
1546   name##_ = (initial_value);
1547   ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE)
1548 #undef ISOLATE_INIT_EXECUTE
1549 
1550 #define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length)                         \
1551   memset(name##_, 0, sizeof(type) * length);
1552   ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE)
1553 #undef ISOLATE_INIT_ARRAY_EXECUTE
1554 
1555   InitializeLoggingAndCounters();
1556   debug_ = new Debug(this);
1557 }
1558 
1559 
TearDown()1560 void Isolate::TearDown() {
1561   TRACE_ISOLATE(tear_down);
1562 
1563   // Temporarily set this isolate as current so that various parts of
1564   // the isolate can access it in their destructors without having a
1565   // direct pointer. We don't use Enter/Exit here to avoid
1566   // initializing the thread data.
1567   PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData();
1568   Isolate* saved_isolate = UncheckedCurrent();
1569   SetIsolateThreadLocals(this, NULL);
1570 
1571   Deinit();
1572 
1573   {
1574     base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
1575     thread_data_table_->RemoveAllThreads(this);
1576   }
1577 
1578   if (serialize_partial_snapshot_cache_ != NULL) {
1579     delete[] serialize_partial_snapshot_cache_;
1580     serialize_partial_snapshot_cache_ = NULL;
1581   }
1582 
1583   delete this;
1584 
1585   // Restore the previous current isolate.
1586   SetIsolateThreadLocals(saved_isolate, saved_data);
1587 }
1588 
1589 
GlobalTearDown()1590 void Isolate::GlobalTearDown() {
1591   delete thread_data_table_;
1592   thread_data_table_ = NULL;
1593 }
1594 
1595 
Deinit()1596 void Isolate::Deinit() {
1597   if (state_ == INITIALIZED) {
1598     TRACE_ISOLATE(deinit);
1599 
1600     debug()->Unload();
1601 
1602     FreeThreadResources();
1603 
1604     if (concurrent_recompilation_enabled()) {
1605       optimizing_compiler_thread_->Stop();
1606       delete optimizing_compiler_thread_;
1607       optimizing_compiler_thread_ = NULL;
1608     }
1609 
1610     for (int i = 0; i < num_sweeper_threads_; i++) {
1611       sweeper_thread_[i]->Stop();
1612       delete sweeper_thread_[i];
1613       sweeper_thread_[i] = NULL;
1614     }
1615     delete[] sweeper_thread_;
1616     sweeper_thread_ = NULL;
1617 
1618     if (FLAG_job_based_sweeping &&
1619         heap_.mark_compact_collector()->sweeping_in_progress()) {
1620       heap_.mark_compact_collector()->EnsureSweepingCompleted();
1621     }
1622 
1623     if (FLAG_turbo_stats) GetTStatistics()->Print("TurboFan");
1624     if (FLAG_hydrogen_stats) GetHStatistics()->Print("Hydrogen");
1625 
1626     if (FLAG_print_deopt_stress) {
1627       PrintF(stdout, "=== Stress deopt counter: %u\n", stress_deopt_count_);
1628     }
1629 
1630     // We must stop the logger before we tear down other components.
1631     Sampler* sampler = logger_->sampler();
1632     if (sampler && sampler->IsActive()) sampler->Stop();
1633 
1634     delete deoptimizer_data_;
1635     deoptimizer_data_ = NULL;
1636     builtins_.TearDown();
1637     bootstrapper_->TearDown();
1638 
1639     if (runtime_profiler_ != NULL) {
1640       delete runtime_profiler_;
1641       runtime_profiler_ = NULL;
1642     }
1643     heap_.TearDown();
1644     logger_->TearDown();
1645 
1646     delete heap_profiler_;
1647     heap_profiler_ = NULL;
1648     delete cpu_profiler_;
1649     cpu_profiler_ = NULL;
1650 
1651     // The default isolate is re-initializable due to legacy API.
1652     state_ = UNINITIALIZED;
1653   }
1654 }
1655 
1656 
PushToPartialSnapshotCache(Object * obj)1657 void Isolate::PushToPartialSnapshotCache(Object* obj) {
1658   int length = serialize_partial_snapshot_cache_length();
1659   int capacity = serialize_partial_snapshot_cache_capacity();
1660 
1661   if (length >= capacity) {
1662     int new_capacity = static_cast<int>((capacity + 10) * 1.2);
1663     Object** new_array = new Object*[new_capacity];
1664     for (int i = 0; i < length; i++) {
1665       new_array[i] = serialize_partial_snapshot_cache()[i];
1666     }
1667     if (capacity != 0) delete[] serialize_partial_snapshot_cache();
1668     set_serialize_partial_snapshot_cache(new_array);
1669     set_serialize_partial_snapshot_cache_capacity(new_capacity);
1670   }
1671 
1672   serialize_partial_snapshot_cache()[length] = obj;
1673   set_serialize_partial_snapshot_cache_length(length + 1);
1674 }
1675 
1676 
SetIsolateThreadLocals(Isolate * isolate,PerIsolateThreadData * data)1677 void Isolate::SetIsolateThreadLocals(Isolate* isolate,
1678                                      PerIsolateThreadData* data) {
1679   base::Thread::SetThreadLocal(isolate_key_, isolate);
1680   base::Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
1681 }
1682 
1683 
~Isolate()1684 Isolate::~Isolate() {
1685   TRACE_ISOLATE(destructor);
1686 
1687   // Has to be called while counters_ are still alive
1688   runtime_zone_.DeleteKeptSegment();
1689 
1690   // The entry stack must be empty when we get here.
1691   DCHECK(entry_stack_ == NULL || entry_stack_->previous_item == NULL);
1692 
1693   delete entry_stack_;
1694   entry_stack_ = NULL;
1695 
1696   delete unicode_cache_;
1697   unicode_cache_ = NULL;
1698 
1699   delete date_cache_;
1700   date_cache_ = NULL;
1701 
1702   delete[] call_descriptor_data_;
1703   call_descriptor_data_ = NULL;
1704 
1705   delete regexp_stack_;
1706   regexp_stack_ = NULL;
1707 
1708   delete descriptor_lookup_cache_;
1709   descriptor_lookup_cache_ = NULL;
1710   delete context_slot_cache_;
1711   context_slot_cache_ = NULL;
1712   delete keyed_lookup_cache_;
1713   keyed_lookup_cache_ = NULL;
1714 
1715   delete stub_cache_;
1716   stub_cache_ = NULL;
1717   delete code_aging_helper_;
1718   code_aging_helper_ = NULL;
1719   delete stats_table_;
1720   stats_table_ = NULL;
1721 
1722   delete materialized_object_store_;
1723   materialized_object_store_ = NULL;
1724 
1725   delete logger_;
1726   logger_ = NULL;
1727 
1728   delete counters_;
1729   counters_ = NULL;
1730 
1731   delete handle_scope_implementer_;
1732   handle_scope_implementer_ = NULL;
1733 
1734   delete compilation_cache_;
1735   compilation_cache_ = NULL;
1736   delete bootstrapper_;
1737   bootstrapper_ = NULL;
1738   delete inner_pointer_to_code_cache_;
1739   inner_pointer_to_code_cache_ = NULL;
1740   delete write_iterator_;
1741   write_iterator_ = NULL;
1742 
1743   delete thread_manager_;
1744   thread_manager_ = NULL;
1745 
1746   delete string_tracker_;
1747   string_tracker_ = NULL;
1748 
1749   delete memory_allocator_;
1750   memory_allocator_ = NULL;
1751   delete code_range_;
1752   code_range_ = NULL;
1753   delete global_handles_;
1754   global_handles_ = NULL;
1755   delete eternal_handles_;
1756   eternal_handles_ = NULL;
1757 
1758   delete string_stream_debug_object_cache_;
1759   string_stream_debug_object_cache_ = NULL;
1760 
1761   delete external_reference_table_;
1762   external_reference_table_ = NULL;
1763 
1764   delete random_number_generator_;
1765   random_number_generator_ = NULL;
1766 
1767   delete debug_;
1768   debug_ = NULL;
1769 }
1770 
1771 
InitializeThreadLocal()1772 void Isolate::InitializeThreadLocal() {
1773   thread_local_top_.isolate_ = this;
1774   thread_local_top_.Initialize();
1775 }
1776 
1777 
PropagatePendingExceptionToExternalTryCatch()1778 bool Isolate::PropagatePendingExceptionToExternalTryCatch() {
1779   DCHECK(has_pending_exception());
1780 
1781   bool has_external_try_catch = HasExternalTryCatch();
1782   if (!has_external_try_catch) {
1783     thread_local_top_.external_caught_exception_ = false;
1784     return true;
1785   }
1786 
1787   bool catchable_by_js = is_catchable_by_javascript(pending_exception());
1788   if (catchable_by_js && IsFinallyOnTop()) {
1789     thread_local_top_.external_caught_exception_ = false;
1790     return false;
1791   }
1792 
1793   thread_local_top_.external_caught_exception_ = true;
1794   if (thread_local_top_.pending_exception_ == heap()->termination_exception()) {
1795     try_catch_handler()->can_continue_ = false;
1796     try_catch_handler()->has_terminated_ = true;
1797     try_catch_handler()->exception_ = heap()->null_value();
1798   } else {
1799     v8::TryCatch* handler = try_catch_handler();
1800     DCHECK(thread_local_top_.pending_message_obj_->IsJSMessageObject() ||
1801            thread_local_top_.pending_message_obj_->IsTheHole());
1802     DCHECK(thread_local_top_.pending_message_script_->IsScript() ||
1803            thread_local_top_.pending_message_script_->IsTheHole());
1804     handler->can_continue_ = true;
1805     handler->has_terminated_ = false;
1806     handler->exception_ = pending_exception();
1807     // Propagate to the external try-catch only if we got an actual message.
1808     if (thread_local_top_.pending_message_obj_->IsTheHole()) return true;
1809 
1810     handler->message_obj_ = thread_local_top_.pending_message_obj_;
1811     handler->message_script_ = thread_local_top_.pending_message_script_;
1812     handler->message_start_pos_ = thread_local_top_.pending_message_start_pos_;
1813     handler->message_end_pos_ = thread_local_top_.pending_message_end_pos_;
1814   }
1815   return true;
1816 }
1817 
1818 
InitializeLoggingAndCounters()1819 void Isolate::InitializeLoggingAndCounters() {
1820   if (logger_ == NULL) {
1821     logger_ = new Logger(this);
1822   }
1823   if (counters_ == NULL) {
1824     counters_ = new Counters(this);
1825   }
1826 }
1827 
1828 
Init(Deserializer * des)1829 bool Isolate::Init(Deserializer* des) {
1830   DCHECK(state_ != INITIALIZED);
1831   TRACE_ISOLATE(init);
1832 
1833   stress_deopt_count_ = FLAG_deopt_every_n_times;
1834 
1835   has_fatal_error_ = false;
1836 
1837   if (function_entry_hook() != NULL) {
1838     // When function entry hooking is in effect, we have to create the code
1839     // stubs from scratch to get entry hooks, rather than loading the previously
1840     // generated stubs from disk.
1841     // If this assert fires, the initialization path has regressed.
1842     DCHECK(des == NULL);
1843   }
1844 
1845   // The initialization process does not handle memory exhaustion.
1846   DisallowAllocationFailure disallow_allocation_failure(this);
1847 
1848   memory_allocator_ = new MemoryAllocator(this);
1849   code_range_ = new CodeRange(this);
1850 
1851   // Safe after setting Heap::isolate_, and initializing StackGuard
1852   heap_.SetStackLimits();
1853 
1854 #define ASSIGN_ELEMENT(CamelName, hacker_name)                  \
1855   isolate_addresses_[Isolate::k##CamelName##Address] =          \
1856       reinterpret_cast<Address>(hacker_name##_address());
1857   FOR_EACH_ISOLATE_ADDRESS_NAME(ASSIGN_ELEMENT)
1858 #undef ASSIGN_ELEMENT
1859 
1860   string_tracker_ = new StringTracker();
1861   string_tracker_->isolate_ = this;
1862   compilation_cache_ = new CompilationCache(this);
1863   keyed_lookup_cache_ = new KeyedLookupCache();
1864   context_slot_cache_ = new ContextSlotCache();
1865   descriptor_lookup_cache_ = new DescriptorLookupCache();
1866   unicode_cache_ = new UnicodeCache();
1867   inner_pointer_to_code_cache_ = new InnerPointerToCodeCache(this);
1868   write_iterator_ = new ConsStringIteratorOp();
1869   global_handles_ = new GlobalHandles(this);
1870   eternal_handles_ = new EternalHandles();
1871   bootstrapper_ = new Bootstrapper(this);
1872   handle_scope_implementer_ = new HandleScopeImplementer(this);
1873   stub_cache_ = new StubCache(this);
1874   materialized_object_store_ = new MaterializedObjectStore(this);
1875   regexp_stack_ = new RegExpStack();
1876   regexp_stack_->isolate_ = this;
1877   date_cache_ = new DateCache();
1878   call_descriptor_data_ =
1879       new CallInterfaceDescriptorData[CallDescriptors::NUMBER_OF_DESCRIPTORS];
1880   cpu_profiler_ = new CpuProfiler(this);
1881   heap_profiler_ = new HeapProfiler(heap());
1882 
1883   // Enable logging before setting up the heap
1884   logger_->SetUp(this);
1885 
1886   // Initialize other runtime facilities
1887 #if defined(USE_SIMULATOR)
1888 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || \
1889     V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
1890   Simulator::Initialize(this);
1891 #endif
1892 #endif
1893 
1894   code_aging_helper_ = new CodeAgingHelper();
1895 
1896   { // NOLINT
1897     // Ensure that the thread has a valid stack guard.  The v8::Locker object
1898     // will ensure this too, but we don't have to use lockers if we are only
1899     // using one thread.
1900     ExecutionAccess lock(this);
1901     stack_guard_.InitThread(lock);
1902   }
1903 
1904   // SetUp the object heap.
1905   DCHECK(!heap_.HasBeenSetUp());
1906   if (!heap_.SetUp()) {
1907     V8::FatalProcessOutOfMemory("heap setup");
1908     return false;
1909   }
1910 
1911   deoptimizer_data_ = new DeoptimizerData(memory_allocator_);
1912 
1913   const bool create_heap_objects = (des == NULL);
1914   if (create_heap_objects && !heap_.CreateHeapObjects()) {
1915     V8::FatalProcessOutOfMemory("heap object creation");
1916     return false;
1917   }
1918 
1919   if (create_heap_objects) {
1920     // Terminate the cache array with the sentinel so we can iterate.
1921     PushToPartialSnapshotCache(heap_.undefined_value());
1922   }
1923 
1924   InitializeThreadLocal();
1925 
1926   bootstrapper_->Initialize(create_heap_objects);
1927   builtins_.SetUp(this, create_heap_objects);
1928 
1929   if (FLAG_log_internal_timer_events) {
1930     set_event_logger(Logger::DefaultTimerEventsLogger);
1931   } else {
1932     set_event_logger(Logger::EmptyTimerEventsLogger);
1933   }
1934 
1935   // Set default value if not yet set.
1936   // TODO(yangguo): move this to ResourceConstraints::ConfigureDefaults
1937   // once ResourceConstraints becomes an argument to the Isolate constructor.
1938   if (max_available_threads_ < 1) {
1939     // Choose the default between 1 and 4.
1940     max_available_threads_ =
1941         Max(Min(base::SysInfo::NumberOfProcessors(), 4), 1);
1942   }
1943 
1944   if (!FLAG_job_based_sweeping) {
1945     num_sweeper_threads_ =
1946         SweeperThread::NumberOfThreads(max_available_threads_);
1947   }
1948 
1949   if (FLAG_trace_hydrogen || FLAG_trace_hydrogen_stubs) {
1950     PrintF("Concurrent recompilation has been disabled for tracing.\n");
1951   } else if (OptimizingCompilerThread::Enabled(max_available_threads_)) {
1952     optimizing_compiler_thread_ = new OptimizingCompilerThread(this);
1953     optimizing_compiler_thread_->Start();
1954   }
1955 
1956   if (num_sweeper_threads_ > 0) {
1957     sweeper_thread_ = new SweeperThread*[num_sweeper_threads_];
1958     for (int i = 0; i < num_sweeper_threads_; i++) {
1959       sweeper_thread_[i] = new SweeperThread(this);
1960       sweeper_thread_[i]->Start();
1961     }
1962   }
1963 
1964   // If we are deserializing, read the state into the now-empty heap.
1965   if (!create_heap_objects) {
1966     des->Deserialize(this);
1967   }
1968   stub_cache_->Initialize();
1969 
1970   // Finish initialization of ThreadLocal after deserialization is done.
1971   clear_pending_exception();
1972   clear_pending_message();
1973   clear_scheduled_exception();
1974 
1975   // Deserializing may put strange things in the root array's copy of the
1976   // stack guard.
1977   heap_.SetStackLimits();
1978 
1979   // Quiet the heap NaN if needed on target platform.
1980   if (!create_heap_objects) Assembler::QuietNaN(heap_.nan_value());
1981 
1982   runtime_profiler_ = new RuntimeProfiler(this);
1983 
1984   // If we are deserializing, log non-function code objects and compiled
1985   // functions found in the snapshot.
1986   if (!create_heap_objects &&
1987       (FLAG_log_code ||
1988        FLAG_ll_prof ||
1989        FLAG_perf_jit_prof ||
1990        FLAG_perf_basic_prof ||
1991        logger_->is_logging_code_events())) {
1992     HandleScope scope(this);
1993     LOG(this, LogCodeObjects());
1994     LOG(this, LogCompiledFunctions());
1995   }
1996 
1997   CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, embedder_data_)),
1998            Internals::kIsolateEmbedderDataOffset);
1999   CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.roots_)),
2000            Internals::kIsolateRootsOffset);
2001   CHECK_EQ(static_cast<int>(
2002                OFFSET_OF(Isolate, heap_.amount_of_external_allocated_memory_)),
2003            Internals::kAmountOfExternalAllocatedMemoryOffset);
2004   CHECK_EQ(static_cast<int>(OFFSET_OF(
2005                Isolate,
2006                heap_.amount_of_external_allocated_memory_at_last_global_gc_)),
2007            Internals::kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset);
2008 
2009   state_ = INITIALIZED;
2010   time_millis_at_init_ = base::OS::TimeCurrentMillis();
2011 
2012   if (!create_heap_objects) {
2013     // Now that the heap is consistent, it's OK to generate the code for the
2014     // deopt entry table that might have been referred to by optimized code in
2015     // the snapshot.
2016     HandleScope scope(this);
2017     Deoptimizer::EnsureCodeForDeoptimizationEntry(
2018         this,
2019         Deoptimizer::LAZY,
2020         kDeoptTableSerializeEntryCount - 1);
2021   }
2022 
2023   if (!serializer_enabled()) {
2024     // Ensure that all stubs which need to be generated ahead of time, but
2025     // cannot be serialized into the snapshot have been generated.
2026     HandleScope scope(this);
2027     CodeStub::GenerateFPStubs(this);
2028     StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(this);
2029     StubFailureTrampolineStub::GenerateAheadOfTime(this);
2030   }
2031 
2032   initialized_from_snapshot_ = (des != NULL);
2033 
2034   return true;
2035 }
2036 
2037 
2038 // Initialized lazily to allow early
2039 // v8::V8::SetAddHistogramSampleFunction calls.
stats_table()2040 StatsTable* Isolate::stats_table() {
2041   if (stats_table_ == NULL) {
2042     stats_table_ = new StatsTable;
2043   }
2044   return stats_table_;
2045 }
2046 
2047 
Enter()2048 void Isolate::Enter() {
2049   Isolate* current_isolate = NULL;
2050   PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
2051   if (current_data != NULL) {
2052     current_isolate = current_data->isolate_;
2053     DCHECK(current_isolate != NULL);
2054     if (current_isolate == this) {
2055       DCHECK(Current() == this);
2056       DCHECK(entry_stack_ != NULL);
2057       DCHECK(entry_stack_->previous_thread_data == NULL ||
2058              entry_stack_->previous_thread_data->thread_id().Equals(
2059                  ThreadId::Current()));
2060       // Same thread re-enters the isolate, no need to re-init anything.
2061       entry_stack_->entry_count++;
2062       return;
2063     }
2064   }
2065 
2066   PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
2067   DCHECK(data != NULL);
2068   DCHECK(data->isolate_ == this);
2069 
2070   EntryStackItem* item = new EntryStackItem(current_data,
2071                                             current_isolate,
2072                                             entry_stack_);
2073   entry_stack_ = item;
2074 
2075   SetIsolateThreadLocals(this, data);
2076 
2077   // In case it's the first time some thread enters the isolate.
2078   set_thread_id(data->thread_id());
2079 }
2080 
2081 
Exit()2082 void Isolate::Exit() {
2083   DCHECK(entry_stack_ != NULL);
2084   DCHECK(entry_stack_->previous_thread_data == NULL ||
2085          entry_stack_->previous_thread_data->thread_id().Equals(
2086              ThreadId::Current()));
2087 
2088   if (--entry_stack_->entry_count > 0) return;
2089 
2090   DCHECK(CurrentPerIsolateThreadData() != NULL);
2091   DCHECK(CurrentPerIsolateThreadData()->isolate_ == this);
2092 
2093   // Pop the stack.
2094   EntryStackItem* item = entry_stack_;
2095   entry_stack_ = item->previous_item;
2096 
2097   PerIsolateThreadData* previous_thread_data = item->previous_thread_data;
2098   Isolate* previous_isolate = item->previous_isolate;
2099 
2100   delete item;
2101 
2102   // Reinit the current thread for the isolate it was running before this one.
2103   SetIsolateThreadLocals(previous_isolate, previous_thread_data);
2104 }
2105 
2106 
LinkDeferredHandles(DeferredHandles * deferred)2107 void Isolate::LinkDeferredHandles(DeferredHandles* deferred) {
2108   deferred->next_ = deferred_handles_head_;
2109   if (deferred_handles_head_ != NULL) {
2110     deferred_handles_head_->previous_ = deferred;
2111   }
2112   deferred_handles_head_ = deferred;
2113 }
2114 
2115 
UnlinkDeferredHandles(DeferredHandles * deferred)2116 void Isolate::UnlinkDeferredHandles(DeferredHandles* deferred) {
2117 #ifdef DEBUG
2118   // In debug mode assert that the linked list is well-formed.
2119   DeferredHandles* deferred_iterator = deferred;
2120   while (deferred_iterator->previous_ != NULL) {
2121     deferred_iterator = deferred_iterator->previous_;
2122   }
2123   DCHECK(deferred_handles_head_ == deferred_iterator);
2124 #endif
2125   if (deferred_handles_head_ == deferred) {
2126     deferred_handles_head_ = deferred_handles_head_->next_;
2127   }
2128   if (deferred->next_ != NULL) {
2129     deferred->next_->previous_ = deferred->previous_;
2130   }
2131   if (deferred->previous_ != NULL) {
2132     deferred->previous_->next_ = deferred->next_;
2133   }
2134 }
2135 
2136 
GetHStatistics()2137 HStatistics* Isolate::GetHStatistics() {
2138   if (hstatistics() == NULL) set_hstatistics(new HStatistics());
2139   return hstatistics();
2140 }
2141 
2142 
GetTStatistics()2143 HStatistics* Isolate::GetTStatistics() {
2144   if (tstatistics() == NULL) set_tstatistics(new HStatistics());
2145   return tstatistics();
2146 }
2147 
2148 
GetHTracer()2149 HTracer* Isolate::GetHTracer() {
2150   if (htracer() == NULL) set_htracer(new HTracer(id()));
2151   return htracer();
2152 }
2153 
2154 
GetCodeTracer()2155 CodeTracer* Isolate::GetCodeTracer() {
2156   if (code_tracer() == NULL) set_code_tracer(new CodeTracer(id()));
2157   return code_tracer();
2158 }
2159 
2160 
get_initial_js_array_map(ElementsKind kind)2161 Map* Isolate::get_initial_js_array_map(ElementsKind kind) {
2162   Context* native_context = context()->native_context();
2163   Object* maybe_map_array = native_context->js_array_maps();
2164   if (!maybe_map_array->IsUndefined()) {
2165     Object* maybe_transitioned_map =
2166         FixedArray::cast(maybe_map_array)->get(kind);
2167     if (!maybe_transitioned_map->IsUndefined()) {
2168       return Map::cast(maybe_transitioned_map);
2169     }
2170   }
2171   return NULL;
2172 }
2173 
2174 
use_crankshaft() const2175 bool Isolate::use_crankshaft() const {
2176   return FLAG_crankshaft &&
2177          !serializer_enabled_ &&
2178          CpuFeatures::SupportsCrankshaft();
2179 }
2180 
2181 
IsFastArrayConstructorPrototypeChainIntact()2182 bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
2183   Map* root_array_map =
2184       get_initial_js_array_map(GetInitialFastElementsKind());
2185   DCHECK(root_array_map != NULL);
2186   JSObject* initial_array_proto = JSObject::cast(*initial_array_prototype());
2187 
2188   // Check that the array prototype hasn't been altered WRT empty elements.
2189   if (root_array_map->prototype() != initial_array_proto) return false;
2190   if (initial_array_proto->elements() != heap()->empty_fixed_array()) {
2191     return false;
2192   }
2193 
2194   // Check that the object prototype hasn't been altered WRT empty elements.
2195   JSObject* initial_object_proto = JSObject::cast(*initial_object_prototype());
2196   PrototypeIterator iter(this, initial_array_proto);
2197   if (iter.IsAtEnd() || iter.GetCurrent() != initial_object_proto) {
2198     return false;
2199   }
2200   if (initial_object_proto->elements() != heap()->empty_fixed_array()) {
2201     return false;
2202   }
2203 
2204   iter.Advance();
2205   return iter.IsAtEnd();
2206 }
2207 
2208 
call_descriptor_data(int index)2209 CallInterfaceDescriptorData* Isolate::call_descriptor_data(int index) {
2210   DCHECK(0 <= index && index < CallDescriptors::NUMBER_OF_DESCRIPTORS);
2211   return &call_descriptor_data_[index];
2212 }
2213 
2214 
FindCodeObject(Address a)2215 Object* Isolate::FindCodeObject(Address a) {
2216   return inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(a);
2217 }
2218 
2219 
2220 #ifdef DEBUG
2221 #define ISOLATE_FIELD_OFFSET(type, name, ignored)                       \
2222 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_);
2223 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)2224 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
2225 #undef ISOLATE_FIELD_OFFSET
2226 #endif
2227 
2228 
2229 Handle<JSObject> Isolate::GetSymbolRegistry() {
2230   if (heap()->symbol_registry()->IsUndefined()) {
2231     Handle<Map> map = factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
2232     Handle<JSObject> registry = factory()->NewJSObjectFromMap(map);
2233     heap()->set_symbol_registry(*registry);
2234 
2235     static const char* nested[] = {
2236       "for", "for_api", "for_intern", "keyFor", "private_api", "private_intern"
2237     };
2238     for (unsigned i = 0; i < arraysize(nested); ++i) {
2239       Handle<String> name = factory()->InternalizeUtf8String(nested[i]);
2240       Handle<JSObject> obj = factory()->NewJSObjectFromMap(map);
2241       JSObject::NormalizeProperties(obj, KEEP_INOBJECT_PROPERTIES, 8);
2242       JSObject::SetProperty(registry, name, obj, STRICT).Assert();
2243     }
2244   }
2245   return Handle<JSObject>::cast(factory()->symbol_registry());
2246 }
2247 
2248 
AddCallCompletedCallback(CallCompletedCallback callback)2249 void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
2250   for (int i = 0; i < call_completed_callbacks_.length(); i++) {
2251     if (callback == call_completed_callbacks_.at(i)) return;
2252   }
2253   call_completed_callbacks_.Add(callback);
2254 }
2255 
2256 
RemoveCallCompletedCallback(CallCompletedCallback callback)2257 void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
2258   for (int i = 0; i < call_completed_callbacks_.length(); i++) {
2259     if (callback == call_completed_callbacks_.at(i)) {
2260       call_completed_callbacks_.Remove(i);
2261     }
2262   }
2263 }
2264 
2265 
FireCallCompletedCallback()2266 void Isolate::FireCallCompletedCallback() {
2267   bool has_call_completed_callbacks = !call_completed_callbacks_.is_empty();
2268   bool run_microtasks = autorun_microtasks() && pending_microtask_count();
2269   if (!has_call_completed_callbacks && !run_microtasks) return;
2270 
2271   if (!handle_scope_implementer()->CallDepthIsZero()) return;
2272   if (run_microtasks) RunMicrotasks();
2273   // Fire callbacks.  Increase call depth to prevent recursive callbacks.
2274   v8::Isolate::SuppressMicrotaskExecutionScope suppress(
2275       reinterpret_cast<v8::Isolate*>(this));
2276   for (int i = 0; i < call_completed_callbacks_.length(); i++) {
2277     call_completed_callbacks_.at(i)();
2278   }
2279 }
2280 
2281 
EnqueueMicrotask(Handle<Object> microtask)2282 void Isolate::EnqueueMicrotask(Handle<Object> microtask) {
2283   DCHECK(microtask->IsJSFunction() || microtask->IsCallHandlerInfo());
2284   Handle<FixedArray> queue(heap()->microtask_queue(), this);
2285   int num_tasks = pending_microtask_count();
2286   DCHECK(num_tasks <= queue->length());
2287   if (num_tasks == 0) {
2288     queue = factory()->NewFixedArray(8);
2289     heap()->set_microtask_queue(*queue);
2290   } else if (num_tasks == queue->length()) {
2291     queue = FixedArray::CopySize(queue, num_tasks * 2);
2292     heap()->set_microtask_queue(*queue);
2293   }
2294   DCHECK(queue->get(num_tasks)->IsUndefined());
2295   queue->set(num_tasks, *microtask);
2296   set_pending_microtask_count(num_tasks + 1);
2297 }
2298 
2299 
RunMicrotasks()2300 void Isolate::RunMicrotasks() {
2301   // %RunMicrotasks may be called in mjsunit tests, which violates
2302   // this assertion, hence the check for --allow-natives-syntax.
2303   // TODO(adamk): However, this also fails some layout tests.
2304   //
2305   // DCHECK(FLAG_allow_natives_syntax ||
2306   //        handle_scope_implementer()->CallDepthIsZero());
2307 
2308   // Increase call depth to prevent recursive callbacks.
2309   v8::Isolate::SuppressMicrotaskExecutionScope suppress(
2310       reinterpret_cast<v8::Isolate*>(this));
2311 
2312   while (pending_microtask_count() > 0) {
2313     HandleScope scope(this);
2314     int num_tasks = pending_microtask_count();
2315     Handle<FixedArray> queue(heap()->microtask_queue(), this);
2316     DCHECK(num_tasks <= queue->length());
2317     set_pending_microtask_count(0);
2318     heap()->set_microtask_queue(heap()->empty_fixed_array());
2319 
2320     for (int i = 0; i < num_tasks; i++) {
2321       HandleScope scope(this);
2322       Handle<Object> microtask(queue->get(i), this);
2323       if (microtask->IsJSFunction()) {
2324         Handle<JSFunction> microtask_function =
2325             Handle<JSFunction>::cast(microtask);
2326         SaveContext save(this);
2327         set_context(microtask_function->context()->native_context());
2328         MaybeHandle<Object> maybe_exception;
2329         MaybeHandle<Object> result =
2330             Execution::TryCall(microtask_function, factory()->undefined_value(),
2331                                0, NULL, &maybe_exception);
2332         // If execution is terminating, just bail out.
2333         Handle<Object> exception;
2334         if (result.is_null() && maybe_exception.is_null()) {
2335           // Clear out any remaining callbacks in the queue.
2336           heap()->set_microtask_queue(heap()->empty_fixed_array());
2337           set_pending_microtask_count(0);
2338           return;
2339         }
2340       } else {
2341         Handle<CallHandlerInfo> callback_info =
2342             Handle<CallHandlerInfo>::cast(microtask);
2343         v8::MicrotaskCallback callback =
2344             v8::ToCData<v8::MicrotaskCallback>(callback_info->callback());
2345         void* data = v8::ToCData<void*>(callback_info->data());
2346         callback(data);
2347       }
2348     }
2349   }
2350 }
2351 
2352 
SetUseCounterCallback(v8::Isolate::UseCounterCallback callback)2353 void Isolate::SetUseCounterCallback(v8::Isolate::UseCounterCallback callback) {
2354   DCHECK(!use_counter_callback_);
2355   use_counter_callback_ = callback;
2356 }
2357 
2358 
CountUsage(v8::Isolate::UseCounterFeature feature)2359 void Isolate::CountUsage(v8::Isolate::UseCounterFeature feature) {
2360   if (use_counter_callback_) {
2361     use_counter_callback_(reinterpret_cast<v8::Isolate*>(this), feature);
2362   }
2363 }
2364 
2365 
JsHasOverflowed() const2366 bool StackLimitCheck::JsHasOverflowed() const {
2367   StackGuard* stack_guard = isolate_->stack_guard();
2368 #ifdef USE_SIMULATOR
2369   // The simulator uses a separate JS stack.
2370   Address jssp_address = Simulator::current(isolate_)->get_sp();
2371   uintptr_t jssp = reinterpret_cast<uintptr_t>(jssp_address);
2372   if (jssp < stack_guard->real_jslimit()) return true;
2373 #endif  // USE_SIMULATOR
2374   return GetCurrentStackPosition() < stack_guard->real_climit();
2375 }
2376 
2377 
Intercept(StackGuard::InterruptFlag flag)2378 bool PostponeInterruptsScope::Intercept(StackGuard::InterruptFlag flag) {
2379   // First check whether the previous scope intercepts.
2380   if (prev_ && prev_->Intercept(flag)) return true;
2381   // Then check whether this scope intercepts.
2382   if ((flag & intercept_mask_)) {
2383     intercepted_flags_ |= flag;
2384     return true;
2385   }
2386   return false;
2387 }
2388 
2389 } }  // namespace v8::internal
2390