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.
10 #include "src/base/platform/platform.h"
11 #include "src/base/sys-info.h"
12 #include "src/base/utils/random-number-generator.h"
13 #include "src/basic-block-profiler.h"
14 #include "src/bootstrapper.h"
15 #include "src/codegen.h"
16 #include "src/compilation-cache.h"
17 #include "src/cpu-profiler.h"
18 #include "src/debug.h"
19 #include "src/deoptimizer.h"
20 #include "src/heap/spaces.h"
21 #include "src/heap/sweeper-thread.h"
22 #include "src/heap-profiler.h"
23 #include "src/hydrogen.h"
24 #include "src/ic/stub-cache.h"
25 #include "src/isolate-inl.h"
26 #include "src/lithium-allocator.h"
28 #include "src/messages.h"
29 #include "src/prototype.h"
30 #include "src/regexp-stack.h"
31 #include "src/runtime-profiler.h"
32 #include "src/sampler.h"
33 #include "src/scopeinfo.h"
34 #include "src/serialize.h"
35 #include "src/simulator.h"
36 #include "src/version.h"
37 #include "src/vm-state-inl.h"
43 base::Atomic32 ThreadId::highest_thread_id_ = 0;
45 int ThreadId::AllocateThreadId() {
46 int new_id = base::NoBarrier_AtomicIncrement(&highest_thread_id_, 1);
51 int ThreadId::GetCurrentThreadId() {
52 int thread_id = base::Thread::GetThreadLocalInt(Isolate::thread_id_key_);
54 thread_id = AllocateThreadId();
55 base::Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id);
61 ThreadLocalTop::ThreadLocalTop() {
66 void ThreadLocalTop::InitializeInternal() {
73 external_callback_scope_ = NULL;
74 current_vm_state_ = EXTERNAL;
75 try_catch_handler_ = NULL;
77 thread_id_ = ThreadId::Invalid();
78 external_caught_exception_ = false;
79 failed_access_check_callback_ = NULL;
82 top_lookup_result_ = NULL;
83 promise_on_stack_ = NULL;
85 // These members are re-initialized later after deserialization
87 pending_exception_ = NULL;
88 has_pending_message_ = false;
89 rethrowing_message_ = false;
90 pending_message_obj_ = NULL;
91 pending_message_script_ = NULL;
92 scheduled_exception_ = NULL;
96 void ThreadLocalTop::Initialize() {
99 simulator_ = Simulator::current(isolate_);
101 thread_id_ = ThreadId::Current();
105 void ThreadLocalTop::Free() {
106 // Match unmatched PopPromise calls.
107 while (promise_on_stack_) isolate_->PopPromise();
111 base::Thread::LocalStorageKey Isolate::isolate_key_;
112 base::Thread::LocalStorageKey Isolate::thread_id_key_;
113 base::Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
114 base::LazyMutex Isolate::thread_data_table_mutex_ = LAZY_MUTEX_INITIALIZER;
115 Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
116 base::Atomic32 Isolate::isolate_counter_ = 0;
118 Isolate::PerIsolateThreadData*
119 Isolate::FindOrAllocatePerThreadDataForThisThread() {
120 ThreadId thread_id = ThreadId::Current();
121 PerIsolateThreadData* per_thread = NULL;
123 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
124 per_thread = thread_data_table_->Lookup(this, thread_id);
125 if (per_thread == NULL) {
126 per_thread = new PerIsolateThreadData(this, thread_id);
127 thread_data_table_->Insert(per_thread);
129 DCHECK(thread_data_table_->Lookup(this, thread_id) == per_thread);
135 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() {
136 ThreadId thread_id = ThreadId::Current();
137 return FindPerThreadDataForThread(thread_id);
141 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThread(
142 ThreadId thread_id) {
143 PerIsolateThreadData* per_thread = NULL;
145 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
146 per_thread = thread_data_table_->Lookup(this, thread_id);
152 void Isolate::InitializeOncePerProcess() {
153 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
154 CHECK(thread_data_table_ == NULL);
155 isolate_key_ = base::Thread::CreateThreadLocalKey();
156 thread_id_key_ = base::Thread::CreateThreadLocalKey();
157 per_isolate_thread_data_key_ = base::Thread::CreateThreadLocalKey();
158 thread_data_table_ = new Isolate::ThreadDataTable();
162 Address Isolate::get_address_from_id(Isolate::AddressId id) {
163 return isolate_addresses_[id];
167 char* Isolate::Iterate(ObjectVisitor* v, char* thread_storage) {
168 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage);
170 return thread_storage + sizeof(ThreadLocalTop);
174 void Isolate::IterateThread(ThreadVisitor* v, char* t) {
175 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
176 v->VisitThread(this, thread);
180 void Isolate::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
181 // Visit the roots from the top for a given thread.
182 v->VisitPointer(&thread->pending_exception_);
183 v->VisitPointer(&(thread->pending_message_obj_));
184 v->VisitPointer(bit_cast<Object**>(&(thread->pending_message_script_)));
185 v->VisitPointer(bit_cast<Object**>(&(thread->context_)));
186 v->VisitPointer(&thread->scheduled_exception_);
188 for (v8::TryCatch* block = thread->try_catch_handler();
190 block = block->next_) {
191 v->VisitPointer(bit_cast<Object**>(&(block->exception_)));
192 v->VisitPointer(bit_cast<Object**>(&(block->message_obj_)));
193 v->VisitPointer(bit_cast<Object**>(&(block->message_script_)));
196 // Iterate over pointers on native execution stack.
197 for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) {
198 it.frame()->Iterate(v);
201 // Iterate pointers in live lookup results.
202 thread->top_lookup_result_->Iterate(v);
206 void Isolate::Iterate(ObjectVisitor* v) {
207 ThreadLocalTop* current_t = thread_local_top();
208 Iterate(v, current_t);
212 void Isolate::IterateDeferredHandles(ObjectVisitor* visitor) {
213 for (DeferredHandles* deferred = deferred_handles_head_;
215 deferred = deferred->next_) {
216 deferred->Iterate(visitor);
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_;
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;
244 void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) {
245 thread_local_top()->set_try_catch_handler(that);
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 thread_local_top()->catcher_ = NULL;
256 Handle<String> Isolate::StackTraceString() {
257 if (stack_trace_nesting_level_ == 0) {
258 stack_trace_nesting_level_++;
259 HeapStringAllocator allocator;
260 StringStream::ClearMentionedObjectCache(this);
261 StringStream accumulator(&allocator);
262 incomplete_message_ = &accumulator;
263 PrintStack(&accumulator);
264 Handle<String> stack_trace = accumulator.ToString(this);
265 incomplete_message_ = NULL;
266 stack_trace_nesting_level_ = 0;
268 } else if (stack_trace_nesting_level_ == 1) {
269 stack_trace_nesting_level_++;
270 base::OS::PrintError(
271 "\n\nAttempt to print stack while printing stack (double fault)\n");
272 base::OS::PrintError(
273 "If you are lucky you may find a partial stack dump on stdout.\n\n");
274 incomplete_message_->OutputToStdOut();
275 return factory()->empty_string();
279 return factory()->empty_string();
284 void Isolate::PushStackTraceAndDie(unsigned int magic,
287 unsigned int magic2) {
288 const int kMaxStackTraceSize = 8192;
289 Handle<String> trace = StackTraceString();
290 uint8_t buffer[kMaxStackTraceSize];
291 int length = Min(kMaxStackTraceSize - 1, trace->length());
292 String::WriteToFlat(*trace, buffer, 0, length);
293 buffer[length] = '\0';
294 // TODO(dcarney): convert buffer to utf8?
295 base::OS::PrintError("Stacktrace (%x-%x) %p %p: %s\n", magic, magic2,
296 static_cast<void*>(object), static_cast<void*>(map),
297 reinterpret_cast<char*>(buffer));
302 // Determines whether the given stack frame should be displayed in
303 // a stack trace. The caller is the error constructor that asked
304 // for the stack trace to be collected. The first time a construct
305 // call to this function is encountered it is skipped. The seen_caller
306 // in/out parameter is used to remember if the caller has been seen
308 static bool IsVisibleInStackTrace(JSFunction* fun,
312 if ((fun == caller) && !(*seen_caller)) {
316 // Skip all frames until we've seen the caller.
317 if (!(*seen_caller)) return false;
318 // Also, skip non-visible built-in functions and any call with the builtins
319 // object as receiver, so as to not reveal either the builtins object or
320 // an internal function.
321 // The --builtins-in-stack-traces command line flag allows including
322 // internal call sites in the stack trace for debugging purposes.
323 if (!FLAG_builtins_in_stack_traces) {
324 if (receiver->IsJSBuiltinsObject()) return false;
325 if (fun->IsBuiltin()) {
326 return fun->shared()->native();
327 } else if (fun->IsFromNativeScript() || fun->IsFromExtensionScript()) {
335 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object,
336 Handle<Object> caller) {
337 // Get stack trace limit.
338 Handle<Object> error = Object::GetProperty(
339 this, js_builtins_object(), "$Error").ToHandleChecked();
340 if (!error->IsJSObject()) return factory()->undefined_value();
342 Handle<String> stackTraceLimit =
343 factory()->InternalizeUtf8String("stackTraceLimit");
344 DCHECK(!stackTraceLimit.is_null());
345 Handle<Object> stack_trace_limit =
346 JSObject::GetDataProperty(Handle<JSObject>::cast(error),
348 if (!stack_trace_limit->IsNumber()) return factory()->undefined_value();
349 int limit = FastD2IChecked(stack_trace_limit->Number());
350 limit = Max(limit, 0); // Ensure that limit is not negative.
352 int initial_size = Min(limit, 10);
353 Handle<FixedArray> elements =
354 factory()->NewFixedArrayWithHoles(initial_size * 4 + 1);
356 // If the caller parameter is a function we skip frames until we're
357 // under it before starting to collect.
358 bool seen_caller = !caller->IsJSFunction();
359 // First element is reserved to store the number of sloppy frames.
362 int sloppy_frames = 0;
363 bool encountered_strict_function = false;
364 for (JavaScriptFrameIterator iter(this);
365 !iter.done() && frames_seen < limit;
367 JavaScriptFrame* frame = iter.frame();
368 // Set initial size to the maximum inlining level + 1 for the outermost
370 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
371 frame->Summarize(&frames);
372 for (int i = frames.length() - 1; i >= 0; i--) {
373 Handle<JSFunction> fun = frames[i].function();
374 Handle<Object> recv = frames[i].receiver();
375 // Filter out internal frames that we do not want to show.
376 if (!IsVisibleInStackTrace(*fun, *caller, *recv, &seen_caller)) continue;
377 // Filter out frames from other security contexts.
378 if (!this->context()->HasSameSecurityTokenAs(fun->context())) continue;
379 if (cursor + 4 > elements->length()) {
380 int new_capacity = JSObject::NewElementsCapacity(elements->length());
381 Handle<FixedArray> new_elements =
382 factory()->NewFixedArrayWithHoles(new_capacity);
383 for (int i = 0; i < cursor; i++) {
384 new_elements->set(i, elements->get(i));
386 elements = new_elements;
388 DCHECK(cursor + 4 <= elements->length());
391 Handle<Code> code = frames[i].code();
392 Handle<Smi> offset(Smi::FromInt(frames[i].offset()), this);
393 // The stack trace API should not expose receivers and function
394 // objects on frames deeper than the top-most one with a strict
395 // mode function. The number of sloppy frames is stored as
396 // first element in the result array.
397 if (!encountered_strict_function) {
398 if (fun->shared()->strict_mode() == STRICT) {
399 encountered_strict_function = true;
404 elements->set(cursor++, *recv);
405 elements->set(cursor++, *fun);
406 elements->set(cursor++, *code);
407 elements->set(cursor++, *offset);
411 elements->set(0, Smi::FromInt(sloppy_frames));
412 Handle<JSArray> result = factory()->NewJSArrayWithElements(elements);
413 result->set_length(Smi::FromInt(cursor));
418 void Isolate::CaptureAndSetDetailedStackTrace(Handle<JSObject> error_object) {
419 if (capture_stack_trace_for_uncaught_exceptions_) {
420 // Capture stack trace for a detailed exception message.
421 Handle<Name> key = factory()->detailed_stack_trace_symbol();
422 Handle<JSArray> stack_trace = CaptureCurrentStackTrace(
423 stack_trace_for_uncaught_exceptions_frame_limit_,
424 stack_trace_for_uncaught_exceptions_options_);
425 JSObject::SetProperty(error_object, key, stack_trace, STRICT).Assert();
430 void Isolate::CaptureAndSetSimpleStackTrace(Handle<JSObject> error_object,
431 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 JSObject::SetProperty(error_object, key, stack_trace, STRICT).Assert();
439 Handle<JSArray> Isolate::CaptureCurrentStackTrace(
440 int frame_limit, StackTrace::StackTraceOptions options) {
441 // Ensure no negative values.
442 int limit = Max(frame_limit, 0);
443 Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit);
445 Handle<String> column_key =
446 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("column"));
447 Handle<String> line_key =
448 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("lineNumber"));
449 Handle<String> script_id_key =
450 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("scriptId"));
451 Handle<String> script_name_key =
452 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("scriptName"));
453 Handle<String> script_name_or_source_url_key =
454 factory()->InternalizeOneByteString(
455 STATIC_CHAR_VECTOR("scriptNameOrSourceURL"));
456 Handle<String> function_key =
457 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("functionName"));
458 Handle<String> eval_key =
459 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("isEval"));
460 Handle<String> constructor_key =
461 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("isConstructor"));
463 StackTraceFrameIterator it(this);
465 while (!it.done() && (frames_seen < limit)) {
466 JavaScriptFrame* frame = it.frame();
467 // Set initial size to the maximum inlining level + 1 for the outermost
469 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
470 frame->Summarize(&frames);
471 for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) {
472 Handle<JSFunction> fun = frames[i].function();
473 // Filter frames from other security contexts.
474 if (!(options & StackTrace::kExposeFramesAcrossSecurityOrigins) &&
475 !this->context()->HasSameSecurityTokenAs(fun->context())) continue;
477 // Create a JSObject to hold the information for the StackFrame.
478 Handle<JSObject> stack_frame = factory()->NewJSObject(object_function());
480 Handle<Script> script(Script::cast(fun->shared()->script()));
482 if (options & StackTrace::kLineNumber) {
483 int script_line_offset = script->line_offset()->value();
484 int position = frames[i].code()->SourcePosition(frames[i].pc());
485 int line_number = Script::GetLineNumber(script, position);
486 // line_number is already shifted by the script_line_offset.
487 int relative_line_number = line_number - script_line_offset;
488 if (options & StackTrace::kColumnOffset && relative_line_number >= 0) {
489 Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
490 int start = (relative_line_number == 0) ? 0 :
491 Smi::cast(line_ends->get(relative_line_number - 1))->value() + 1;
492 int column_offset = position - start;
493 if (relative_line_number == 0) {
494 // For the case where the code is on the same line as the script
496 column_offset += script->column_offset()->value();
498 JSObject::AddProperty(
499 stack_frame, column_key,
500 handle(Smi::FromInt(column_offset + 1), this), NONE);
502 JSObject::AddProperty(
503 stack_frame, line_key,
504 handle(Smi::FromInt(line_number + 1), this), NONE);
507 if (options & StackTrace::kScriptId) {
508 JSObject::AddProperty(
509 stack_frame, script_id_key, handle(script->id(), this), NONE);
512 if (options & StackTrace::kScriptName) {
513 JSObject::AddProperty(
514 stack_frame, script_name_key, handle(script->name(), this), NONE);
517 if (options & StackTrace::kScriptNameOrSourceURL) {
518 Handle<Object> result = Script::GetNameOrSourceURL(script);
519 JSObject::AddProperty(
520 stack_frame, script_name_or_source_url_key, result, NONE);
523 if (options & StackTrace::kFunctionName) {
524 Handle<Object> fun_name(fun->shared()->DebugName(), this);
525 JSObject::AddProperty(stack_frame, function_key, fun_name, NONE);
528 if (options & StackTrace::kIsEval) {
529 Handle<Object> is_eval =
530 script->compilation_type() == Script::COMPILATION_TYPE_EVAL ?
531 factory()->true_value() : factory()->false_value();
532 JSObject::AddProperty(stack_frame, eval_key, is_eval, NONE);
535 if (options & StackTrace::kIsConstructor) {
536 Handle<Object> is_constructor = (frames[i].is_constructor()) ?
537 factory()->true_value() : factory()->false_value();
538 JSObject::AddProperty(
539 stack_frame, constructor_key, is_constructor, NONE);
542 FixedArray::cast(stack_trace->elements())->set(frames_seen, *stack_frame);
548 stack_trace->set_length(Smi::FromInt(frames_seen));
553 void Isolate::PrintStack(FILE* out) {
554 if (stack_trace_nesting_level_ == 0) {
555 stack_trace_nesting_level_++;
556 StringStream::ClearMentionedObjectCache(this);
557 HeapStringAllocator allocator;
558 StringStream accumulator(&allocator);
559 incomplete_message_ = &accumulator;
560 PrintStack(&accumulator);
561 accumulator.OutputToFile(out);
562 InitializeLoggingAndCounters();
563 accumulator.Log(this);
564 incomplete_message_ = NULL;
565 stack_trace_nesting_level_ = 0;
566 } else if (stack_trace_nesting_level_ == 1) {
567 stack_trace_nesting_level_++;
568 base::OS::PrintError(
569 "\n\nAttempt to print stack while printing stack (double fault)\n");
570 base::OS::PrintError(
571 "If you are lucky you may find a partial stack dump on stdout.\n\n");
572 incomplete_message_->OutputToFile(out);
577 static void PrintFrames(Isolate* isolate,
578 StringStream* accumulator,
579 StackFrame::PrintMode mode) {
580 StackFrameIterator it(isolate);
581 for (int i = 0; !it.done(); it.Advance()) {
582 it.frame()->Print(accumulator, mode, i++);
587 void Isolate::PrintStack(StringStream* accumulator) {
588 if (!IsInitialized()) {
590 "\n==== JS stack trace is not available =======================\n\n");
592 "\n==== Isolate for the thread is not initialized =============\n\n");
595 // The MentionedObjectCache is not GC-proof at the moment.
596 DisallowHeapAllocation no_gc;
597 DCHECK(StringStream::IsMentionedObjectCacheClear(this));
599 // Avoid printing anything if there are no frames.
600 if (c_entry_fp(thread_local_top()) == 0) return;
603 "\n==== JS stack trace =========================================\n\n");
604 PrintFrames(this, accumulator, StackFrame::OVERVIEW);
607 "\n==== Details ================================================\n\n");
608 PrintFrames(this, accumulator, StackFrame::DETAILS);
610 accumulator->PrintMentionedObjectCache(this);
611 accumulator->Add("=====================\n\n");
615 void Isolate::SetFailedAccessCheckCallback(
616 v8::FailedAccessCheckCallback callback) {
617 thread_local_top()->failed_access_check_callback_ = callback;
621 static inline AccessCheckInfo* GetAccessCheckInfo(Isolate* isolate,
622 Handle<JSObject> receiver) {
623 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
624 if (!constructor->shared()->IsApiFunction()) return NULL;
627 constructor->shared()->get_api_func_data()->access_check_info();
628 if (data_obj == isolate->heap()->undefined_value()) return NULL;
630 return AccessCheckInfo::cast(data_obj);
634 void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver,
635 v8::AccessType type) {
636 if (!thread_local_top()->failed_access_check_callback_) {
637 Handle<String> message = factory()->InternalizeUtf8String("no access");
638 Handle<Object> error;
639 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
640 this, error, factory()->NewTypeError(message), /* void */);
641 ScheduleThrow(*error);
645 DCHECK(receiver->IsAccessCheckNeeded());
648 // Get the data object from access check info.
649 HandleScope scope(this);
651 { DisallowHeapAllocation no_gc;
652 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver);
653 if (!access_check_info) return;
654 data = handle(access_check_info->data(), this);
657 // Leaving JavaScript.
658 VMState<EXTERNAL> state(this);
659 thread_local_top()->failed_access_check_callback_(
660 v8::Utils::ToLocal(receiver),
662 v8::Utils::ToLocal(data));
666 enum MayAccessDecision {
671 static MayAccessDecision MayAccessPreCheck(Isolate* isolate,
672 Handle<JSObject> receiver,
673 v8::AccessType type) {
674 DisallowHeapAllocation no_gc;
675 // During bootstrapping, callback functions are not enabled yet.
676 if (isolate->bootstrapper()->IsActive()) return YES;
678 if (receiver->IsJSGlobalProxy()) {
679 Object* receiver_context = JSGlobalProxy::cast(*receiver)->native_context();
680 if (!receiver_context->IsContext()) return NO;
682 // Get the native context of current top context.
683 // avoid using Isolate::native_context() because it uses Handle.
684 Context* native_context =
685 isolate->context()->global_object()->native_context();
686 if (receiver_context == native_context) return YES;
688 if (Context::cast(receiver_context)->security_token() ==
689 native_context->security_token())
697 bool Isolate::MayNamedAccess(Handle<JSObject> receiver,
699 v8::AccessType type) {
700 DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded());
702 // Skip checks for hidden properties access. Note, we do not
703 // require existence of a context in this case.
704 if (key.is_identical_to(factory()->hidden_string())) return true;
706 // Check for compatibility between the security tokens in the
707 // current lexical context and the accessed object.
710 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type);
711 if (decision != UNKNOWN) return decision == YES;
713 HandleScope scope(this);
715 v8::NamedSecurityCallback callback;
716 { DisallowHeapAllocation no_gc;
717 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver);
718 if (!access_check_info) return false;
719 Object* fun_obj = access_check_info->named_callback();
720 callback = v8::ToCData<v8::NamedSecurityCallback>(fun_obj);
721 if (!callback) return false;
722 data = handle(access_check_info->data(), this);
725 LOG(this, ApiNamedSecurityCheck(*key));
727 // Leaving JavaScript.
728 VMState<EXTERNAL> state(this);
729 return callback(v8::Utils::ToLocal(receiver),
730 v8::Utils::ToLocal(key),
732 v8::Utils::ToLocal(data));
736 bool Isolate::MayIndexedAccess(Handle<JSObject> receiver,
738 v8::AccessType type) {
739 DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded());
740 // Check for compatibility between the security tokens in the
741 // current lexical context and the accessed object.
744 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type);
745 if (decision != UNKNOWN) return decision == YES;
747 HandleScope scope(this);
749 v8::IndexedSecurityCallback callback;
750 { DisallowHeapAllocation no_gc;
751 // Get named access check callback
752 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver);
753 if (!access_check_info) return false;
754 Object* fun_obj = access_check_info->indexed_callback();
755 callback = v8::ToCData<v8::IndexedSecurityCallback>(fun_obj);
756 if (!callback) return false;
757 data = handle(access_check_info->data(), this);
760 LOG(this, ApiIndexedSecurityCheck(index));
762 // Leaving JavaScript.
763 VMState<EXTERNAL> state(this);
765 v8::Utils::ToLocal(receiver), index, type, v8::Utils::ToLocal(data));
769 const char* const Isolate::kStackOverflowMessage =
770 "Uncaught RangeError: Maximum call stack size exceeded";
773 Object* Isolate::StackOverflow() {
774 HandleScope scope(this);
775 // At this point we cannot create an Error object using its javascript
776 // constructor. Instead, we copy the pre-constructed boilerplate and
777 // attach the stack trace as a hidden property.
778 Handle<String> key = factory()->stack_overflow_string();
779 Handle<JSObject> boilerplate = Handle<JSObject>::cast(
780 Object::GetProperty(js_builtins_object(), key).ToHandleChecked());
781 Handle<JSObject> exception = factory()->CopyJSObject(boilerplate);
782 DoThrow(*exception, NULL);
784 CaptureAndSetSimpleStackTrace(exception, factory()->undefined_value());
785 return heap()->exception();
789 Object* Isolate::TerminateExecution() {
790 DoThrow(heap_.termination_exception(), NULL);
791 return heap()->exception();
795 void Isolate::CancelTerminateExecution() {
796 if (try_catch_handler()) {
797 try_catch_handler()->has_terminated_ = false;
799 if (has_pending_exception() &&
800 pending_exception() == heap_.termination_exception()) {
801 thread_local_top()->external_caught_exception_ = false;
802 clear_pending_exception();
804 if (has_scheduled_exception() &&
805 scheduled_exception() == heap_.termination_exception()) {
806 thread_local_top()->external_caught_exception_ = false;
807 clear_scheduled_exception();
812 void Isolate::InvokeApiInterruptCallback() {
813 // Note: callback below should be called outside of execution access lock.
814 InterruptCallback callback = NULL;
817 ExecutionAccess access(this);
818 callback = api_interrupt_callback_;
819 data = api_interrupt_callback_data_;
820 api_interrupt_callback_ = NULL;
821 api_interrupt_callback_data_ = NULL;
824 if (callback != NULL) {
825 VMState<EXTERNAL> state(this);
826 HandleScope handle_scope(this);
827 callback(reinterpret_cast<v8::Isolate*>(this), data);
832 Object* Isolate::Throw(Object* exception, MessageLocation* location) {
833 DoThrow(exception, location);
834 return heap()->exception();
838 Object* Isolate::ReThrow(Object* exception) {
839 bool can_be_caught_externally = false;
840 bool catchable_by_javascript = is_catchable_by_javascript(exception);
841 ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
843 thread_local_top()->catcher_ = can_be_caught_externally ?
844 try_catch_handler() : NULL;
846 // Set the exception being re-thrown.
847 set_pending_exception(exception);
848 return heap()->exception();
852 Object* Isolate::ThrowIllegalOperation() {
853 if (FLAG_stack_trace_on_illegal) PrintStack(stdout);
854 return Throw(heap_.illegal_access_string());
858 void Isolate::ScheduleThrow(Object* exception) {
859 // When scheduling a throw we first throw the exception to get the
860 // error reporting if it is uncaught before rescheduling it.
862 PropagatePendingExceptionToExternalTryCatch();
863 if (has_pending_exception()) {
864 thread_local_top()->scheduled_exception_ = pending_exception();
865 thread_local_top()->external_caught_exception_ = false;
866 clear_pending_exception();
871 void Isolate::RestorePendingMessageFromTryCatch(v8::TryCatch* handler) {
872 DCHECK(handler == try_catch_handler());
873 DCHECK(handler->HasCaught());
874 DCHECK(handler->rethrow_);
875 DCHECK(handler->capture_message_);
876 Object* message = reinterpret_cast<Object*>(handler->message_obj_);
877 Object* script = reinterpret_cast<Object*>(handler->message_script_);
878 DCHECK(message->IsJSMessageObject() || message->IsTheHole());
879 DCHECK(script->IsScript() || script->IsTheHole());
880 thread_local_top()->pending_message_obj_ = message;
881 thread_local_top()->pending_message_script_ = script;
882 thread_local_top()->pending_message_start_pos_ = handler->message_start_pos_;
883 thread_local_top()->pending_message_end_pos_ = handler->message_end_pos_;
887 void Isolate::CancelScheduledExceptionFromTryCatch(v8::TryCatch* handler) {
888 DCHECK(has_scheduled_exception());
889 if (scheduled_exception() == handler->exception_) {
890 DCHECK(scheduled_exception() != heap()->termination_exception());
891 clear_scheduled_exception();
896 Object* Isolate::PromoteScheduledException() {
897 Object* thrown = scheduled_exception();
898 clear_scheduled_exception();
899 // Re-throw the exception to avoid getting repeated error reporting.
900 return ReThrow(thrown);
904 void Isolate::PrintCurrentStackTrace(FILE* out) {
905 StackTraceFrameIterator it(this);
907 HandleScope scope(this);
908 // Find code position if recorded in relocation info.
909 JavaScriptFrame* frame = it.frame();
910 int pos = frame->LookupCode()->SourcePosition(frame->pc());
911 Handle<Object> pos_obj(Smi::FromInt(pos), this);
912 // Fetch function and receiver.
913 Handle<JSFunction> fun(frame->function());
914 Handle<Object> recv(frame->receiver(), this);
915 // Advance to the next JavaScript frame and determine if the
916 // current frame is the top-level frame.
918 Handle<Object> is_top_level = it.done()
919 ? factory()->true_value()
920 : factory()->false_value();
921 // Generate and print stack trace line.
922 Handle<String> line =
923 Execution::GetStackTraceLine(recv, fun, pos_obj, is_top_level);
924 if (line->length() > 0) {
932 void Isolate::ComputeLocation(MessageLocation* target) {
933 *target = MessageLocation(Handle<Script>(heap_.empty_script()), -1, -1);
934 StackTraceFrameIterator it(this);
936 JavaScriptFrame* frame = it.frame();
937 JSFunction* fun = frame->function();
938 Object* script = fun->shared()->script();
939 if (script->IsScript() &&
940 !(Script::cast(script)->source()->IsUndefined())) {
941 int pos = frame->LookupCode()->SourcePosition(frame->pc());
942 // Compute the location from the function and the reloc info.
943 Handle<Script> casted_script(Script::cast(script));
944 *target = MessageLocation(casted_script, pos, pos + 1);
950 bool Isolate::ShouldReportException(bool* can_be_caught_externally,
951 bool catchable_by_javascript) {
952 // Find the top-most try-catch handler.
953 StackHandler* handler =
954 StackHandler::FromAddress(Isolate::handler(thread_local_top()));
955 while (handler != NULL && !handler->is_catch()) {
956 handler = handler->next();
959 // Get the address of the external handler so we can compare the address to
960 // determine which one is closer to the top of the stack.
961 Address external_handler_address =
962 thread_local_top()->try_catch_handler_address();
964 // The exception has been externally caught if and only if there is
965 // an external handler which is on top of the top-most try-catch
967 *can_be_caught_externally = external_handler_address != NULL &&
968 (handler == NULL || handler->address() > external_handler_address ||
969 !catchable_by_javascript);
971 if (*can_be_caught_externally) {
972 // Only report the exception if the external handler is verbose.
973 return try_catch_handler()->is_verbose_;
975 // Report the exception if it isn't caught by JavaScript code.
976 return handler == NULL;
981 bool Isolate::IsErrorObject(Handle<Object> obj) {
982 if (!obj->IsJSObject()) return false;
984 Handle<String> error_key =
985 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("$Error"));
986 Handle<Object> error_constructor = Object::GetProperty(
987 js_builtins_object(), error_key).ToHandleChecked();
989 DisallowHeapAllocation no_gc;
990 for (PrototypeIterator iter(this, *obj, PrototypeIterator::START_AT_RECEIVER);
991 !iter.IsAtEnd(); iter.Advance()) {
992 if (iter.GetCurrent()->IsJSProxy()) return false;
993 if (JSObject::cast(iter.GetCurrent())->map()->constructor() ==
994 *error_constructor) {
1001 static int fatal_exception_depth = 0;
1003 void Isolate::DoThrow(Object* exception, MessageLocation* location) {
1004 DCHECK(!has_pending_exception());
1006 HandleScope scope(this);
1007 Handle<Object> exception_handle(exception, this);
1009 // Determine reporting and whether the exception is caught externally.
1010 bool catchable_by_javascript = is_catchable_by_javascript(exception);
1011 bool can_be_caught_externally = false;
1012 bool should_report_exception =
1013 ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
1014 bool report_exception = catchable_by_javascript && should_report_exception;
1015 bool try_catch_needs_message =
1016 can_be_caught_externally && try_catch_handler()->capture_message_;
1017 bool bootstrapping = bootstrapper()->IsActive();
1018 bool rethrowing_message = thread_local_top()->rethrowing_message_;
1020 thread_local_top()->rethrowing_message_ = false;
1022 // Notify debugger of exception.
1023 if (catchable_by_javascript) {
1024 debug()->OnThrow(exception_handle, report_exception);
1027 // Generate the message if required.
1028 if (!rethrowing_message && (report_exception || try_catch_needs_message)) {
1029 MessageLocation potential_computed_location;
1030 if (location == NULL) {
1031 // If no location was specified we use a computed one instead.
1032 ComputeLocation(&potential_computed_location);
1033 location = &potential_computed_location;
1035 // It's not safe to try to make message objects or collect stack traces
1036 // while the bootstrapper is active since the infrastructure may not have
1037 // been properly initialized.
1038 if (!bootstrapping) {
1039 Handle<JSArray> stack_trace_object;
1040 if (capture_stack_trace_for_uncaught_exceptions_) {
1041 if (IsErrorObject(exception_handle)) {
1042 // We fetch the stack trace that corresponds to this error object.
1043 Handle<Name> key = factory()->detailed_stack_trace_symbol();
1044 // Look up as own property. If the lookup fails, the exception is
1045 // probably not a valid Error object. In that case, we fall through
1046 // and capture the stack trace at this throw site.
1047 LookupIterator lookup(exception_handle, key,
1048 LookupIterator::OWN_SKIP_INTERCEPTOR);
1049 Handle<Object> stack_trace_property;
1050 if (Object::GetProperty(&lookup).ToHandle(&stack_trace_property) &&
1051 stack_trace_property->IsJSArray()) {
1052 stack_trace_object = Handle<JSArray>::cast(stack_trace_property);
1055 if (stack_trace_object.is_null()) {
1056 // Not an error object, we capture at throw site.
1057 stack_trace_object = CaptureCurrentStackTrace(
1058 stack_trace_for_uncaught_exceptions_frame_limit_,
1059 stack_trace_for_uncaught_exceptions_options_);
1063 Handle<Object> exception_arg = exception_handle;
1064 // If the exception argument is a custom object, turn it into a string
1065 // before throwing as uncaught exception. Note that the pending
1066 // exception object to be set later must not be turned into a string.
1067 if (exception_arg->IsJSObject() && !IsErrorObject(exception_arg)) {
1068 MaybeHandle<Object> maybe_exception =
1069 Execution::ToDetailString(this, exception_arg);
1070 if (!maybe_exception.ToHandle(&exception_arg)) {
1071 exception_arg = factory()->InternalizeOneByteString(
1072 STATIC_CHAR_VECTOR("exception"));
1075 Handle<Object> message_obj = MessageHandler::MakeMessageObject(
1077 "uncaught_exception",
1079 HandleVector<Object>(&exception_arg, 1),
1080 stack_trace_object);
1081 thread_local_top()->pending_message_obj_ = *message_obj;
1082 if (location != NULL) {
1083 thread_local_top()->pending_message_script_ = *location->script();
1084 thread_local_top()->pending_message_start_pos_ = location->start_pos();
1085 thread_local_top()->pending_message_end_pos_ = location->end_pos();
1088 // If the abort-on-uncaught-exception flag is specified, abort on any
1089 // exception not caught by JavaScript, even when an external handler is
1090 // present. This flag is intended for use by JavaScript developers, so
1091 // print a user-friendly stack trace (not an internal one).
1092 if (fatal_exception_depth == 0 &&
1093 FLAG_abort_on_uncaught_exception &&
1094 (report_exception || can_be_caught_externally)) {
1095 fatal_exception_depth++;
1098 MessageHandler::GetLocalizedMessage(this, message_obj).get());
1099 PrintCurrentStackTrace(stderr);
1102 } else if (location != NULL && !location->script().is_null()) {
1103 // We are bootstrapping and caught an error where the location is set
1104 // and we have a script for the location.
1105 // In this case we could have an extension (or an internal error
1106 // somewhere) and we print out the line number at which the error occured
1107 // to the console for easier debugging.
1109 location->script()->GetLineNumber(location->start_pos()) + 1;
1110 if (exception->IsString() && location->script()->name()->IsString()) {
1111 base::OS::PrintError(
1112 "Extension or internal compilation error: %s in %s at line %d.\n",
1113 String::cast(exception)->ToCString().get(),
1114 String::cast(location->script()->name())->ToCString().get(),
1116 } else if (location->script()->name()->IsString()) {
1117 base::OS::PrintError(
1118 "Extension or internal compilation error in %s at line %d.\n",
1119 String::cast(location->script()->name())->ToCString().get(),
1122 base::OS::PrintError("Extension or internal compilation error.\n");
1125 // Since comments and empty lines have been stripped from the source of
1126 // builtins, print the actual source here so that line numbers match.
1127 if (location->script()->source()->IsString()) {
1128 Handle<String> src(String::cast(location->script()->source()));
1129 PrintF("Failing script:\n");
1130 int len = src->length();
1131 int line_number = 1;
1132 PrintF("%5d: ", line_number);
1133 for (int i = 0; i < len; i++) {
1134 uint16_t character = src->Get(i);
1135 PrintF("%c", character);
1136 if (character == '\n' && i < len - 2) {
1137 PrintF("%5d: ", ++line_number);
1145 // Save the message for reporting if the the exception remains uncaught.
1146 thread_local_top()->has_pending_message_ = report_exception;
1148 // Do not forget to clean catcher_ if currently thrown exception cannot
1149 // be caught. If necessary, ReThrow will update the catcher.
1150 thread_local_top()->catcher_ = can_be_caught_externally ?
1151 try_catch_handler() : NULL;
1153 set_pending_exception(*exception_handle);
1157 bool Isolate::HasExternalTryCatch() {
1158 DCHECK(has_pending_exception());
1160 return (thread_local_top()->catcher_ != NULL) &&
1161 (try_catch_handler() == thread_local_top()->catcher_);
1165 bool Isolate::IsFinallyOnTop() {
1166 // Get the address of the external handler so we can compare the address to
1167 // determine which one is closer to the top of the stack.
1168 Address external_handler_address =
1169 thread_local_top()->try_catch_handler_address();
1170 DCHECK(external_handler_address != NULL);
1172 // The exception has been externally caught if and only if there is
1173 // an external handler which is on top of the top-most try-finally
1175 // There should be no try-catch blocks as they would prohibit us from
1176 // finding external catcher in the first place (see catcher_ check above).
1178 // Note, that finally clause would rethrow an exception unless it's
1179 // aborted by jumps in control flow like return, break, etc. and we'll
1180 // have another chances to set proper v8::TryCatch.
1181 StackHandler* handler =
1182 StackHandler::FromAddress(Isolate::handler(thread_local_top()));
1183 while (handler != NULL && handler->address() < external_handler_address) {
1184 DCHECK(!handler->is_catch());
1185 if (handler->is_finally()) return true;
1187 handler = handler->next();
1194 void Isolate::ReportPendingMessages() {
1195 DCHECK(has_pending_exception());
1196 bool can_clear_message = PropagatePendingExceptionToExternalTryCatch();
1198 HandleScope scope(this);
1199 if (thread_local_top_.pending_exception_ == heap()->termination_exception()) {
1200 // Do nothing: if needed, the exception has been already propagated to
1203 if (thread_local_top_.has_pending_message_) {
1204 thread_local_top_.has_pending_message_ = false;
1205 if (!thread_local_top_.pending_message_obj_->IsTheHole()) {
1206 HandleScope scope(this);
1207 Handle<Object> message_obj(thread_local_top_.pending_message_obj_,
1209 if (!thread_local_top_.pending_message_script_->IsTheHole()) {
1210 Handle<Script> script(
1211 Script::cast(thread_local_top_.pending_message_script_));
1212 int start_pos = thread_local_top_.pending_message_start_pos_;
1213 int end_pos = thread_local_top_.pending_message_end_pos_;
1214 MessageLocation location(script, start_pos, end_pos);
1215 MessageHandler::ReportMessage(this, &location, message_obj);
1217 MessageHandler::ReportMessage(this, NULL, message_obj);
1222 if (can_clear_message) clear_pending_message();
1226 MessageLocation Isolate::GetMessageLocation() {
1227 DCHECK(has_pending_exception());
1229 if (thread_local_top_.pending_exception_ != heap()->termination_exception() &&
1230 thread_local_top_.has_pending_message_ &&
1231 !thread_local_top_.pending_message_obj_->IsTheHole() &&
1232 !thread_local_top_.pending_message_obj_->IsTheHole()) {
1233 Handle<Script> script(
1234 Script::cast(thread_local_top_.pending_message_script_));
1235 int start_pos = thread_local_top_.pending_message_start_pos_;
1236 int end_pos = thread_local_top_.pending_message_end_pos_;
1237 return MessageLocation(script, start_pos, end_pos);
1240 return MessageLocation();
1244 bool Isolate::OptionalRescheduleException(bool is_bottom_call) {
1245 DCHECK(has_pending_exception());
1246 PropagatePendingExceptionToExternalTryCatch();
1248 bool is_termination_exception =
1249 pending_exception() == heap_.termination_exception();
1251 // Do not reschedule the exception if this is the bottom call.
1252 bool clear_exception = is_bottom_call;
1254 if (is_termination_exception) {
1255 if (is_bottom_call) {
1256 thread_local_top()->external_caught_exception_ = false;
1257 clear_pending_exception();
1260 } else if (thread_local_top()->external_caught_exception_) {
1261 // If the exception is externally caught, clear it if there are no
1262 // JavaScript frames on the way to the C++ frame that has the
1263 // external handler.
1264 DCHECK(thread_local_top()->try_catch_handler_address() != NULL);
1265 Address external_handler_address =
1266 thread_local_top()->try_catch_handler_address();
1267 JavaScriptFrameIterator it(this);
1268 if (it.done() || (it.frame()->sp() > external_handler_address)) {
1269 clear_exception = true;
1273 // Clear the exception if needed.
1274 if (clear_exception) {
1275 thread_local_top()->external_caught_exception_ = false;
1276 clear_pending_exception();
1280 // Reschedule the exception.
1281 thread_local_top()->scheduled_exception_ = pending_exception();
1282 clear_pending_exception();
1287 void Isolate::PushPromise(Handle<JSObject> promise) {
1288 ThreadLocalTop* tltop = thread_local_top();
1289 PromiseOnStack* prev = tltop->promise_on_stack_;
1290 StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop));
1291 Handle<JSObject> global_handle =
1292 Handle<JSObject>::cast(global_handles()->Create(*promise));
1293 tltop->promise_on_stack_ = new PromiseOnStack(handler, global_handle, prev);
1297 void Isolate::PopPromise() {
1298 ThreadLocalTop* tltop = thread_local_top();
1299 if (tltop->promise_on_stack_ == NULL) return;
1300 PromiseOnStack* prev = tltop->promise_on_stack_->prev();
1301 Handle<Object> global_handle = tltop->promise_on_stack_->promise();
1302 delete tltop->promise_on_stack_;
1303 tltop->promise_on_stack_ = prev;
1304 global_handles()->Destroy(global_handle.location());
1308 Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
1309 Handle<Object> undefined = factory()->undefined_value();
1310 ThreadLocalTop* tltop = thread_local_top();
1311 if (tltop->promise_on_stack_ == NULL) return undefined;
1312 StackHandler* promise_try = tltop->promise_on_stack_->handler();
1313 // Find the top-most try-catch handler.
1314 StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop));
1316 if (handler == promise_try) {
1317 // Mark the pushed try-catch handler to prevent a later duplicate event
1318 // triggered with the following reject.
1319 return tltop->promise_on_stack_->promise();
1321 handler = handler->next();
1322 // Throwing inside a Promise can be intercepted by an inner try-catch, so
1323 // we stop at the first try-catch handler.
1324 } while (handler != NULL && !handler->is_catch());
1329 void Isolate::SetCaptureStackTraceForUncaughtExceptions(
1332 StackTrace::StackTraceOptions options) {
1333 capture_stack_trace_for_uncaught_exceptions_ = capture;
1334 stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit;
1335 stack_trace_for_uncaught_exceptions_options_ = options;
1339 Handle<Context> Isolate::native_context() {
1340 return handle(context()->native_context());
1344 Handle<Context> Isolate::global_context() {
1345 return handle(context()->global_object()->global_context());
1349 Handle<Context> Isolate::GetCallingNativeContext() {
1350 JavaScriptFrameIterator it(this);
1351 if (debug_->in_debug_scope()) {
1352 while (!it.done()) {
1353 JavaScriptFrame* frame = it.frame();
1354 Context* context = Context::cast(frame->context());
1355 if (context->native_context() == *debug_->debug_context()) {
1362 if (it.done()) return Handle<Context>::null();
1363 JavaScriptFrame* frame = it.frame();
1364 Context* context = Context::cast(frame->context());
1365 return Handle<Context>(context->native_context());
1369 char* Isolate::ArchiveThread(char* to) {
1370 MemCopy(to, reinterpret_cast<char*>(thread_local_top()),
1371 sizeof(ThreadLocalTop));
1372 InitializeThreadLocal();
1373 clear_pending_exception();
1374 clear_pending_message();
1375 clear_scheduled_exception();
1376 return to + sizeof(ThreadLocalTop);
1380 char* Isolate::RestoreThread(char* from) {
1381 MemCopy(reinterpret_cast<char*>(thread_local_top()), from,
1382 sizeof(ThreadLocalTop));
1383 // This might be just paranoia, but it seems to be needed in case a
1384 // thread_local_top_ is restored on a separate OS thread.
1385 #ifdef USE_SIMULATOR
1386 thread_local_top()->simulator_ = Simulator::current(this);
1388 DCHECK(context() == NULL || context()->IsContext());
1389 return from + sizeof(ThreadLocalTop);
1393 Isolate::ThreadDataTable::ThreadDataTable()
1398 Isolate::ThreadDataTable::~ThreadDataTable() {
1399 // TODO(svenpanne) The assertion below would fire if an embedder does not
1400 // cleanly dispose all Isolates before disposing v8, so we are conservative
1401 // and leave it out for now.
1402 // DCHECK_EQ(NULL, list_);
1406 Isolate::PerIsolateThreadData::~PerIsolateThreadData() {
1407 #if defined(USE_SIMULATOR)
1413 Isolate::PerIsolateThreadData*
1414 Isolate::ThreadDataTable::Lookup(Isolate* isolate,
1415 ThreadId thread_id) {
1416 for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) {
1417 if (data->Matches(isolate, thread_id)) return data;
1423 void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) {
1424 if (list_ != NULL) list_->prev_ = data;
1425 data->next_ = list_;
1430 void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
1431 if (list_ == data) list_ = data->next_;
1432 if (data->next_ != NULL) data->next_->prev_ = data->prev_;
1433 if (data->prev_ != NULL) data->prev_->next_ = data->next_;
1438 void Isolate::ThreadDataTable::RemoveAllThreads(Isolate* isolate) {
1439 PerIsolateThreadData* data = list_;
1440 while (data != NULL) {
1441 PerIsolateThreadData* next = data->next_;
1442 if (data->isolate() == isolate) Remove(data);
1449 #define TRACE_ISOLATE(tag) \
1451 if (FLAG_trace_isolates) { \
1452 PrintF("Isolate %p (id %d)" #tag "\n", \
1453 reinterpret_cast<void*>(this), id()); \
1457 #define TRACE_ISOLATE(tag)
1463 state_(UNINITIALIZED),
1465 stack_trace_nesting_level_(0),
1466 incomplete_message_(NULL),
1467 bootstrapper_(NULL),
1468 runtime_profiler_(NULL),
1469 compilation_cache_(NULL),
1475 code_aging_helper_(NULL),
1476 deoptimizer_data_(NULL),
1477 materialized_object_store_(NULL),
1478 capture_stack_trace_for_uncaught_exceptions_(false),
1479 stack_trace_for_uncaught_exceptions_frame_limit_(0),
1480 stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview),
1481 memory_allocator_(NULL),
1482 keyed_lookup_cache_(NULL),
1483 context_slot_cache_(NULL),
1484 descriptor_lookup_cache_(NULL),
1485 handle_scope_implementer_(NULL),
1486 unicode_cache_(NULL),
1487 runtime_zone_(this),
1488 inner_pointer_to_code_cache_(NULL),
1489 write_iterator_(NULL),
1490 global_handles_(NULL),
1491 eternal_handles_(NULL),
1492 thread_manager_(NULL),
1493 has_installed_extensions_(false),
1494 string_tracker_(NULL),
1495 regexp_stack_(NULL),
1497 call_descriptor_data_(NULL),
1498 // TODO(bmeurer) Initialized lazily because it depends on flags; can
1499 // be fixed once the default isolate cleanup is done.
1500 random_number_generator_(NULL),
1501 serializer_enabled_(false),
1502 has_fatal_error_(false),
1503 initialized_from_snapshot_(false),
1504 cpu_profiler_(NULL),
1505 heap_profiler_(NULL),
1506 function_entry_hook_(NULL),
1507 deferred_handles_head_(NULL),
1508 optimizing_compiler_thread_(NULL),
1509 sweeper_thread_(NULL),
1510 num_sweeper_threads_(0),
1511 stress_deopt_count_(0),
1512 next_optimization_id_(0),
1513 use_counter_callback_(NULL),
1514 basic_block_profiler_(NULL) {
1516 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
1517 CHECK(thread_data_table_);
1519 id_ = base::NoBarrier_AtomicIncrement(&isolate_counter_, 1);
1520 TRACE_ISOLATE(constructor);
1522 memset(isolate_addresses_, 0,
1523 sizeof(isolate_addresses_[0]) * (kIsolateAddressCount + 1));
1525 heap_.isolate_ = this;
1526 stack_guard_.isolate_ = this;
1528 // ThreadManager is initialized early to support locking an isolate
1529 // before it is entered.
1530 thread_manager_ = new ThreadManager();
1531 thread_manager_->isolate_ = this;
1534 // heap_histograms_ initializes itself.
1535 memset(&js_spill_information_, 0, sizeof(js_spill_information_));
1538 handle_scope_data_.Initialize();
1540 #define ISOLATE_INIT_EXECUTE(type, name, initial_value) \
1541 name##_ = (initial_value);
1542 ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE)
1543 #undef ISOLATE_INIT_EXECUTE
1545 #define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length) \
1546 memset(name##_, 0, sizeof(type) * length);
1547 ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE)
1548 #undef ISOLATE_INIT_ARRAY_EXECUTE
1550 InitializeLoggingAndCounters();
1551 debug_ = new Debug(this);
1555 void Isolate::TearDown() {
1556 TRACE_ISOLATE(tear_down);
1558 // Temporarily set this isolate as current so that various parts of
1559 // the isolate can access it in their destructors without having a
1560 // direct pointer. We don't use Enter/Exit here to avoid
1561 // initializing the thread data.
1562 PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData();
1563 Isolate* saved_isolate = UncheckedCurrent();
1564 SetIsolateThreadLocals(this, NULL);
1569 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer());
1570 thread_data_table_->RemoveAllThreads(this);
1573 if (serialize_partial_snapshot_cache_ != NULL) {
1574 delete[] serialize_partial_snapshot_cache_;
1575 serialize_partial_snapshot_cache_ = NULL;
1580 // Restore the previous current isolate.
1581 SetIsolateThreadLocals(saved_isolate, saved_data);
1585 void Isolate::GlobalTearDown() {
1586 delete thread_data_table_;
1587 thread_data_table_ = NULL;
1591 void Isolate::Deinit() {
1592 if (state_ == INITIALIZED) {
1593 TRACE_ISOLATE(deinit);
1597 FreeThreadResources();
1599 if (concurrent_recompilation_enabled()) {
1600 optimizing_compiler_thread_->Stop();
1601 delete optimizing_compiler_thread_;
1602 optimizing_compiler_thread_ = NULL;
1605 for (int i = 0; i < num_sweeper_threads_; i++) {
1606 sweeper_thread_[i]->Stop();
1607 delete sweeper_thread_[i];
1608 sweeper_thread_[i] = NULL;
1610 delete[] sweeper_thread_;
1611 sweeper_thread_ = NULL;
1613 if (FLAG_job_based_sweeping &&
1614 heap_.mark_compact_collector()->sweeping_in_progress()) {
1615 heap_.mark_compact_collector()->EnsureSweepingCompleted();
1618 if (FLAG_turbo_stats) GetTStatistics()->Print("TurboFan");
1619 if (FLAG_hydrogen_stats) GetHStatistics()->Print("Hydrogen");
1621 if (FLAG_print_deopt_stress) {
1622 PrintF(stdout, "=== Stress deopt counter: %u\n", stress_deopt_count_);
1625 // We must stop the logger before we tear down other components.
1626 Sampler* sampler = logger_->sampler();
1627 if (sampler && sampler->IsActive()) sampler->Stop();
1629 delete deoptimizer_data_;
1630 deoptimizer_data_ = NULL;
1631 builtins_.TearDown();
1632 bootstrapper_->TearDown();
1634 if (runtime_profiler_ != NULL) {
1635 delete runtime_profiler_;
1636 runtime_profiler_ = NULL;
1639 delete basic_block_profiler_;
1640 basic_block_profiler_ = NULL;
1643 logger_->TearDown();
1645 delete heap_profiler_;
1646 heap_profiler_ = NULL;
1647 delete cpu_profiler_;
1648 cpu_profiler_ = NULL;
1650 // The default isolate is re-initializable due to legacy API.
1651 state_ = UNINITIALIZED;
1656 void Isolate::PushToPartialSnapshotCache(Object* obj) {
1657 int length = serialize_partial_snapshot_cache_length();
1658 int capacity = serialize_partial_snapshot_cache_capacity();
1660 if (length >= capacity) {
1661 int new_capacity = static_cast<int>((capacity + 10) * 1.2);
1662 Object** new_array = new Object*[new_capacity];
1663 for (int i = 0; i < length; i++) {
1664 new_array[i] = serialize_partial_snapshot_cache()[i];
1666 if (capacity != 0) delete[] serialize_partial_snapshot_cache();
1667 set_serialize_partial_snapshot_cache(new_array);
1668 set_serialize_partial_snapshot_cache_capacity(new_capacity);
1671 serialize_partial_snapshot_cache()[length] = obj;
1672 set_serialize_partial_snapshot_cache_length(length + 1);
1676 void Isolate::SetIsolateThreadLocals(Isolate* isolate,
1677 PerIsolateThreadData* data) {
1678 base::Thread::SetThreadLocal(isolate_key_, isolate);
1679 base::Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
1683 Isolate::~Isolate() {
1684 TRACE_ISOLATE(destructor);
1686 // Has to be called while counters_ are still alive
1687 runtime_zone_.DeleteKeptSegment();
1689 // The entry stack must be empty when we get here.
1690 DCHECK(entry_stack_ == NULL || entry_stack_->previous_item == NULL);
1692 delete entry_stack_;
1693 entry_stack_ = NULL;
1695 delete unicode_cache_;
1696 unicode_cache_ = NULL;
1701 delete[] call_descriptor_data_;
1702 call_descriptor_data_ = NULL;
1704 delete regexp_stack_;
1705 regexp_stack_ = NULL;
1707 delete descriptor_lookup_cache_;
1708 descriptor_lookup_cache_ = NULL;
1709 delete context_slot_cache_;
1710 context_slot_cache_ = NULL;
1711 delete keyed_lookup_cache_;
1712 keyed_lookup_cache_ = NULL;
1716 delete code_aging_helper_;
1717 code_aging_helper_ = NULL;
1718 delete stats_table_;
1719 stats_table_ = NULL;
1721 delete materialized_object_store_;
1722 materialized_object_store_ = NULL;
1730 delete handle_scope_implementer_;
1731 handle_scope_implementer_ = NULL;
1733 delete compilation_cache_;
1734 compilation_cache_ = NULL;
1735 delete bootstrapper_;
1736 bootstrapper_ = NULL;
1737 delete inner_pointer_to_code_cache_;
1738 inner_pointer_to_code_cache_ = NULL;
1739 delete write_iterator_;
1740 write_iterator_ = NULL;
1742 delete thread_manager_;
1743 thread_manager_ = NULL;
1745 delete string_tracker_;
1746 string_tracker_ = NULL;
1748 delete memory_allocator_;
1749 memory_allocator_ = NULL;
1752 delete global_handles_;
1753 global_handles_ = NULL;
1754 delete eternal_handles_;
1755 eternal_handles_ = NULL;
1757 delete string_stream_debug_object_cache_;
1758 string_stream_debug_object_cache_ = NULL;
1760 delete external_reference_table_;
1761 external_reference_table_ = NULL;
1763 delete random_number_generator_;
1764 random_number_generator_ = NULL;
1771 void Isolate::InitializeThreadLocal() {
1772 thread_local_top_.isolate_ = this;
1773 thread_local_top_.Initialize();
1777 bool Isolate::PropagatePendingExceptionToExternalTryCatch() {
1778 DCHECK(has_pending_exception());
1780 bool has_external_try_catch = HasExternalTryCatch();
1781 if (!has_external_try_catch) {
1782 thread_local_top_.external_caught_exception_ = false;
1786 bool catchable_by_js = is_catchable_by_javascript(pending_exception());
1787 if (catchable_by_js && IsFinallyOnTop()) {
1788 thread_local_top_.external_caught_exception_ = false;
1792 thread_local_top_.external_caught_exception_ = true;
1793 if (thread_local_top_.pending_exception_ == heap()->termination_exception()) {
1794 try_catch_handler()->can_continue_ = false;
1795 try_catch_handler()->has_terminated_ = true;
1796 try_catch_handler()->exception_ = heap()->null_value();
1798 v8::TryCatch* handler = try_catch_handler();
1799 DCHECK(thread_local_top_.pending_message_obj_->IsJSMessageObject() ||
1800 thread_local_top_.pending_message_obj_->IsTheHole());
1801 DCHECK(thread_local_top_.pending_message_script_->IsScript() ||
1802 thread_local_top_.pending_message_script_->IsTheHole());
1803 handler->can_continue_ = true;
1804 handler->has_terminated_ = false;
1805 handler->exception_ = pending_exception();
1806 // Propagate to the external try-catch only if we got an actual message.
1807 if (thread_local_top_.pending_message_obj_->IsTheHole()) return true;
1809 handler->message_obj_ = thread_local_top_.pending_message_obj_;
1810 handler->message_script_ = thread_local_top_.pending_message_script_;
1811 handler->message_start_pos_ = thread_local_top_.pending_message_start_pos_;
1812 handler->message_end_pos_ = thread_local_top_.pending_message_end_pos_;
1818 void Isolate::InitializeLoggingAndCounters() {
1819 if (logger_ == NULL) {
1820 logger_ = new Logger(this);
1822 if (counters_ == NULL) {
1823 counters_ = new Counters(this);
1828 bool Isolate::Init(Deserializer* des) {
1829 DCHECK(state_ != INITIALIZED);
1830 TRACE_ISOLATE(init);
1832 stress_deopt_count_ = FLAG_deopt_every_n_times;
1834 has_fatal_error_ = false;
1836 if (function_entry_hook() != NULL) {
1837 // When function entry hooking is in effect, we have to create the code
1838 // stubs from scratch to get entry hooks, rather than loading the previously
1839 // generated stubs from disk.
1840 // If this assert fires, the initialization path has regressed.
1841 DCHECK(des == NULL);
1844 // The initialization process does not handle memory exhaustion.
1845 DisallowAllocationFailure disallow_allocation_failure(this);
1847 memory_allocator_ = new MemoryAllocator(this);
1848 code_range_ = new CodeRange(this);
1850 // Safe after setting Heap::isolate_, and initializing StackGuard
1851 heap_.SetStackLimits();
1853 #define ASSIGN_ELEMENT(CamelName, hacker_name) \
1854 isolate_addresses_[Isolate::k##CamelName##Address] = \
1855 reinterpret_cast<Address>(hacker_name##_address());
1856 FOR_EACH_ISOLATE_ADDRESS_NAME(ASSIGN_ELEMENT)
1857 #undef ASSIGN_ELEMENT
1859 string_tracker_ = new StringTracker();
1860 string_tracker_->isolate_ = this;
1861 compilation_cache_ = new CompilationCache(this);
1862 keyed_lookup_cache_ = new KeyedLookupCache();
1863 context_slot_cache_ = new ContextSlotCache();
1864 descriptor_lookup_cache_ = new DescriptorLookupCache();
1865 unicode_cache_ = new UnicodeCache();
1866 inner_pointer_to_code_cache_ = new InnerPointerToCodeCache(this);
1867 write_iterator_ = new ConsStringIteratorOp();
1868 global_handles_ = new GlobalHandles(this);
1869 eternal_handles_ = new EternalHandles();
1870 bootstrapper_ = new Bootstrapper(this);
1871 handle_scope_implementer_ = new HandleScopeImplementer(this);
1872 stub_cache_ = new StubCache(this);
1873 materialized_object_store_ = new MaterializedObjectStore(this);
1874 regexp_stack_ = new RegExpStack();
1875 regexp_stack_->isolate_ = this;
1876 date_cache_ = new DateCache();
1877 call_descriptor_data_ =
1878 new CallInterfaceDescriptorData[CallDescriptors::NUMBER_OF_DESCRIPTORS];
1879 cpu_profiler_ = new CpuProfiler(this);
1880 heap_profiler_ = new HeapProfiler(heap());
1882 // Enable logging before setting up the heap
1883 logger_->SetUp(this);
1885 // Initialize other runtime facilities
1886 #if defined(USE_SIMULATOR)
1887 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || \
1888 V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
1889 Simulator::Initialize(this);
1893 code_aging_helper_ = new CodeAgingHelper();
1896 // Ensure that the thread has a valid stack guard. The v8::Locker object
1897 // will ensure this too, but we don't have to use lockers if we are only
1898 // using one thread.
1899 ExecutionAccess lock(this);
1900 stack_guard_.InitThread(lock);
1903 // SetUp the object heap.
1904 DCHECK(!heap_.HasBeenSetUp());
1905 if (!heap_.SetUp()) {
1906 V8::FatalProcessOutOfMemory("heap setup");
1910 deoptimizer_data_ = new DeoptimizerData(memory_allocator_);
1912 const bool create_heap_objects = (des == NULL);
1913 if (create_heap_objects && !heap_.CreateHeapObjects()) {
1914 V8::FatalProcessOutOfMemory("heap object creation");
1918 if (create_heap_objects) {
1919 // Terminate the cache array with the sentinel so we can iterate.
1920 PushToPartialSnapshotCache(heap_.undefined_value());
1923 InitializeThreadLocal();
1925 bootstrapper_->Initialize(create_heap_objects);
1926 builtins_.SetUp(this, create_heap_objects);
1928 if (FLAG_log_internal_timer_events) {
1929 set_event_logger(Logger::DefaultTimerEventsLogger);
1931 set_event_logger(Logger::EmptyTimerEventsLogger);
1934 // Set default value if not yet set.
1935 // TODO(yangguo): move this to ResourceConstraints::ConfigureDefaults
1936 // once ResourceConstraints becomes an argument to the Isolate constructor.
1937 if (max_available_threads_ < 1) {
1938 // Choose the default between 1 and 4.
1939 max_available_threads_ =
1940 Max(Min(base::SysInfo::NumberOfProcessors(), 4), 1);
1943 if (!FLAG_job_based_sweeping) {
1944 num_sweeper_threads_ =
1945 SweeperThread::NumberOfThreads(max_available_threads_);
1948 if (FLAG_trace_hydrogen || FLAG_trace_hydrogen_stubs) {
1949 PrintF("Concurrent recompilation has been disabled for tracing.\n");
1950 } else if (OptimizingCompilerThread::Enabled(max_available_threads_)) {
1951 optimizing_compiler_thread_ = new OptimizingCompilerThread(this);
1952 optimizing_compiler_thread_->Start();
1955 if (num_sweeper_threads_ > 0) {
1956 sweeper_thread_ = new SweeperThread*[num_sweeper_threads_];
1957 for (int i = 0; i < num_sweeper_threads_; i++) {
1958 sweeper_thread_[i] = new SweeperThread(this);
1959 sweeper_thread_[i]->Start();
1963 // If we are deserializing, read the state into the now-empty heap.
1964 if (!create_heap_objects) {
1965 des->Deserialize(this);
1967 stub_cache_->Initialize();
1969 // Finish initialization of ThreadLocal after deserialization is done.
1970 clear_pending_exception();
1971 clear_pending_message();
1972 clear_scheduled_exception();
1974 // Deserializing may put strange things in the root array's copy of the
1976 heap_.SetStackLimits();
1978 // Quiet the heap NaN if needed on target platform.
1979 if (!create_heap_objects) Assembler::QuietNaN(heap_.nan_value());
1981 runtime_profiler_ = new RuntimeProfiler(this);
1983 // If we are deserializing, log non-function code objects and compiled
1984 // functions found in the snapshot.
1985 if (!create_heap_objects &&
1988 FLAG_perf_jit_prof ||
1989 FLAG_perf_basic_prof ||
1990 logger_->is_logging_code_events())) {
1991 HandleScope scope(this);
1992 LOG(this, LogCodeObjects());
1993 LOG(this, LogCompiledFunctions());
1996 CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, embedder_data_)),
1997 Internals::kIsolateEmbedderDataOffset);
1998 CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.roots_)),
1999 Internals::kIsolateRootsOffset);
2000 CHECK_EQ(static_cast<int>(
2001 OFFSET_OF(Isolate, heap_.amount_of_external_allocated_memory_)),
2002 Internals::kAmountOfExternalAllocatedMemoryOffset);
2003 CHECK_EQ(static_cast<int>(OFFSET_OF(
2005 heap_.amount_of_external_allocated_memory_at_last_global_gc_)),
2006 Internals::kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset);
2008 state_ = INITIALIZED;
2009 time_millis_at_init_ = base::OS::TimeCurrentMillis();
2011 if (!create_heap_objects) {
2012 // Now that the heap is consistent, it's OK to generate the code for the
2013 // deopt entry table that might have been referred to by optimized code in
2015 HandleScope scope(this);
2016 Deoptimizer::EnsureCodeForDeoptimizationEntry(
2019 kDeoptTableSerializeEntryCount - 1);
2022 if (!serializer_enabled()) {
2023 // Ensure that all stubs which need to be generated ahead of time, but
2024 // cannot be serialized into the snapshot have been generated.
2025 HandleScope scope(this);
2026 CodeStub::GenerateFPStubs(this);
2027 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(this);
2028 StubFailureTrampolineStub::GenerateAheadOfTime(this);
2031 initialized_from_snapshot_ = (des != NULL);
2037 // Initialized lazily to allow early
2038 // v8::V8::SetAddHistogramSampleFunction calls.
2039 StatsTable* Isolate::stats_table() {
2040 if (stats_table_ == NULL) {
2041 stats_table_ = new StatsTable;
2043 return stats_table_;
2047 void Isolate::Enter() {
2048 Isolate* current_isolate = NULL;
2049 PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
2050 if (current_data != NULL) {
2051 current_isolate = current_data->isolate_;
2052 DCHECK(current_isolate != NULL);
2053 if (current_isolate == this) {
2054 DCHECK(Current() == this);
2055 DCHECK(entry_stack_ != NULL);
2056 DCHECK(entry_stack_->previous_thread_data == NULL ||
2057 entry_stack_->previous_thread_data->thread_id().Equals(
2058 ThreadId::Current()));
2059 // Same thread re-enters the isolate, no need to re-init anything.
2060 entry_stack_->entry_count++;
2065 PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
2066 DCHECK(data != NULL);
2067 DCHECK(data->isolate_ == this);
2069 EntryStackItem* item = new EntryStackItem(current_data,
2072 entry_stack_ = item;
2074 SetIsolateThreadLocals(this, data);
2076 // In case it's the first time some thread enters the isolate.
2077 set_thread_id(data->thread_id());
2081 void Isolate::Exit() {
2082 DCHECK(entry_stack_ != NULL);
2083 DCHECK(entry_stack_->previous_thread_data == NULL ||
2084 entry_stack_->previous_thread_data->thread_id().Equals(
2085 ThreadId::Current()));
2087 if (--entry_stack_->entry_count > 0) return;
2089 DCHECK(CurrentPerIsolateThreadData() != NULL);
2090 DCHECK(CurrentPerIsolateThreadData()->isolate_ == this);
2093 EntryStackItem* item = entry_stack_;
2094 entry_stack_ = item->previous_item;
2096 PerIsolateThreadData* previous_thread_data = item->previous_thread_data;
2097 Isolate* previous_isolate = item->previous_isolate;
2101 // Reinit the current thread for the isolate it was running before this one.
2102 SetIsolateThreadLocals(previous_isolate, previous_thread_data);
2106 void Isolate::LinkDeferredHandles(DeferredHandles* deferred) {
2107 deferred->next_ = deferred_handles_head_;
2108 if (deferred_handles_head_ != NULL) {
2109 deferred_handles_head_->previous_ = deferred;
2111 deferred_handles_head_ = deferred;
2115 void Isolate::UnlinkDeferredHandles(DeferredHandles* deferred) {
2117 // In debug mode assert that the linked list is well-formed.
2118 DeferredHandles* deferred_iterator = deferred;
2119 while (deferred_iterator->previous_ != NULL) {
2120 deferred_iterator = deferred_iterator->previous_;
2122 DCHECK(deferred_handles_head_ == deferred_iterator);
2124 if (deferred_handles_head_ == deferred) {
2125 deferred_handles_head_ = deferred_handles_head_->next_;
2127 if (deferred->next_ != NULL) {
2128 deferred->next_->previous_ = deferred->previous_;
2130 if (deferred->previous_ != NULL) {
2131 deferred->previous_->next_ = deferred->next_;
2136 HStatistics* Isolate::GetHStatistics() {
2137 if (hstatistics() == NULL) set_hstatistics(new HStatistics());
2138 return hstatistics();
2142 HStatistics* Isolate::GetTStatistics() {
2143 if (tstatistics() == NULL) set_tstatistics(new HStatistics());
2144 return tstatistics();
2148 HTracer* Isolate::GetHTracer() {
2149 if (htracer() == NULL) set_htracer(new HTracer(id()));
2154 CodeTracer* Isolate::GetCodeTracer() {
2155 if (code_tracer() == NULL) set_code_tracer(new CodeTracer(id()));
2156 return code_tracer();
2160 Map* Isolate::get_initial_js_array_map(ElementsKind kind) {
2161 Context* native_context = context()->native_context();
2162 Object* maybe_map_array = native_context->js_array_maps();
2163 if (!maybe_map_array->IsUndefined()) {
2164 Object* maybe_transitioned_map =
2165 FixedArray::cast(maybe_map_array)->get(kind);
2166 if (!maybe_transitioned_map->IsUndefined()) {
2167 return Map::cast(maybe_transitioned_map);
2174 bool Isolate::use_crankshaft() const {
2175 return FLAG_crankshaft &&
2176 !serializer_enabled_ &&
2177 CpuFeatures::SupportsCrankshaft();
2181 bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
2182 Map* root_array_map =
2183 get_initial_js_array_map(GetInitialFastElementsKind());
2184 DCHECK(root_array_map != NULL);
2185 JSObject* initial_array_proto = JSObject::cast(*initial_array_prototype());
2187 // Check that the array prototype hasn't been altered WRT empty elements.
2188 if (root_array_map->prototype() != initial_array_proto) return false;
2189 if (initial_array_proto->elements() != heap()->empty_fixed_array()) {
2193 // Check that the object prototype hasn't been altered WRT empty elements.
2194 JSObject* initial_object_proto = JSObject::cast(*initial_object_prototype());
2195 PrototypeIterator iter(this, initial_array_proto);
2196 if (iter.IsAtEnd() || iter.GetCurrent() != initial_object_proto) {
2199 if (initial_object_proto->elements() != heap()->empty_fixed_array()) {
2204 return iter.IsAtEnd();
2208 CallInterfaceDescriptorData* Isolate::call_descriptor_data(int index) {
2209 DCHECK(0 <= index && index < CallDescriptors::NUMBER_OF_DESCRIPTORS);
2210 return &call_descriptor_data_[index];
2214 Object* Isolate::FindCodeObject(Address a) {
2215 return inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(a);
2220 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \
2221 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_);
2222 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
2223 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
2224 #undef ISOLATE_FIELD_OFFSET
2228 Handle<JSObject> Isolate::GetSymbolRegistry() {
2229 if (heap()->symbol_registry()->IsUndefined()) {
2230 Handle<Map> map = factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
2231 Handle<JSObject> registry = factory()->NewJSObjectFromMap(map);
2232 heap()->set_symbol_registry(*registry);
2234 static const char* nested[] = {
2235 "for", "for_api", "for_intern", "keyFor", "private_api", "private_intern"
2237 for (unsigned i = 0; i < arraysize(nested); ++i) {
2238 Handle<String> name = factory()->InternalizeUtf8String(nested[i]);
2239 Handle<JSObject> obj = factory()->NewJSObjectFromMap(map);
2240 JSObject::NormalizeProperties(obj, KEEP_INOBJECT_PROPERTIES, 8);
2241 JSObject::SetProperty(registry, name, obj, STRICT).Assert();
2244 return Handle<JSObject>::cast(factory()->symbol_registry());
2248 void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
2249 for (int i = 0; i < call_completed_callbacks_.length(); i++) {
2250 if (callback == call_completed_callbacks_.at(i)) return;
2252 call_completed_callbacks_.Add(callback);
2256 void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
2257 for (int i = 0; i < call_completed_callbacks_.length(); i++) {
2258 if (callback == call_completed_callbacks_.at(i)) {
2259 call_completed_callbacks_.Remove(i);
2265 void Isolate::FireCallCompletedCallback() {
2266 bool has_call_completed_callbacks = !call_completed_callbacks_.is_empty();
2267 bool run_microtasks = autorun_microtasks() && pending_microtask_count();
2268 if (!has_call_completed_callbacks && !run_microtasks) return;
2270 if (!handle_scope_implementer()->CallDepthIsZero()) return;
2271 if (run_microtasks) RunMicrotasks();
2272 // Fire callbacks. Increase call depth to prevent recursive callbacks.
2273 v8::Isolate::SuppressMicrotaskExecutionScope suppress(
2274 reinterpret_cast<v8::Isolate*>(this));
2275 for (int i = 0; i < call_completed_callbacks_.length(); i++) {
2276 call_completed_callbacks_.at(i)();
2281 void Isolate::EnqueueMicrotask(Handle<Object> microtask) {
2282 DCHECK(microtask->IsJSFunction() || microtask->IsCallHandlerInfo());
2283 Handle<FixedArray> queue(heap()->microtask_queue(), this);
2284 int num_tasks = pending_microtask_count();
2285 DCHECK(num_tasks <= queue->length());
2286 if (num_tasks == 0) {
2287 queue = factory()->NewFixedArray(8);
2288 heap()->set_microtask_queue(*queue);
2289 } else if (num_tasks == queue->length()) {
2290 queue = FixedArray::CopySize(queue, num_tasks * 2);
2291 heap()->set_microtask_queue(*queue);
2293 DCHECK(queue->get(num_tasks)->IsUndefined());
2294 queue->set(num_tasks, *microtask);
2295 set_pending_microtask_count(num_tasks + 1);
2299 void Isolate::RunMicrotasks() {
2300 // %RunMicrotasks may be called in mjsunit tests, which violates
2301 // this assertion, hence the check for --allow-natives-syntax.
2302 // TODO(adamk): However, this also fails some layout tests.
2304 // DCHECK(FLAG_allow_natives_syntax ||
2305 // handle_scope_implementer()->CallDepthIsZero());
2307 // Increase call depth to prevent recursive callbacks.
2308 v8::Isolate::SuppressMicrotaskExecutionScope suppress(
2309 reinterpret_cast<v8::Isolate*>(this));
2311 while (pending_microtask_count() > 0) {
2312 HandleScope scope(this);
2313 int num_tasks = pending_microtask_count();
2314 Handle<FixedArray> queue(heap()->microtask_queue(), this);
2315 DCHECK(num_tasks <= queue->length());
2316 set_pending_microtask_count(0);
2317 heap()->set_microtask_queue(heap()->empty_fixed_array());
2319 for (int i = 0; i < num_tasks; i++) {
2320 HandleScope scope(this);
2321 Handle<Object> microtask(queue->get(i), this);
2322 if (microtask->IsJSFunction()) {
2323 Handle<JSFunction> microtask_function =
2324 Handle<JSFunction>::cast(microtask);
2325 SaveContext save(this);
2326 set_context(microtask_function->context()->native_context());
2327 MaybeHandle<Object> maybe_exception;
2328 MaybeHandle<Object> result =
2329 Execution::TryCall(microtask_function, factory()->undefined_value(),
2330 0, NULL, &maybe_exception);
2331 // If execution is terminating, just bail out.
2332 Handle<Object> exception;
2333 if (result.is_null() && maybe_exception.is_null()) {
2334 // Clear out any remaining callbacks in the queue.
2335 heap()->set_microtask_queue(heap()->empty_fixed_array());
2336 set_pending_microtask_count(0);
2340 Handle<CallHandlerInfo> callback_info =
2341 Handle<CallHandlerInfo>::cast(microtask);
2342 v8::MicrotaskCallback callback =
2343 v8::ToCData<v8::MicrotaskCallback>(callback_info->callback());
2344 void* data = v8::ToCData<void*>(callback_info->data());
2352 void Isolate::SetUseCounterCallback(v8::Isolate::UseCounterCallback callback) {
2353 DCHECK(!use_counter_callback_);
2354 use_counter_callback_ = callback;
2358 void Isolate::CountUsage(v8::Isolate::UseCounterFeature feature) {
2359 if (use_counter_callback_) {
2360 use_counter_callback_(reinterpret_cast<v8::Isolate*>(this), feature);
2365 BasicBlockProfiler* Isolate::GetOrCreateBasicBlockProfiler() {
2366 if (basic_block_profiler_ == NULL) {
2367 basic_block_profiler_ = new BasicBlockProfiler();
2369 return basic_block_profiler_;
2373 bool StackLimitCheck::JsHasOverflowed() const {
2374 StackGuard* stack_guard = isolate_->stack_guard();
2375 #ifdef USE_SIMULATOR
2376 // The simulator uses a separate JS stack.
2377 Address jssp_address = Simulator::current(isolate_)->get_sp();
2378 uintptr_t jssp = reinterpret_cast<uintptr_t>(jssp_address);
2379 if (jssp < stack_guard->real_jslimit()) return true;
2380 #endif // USE_SIMULATOR
2381 return GetCurrentStackPosition() < stack_guard->real_climit();
2385 bool PostponeInterruptsScope::Intercept(StackGuard::InterruptFlag flag) {
2386 // First check whether the previous scope intercepts.
2387 if (prev_ && prev_->Intercept(flag)) return true;
2388 // Then check whether this scope intercepts.
2389 if ((flag & intercept_mask_)) {
2390 intercepted_flags_ |= flag;
2396 } } // namespace v8::internal