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