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