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