1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #include <stdlib.h> 29 30 #include "v8.h" 31 32 #include "ast.h" 33 #include "bootstrapper.h" 34 #include "codegen.h" 35 #include "compilation-cache.h" 36 #include "debug.h" 37 #include "deoptimizer.h" 38 #include "heap-profiler.h" 39 #include "hydrogen.h" 40 #include "isolate.h" 41 #include "lithium-allocator.h" 42 #include "log.h" 43 #include "regexp-stack.h" 44 #include "runtime-profiler.h" 45 #include "scanner.h" 46 #include "scopeinfo.h" 47 #include "serialize.h" 48 #include "simulator.h" 49 #include "spaces.h" 50 #include "stub-cache.h" 51 #include "version.h" 52 53 54 namespace v8 { 55 namespace internal { 56 57 Atomic32 ThreadId::highest_thread_id_ = 0; 58 59 int ThreadId::AllocateThreadId() { 60 int new_id = NoBarrier_AtomicIncrement(&highest_thread_id_, 1); 61 return new_id; 62 } 63 64 int ThreadId::GetCurrentThreadId() { 65 int thread_id = Thread::GetThreadLocalInt(Isolate::thread_id_key_); 66 if (thread_id == 0) { 67 thread_id = AllocateThreadId(); 68 Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id); 69 } 70 return thread_id; 71 } 72 73 74 // Create a dummy thread that will wait forever on a semaphore. The only 75 // purpose for this thread is to have some stack area to save essential data 76 // into for use by a stacks only core dump (aka minidump). 77 class PreallocatedMemoryThread: public Thread { 78 public: 79 char* data() { 80 if (data_ready_semaphore_ != NULL) { 81 // Initial access is guarded until the data has been published. 82 data_ready_semaphore_->Wait(); 83 delete data_ready_semaphore_; 84 data_ready_semaphore_ = NULL; 85 } 86 return data_; 87 } 88 89 unsigned length() { 90 if (data_ready_semaphore_ != NULL) { 91 // Initial access is guarded until the data has been published. 92 data_ready_semaphore_->Wait(); 93 delete data_ready_semaphore_; 94 data_ready_semaphore_ = NULL; 95 } 96 return length_; 97 } 98 99 // Stop the PreallocatedMemoryThread and release its resources. 100 void StopThread() { 101 keep_running_ = false; 102 wait_for_ever_semaphore_->Signal(); 103 104 // Wait for the thread to terminate. 105 Join(); 106 107 if (data_ready_semaphore_ != NULL) { 108 delete data_ready_semaphore_; 109 data_ready_semaphore_ = NULL; 110 } 111 112 delete wait_for_ever_semaphore_; 113 wait_for_ever_semaphore_ = NULL; 114 } 115 116 protected: 117 // When the thread starts running it will allocate a fixed number of bytes 118 // on the stack and publish the location of this memory for others to use. 119 void Run() { 120 EmbeddedVector<char, 15 * 1024> local_buffer; 121 122 // Initialize the buffer with a known good value. 123 OS::StrNCpy(local_buffer, "Trace data was not generated.\n", 124 local_buffer.length()); 125 126 // Publish the local buffer and signal its availability. 127 data_ = local_buffer.start(); 128 length_ = local_buffer.length(); 129 data_ready_semaphore_->Signal(); 130 131 while (keep_running_) { 132 // This thread will wait here until the end of time. 133 wait_for_ever_semaphore_->Wait(); 134 } 135 136 // Make sure we access the buffer after the wait to remove all possibility 137 // of it being optimized away. 138 OS::StrNCpy(local_buffer, "PreallocatedMemoryThread shutting down.\n", 139 local_buffer.length()); 140 } 141 142 143 private: 144 explicit PreallocatedMemoryThread(Isolate* isolate) 145 : Thread(isolate, "v8:PreallocMem"), 146 keep_running_(true), 147 wait_for_ever_semaphore_(OS::CreateSemaphore(0)), 148 data_ready_semaphore_(OS::CreateSemaphore(0)), 149 data_(NULL), 150 length_(0) { 151 } 152 153 // Used to make sure that the thread keeps looping even for spurious wakeups. 154 bool keep_running_; 155 156 // This semaphore is used by the PreallocatedMemoryThread to wait for ever. 157 Semaphore* wait_for_ever_semaphore_; 158 // Semaphore to signal that the data has been initialized. 159 Semaphore* data_ready_semaphore_; 160 161 // Location and size of the preallocated memory block. 162 char* data_; 163 unsigned length_; 164 165 friend class Isolate; 166 167 DISALLOW_COPY_AND_ASSIGN(PreallocatedMemoryThread); 168 }; 169 170 171 void Isolate::PreallocatedMemoryThreadStart() { 172 if (preallocated_memory_thread_ != NULL) return; 173 preallocated_memory_thread_ = new PreallocatedMemoryThread(this); 174 preallocated_memory_thread_->Start(); 175 } 176 177 178 void Isolate::PreallocatedMemoryThreadStop() { 179 if (preallocated_memory_thread_ == NULL) return; 180 preallocated_memory_thread_->StopThread(); 181 // Done with the thread entirely. 182 delete preallocated_memory_thread_; 183 preallocated_memory_thread_ = NULL; 184 } 185 186 187 void Isolate::PreallocatedStorageInit(size_t size) { 188 ASSERT(free_list_.next_ == &free_list_); 189 ASSERT(free_list_.previous_ == &free_list_); 190 PreallocatedStorage* free_chunk = 191 reinterpret_cast<PreallocatedStorage*>(new char[size]); 192 free_list_.next_ = free_list_.previous_ = free_chunk; 193 free_chunk->next_ = free_chunk->previous_ = &free_list_; 194 free_chunk->size_ = size - sizeof(PreallocatedStorage); 195 preallocated_storage_preallocated_ = true; 196 } 197 198 199 void* Isolate::PreallocatedStorageNew(size_t size) { 200 if (!preallocated_storage_preallocated_) { 201 return FreeStoreAllocationPolicy::New(size); 202 } 203 ASSERT(free_list_.next_ != &free_list_); 204 ASSERT(free_list_.previous_ != &free_list_); 205 206 size = (size + kPointerSize - 1) & ~(kPointerSize - 1); 207 // Search for exact fit. 208 for (PreallocatedStorage* storage = free_list_.next_; 209 storage != &free_list_; 210 storage = storage->next_) { 211 if (storage->size_ == size) { 212 storage->Unlink(); 213 storage->LinkTo(&in_use_list_); 214 return reinterpret_cast<void*>(storage + 1); 215 } 216 } 217 // Search for first fit. 218 for (PreallocatedStorage* storage = free_list_.next_; 219 storage != &free_list_; 220 storage = storage->next_) { 221 if (storage->size_ >= size + sizeof(PreallocatedStorage)) { 222 storage->Unlink(); 223 storage->LinkTo(&in_use_list_); 224 PreallocatedStorage* left_over = 225 reinterpret_cast<PreallocatedStorage*>( 226 reinterpret_cast<char*>(storage + 1) + size); 227 left_over->size_ = storage->size_ - size - sizeof(PreallocatedStorage); 228 ASSERT(size + left_over->size_ + sizeof(PreallocatedStorage) == 229 storage->size_); 230 storage->size_ = size; 231 left_over->LinkTo(&free_list_); 232 return reinterpret_cast<void*>(storage + 1); 233 } 234 } 235 // Allocation failure. 236 ASSERT(false); 237 return NULL; 238 } 239 240 241 // We don't attempt to coalesce. 242 void Isolate::PreallocatedStorageDelete(void* p) { 243 if (p == NULL) { 244 return; 245 } 246 if (!preallocated_storage_preallocated_) { 247 FreeStoreAllocationPolicy::Delete(p); 248 return; 249 } 250 PreallocatedStorage* storage = reinterpret_cast<PreallocatedStorage*>(p) - 1; 251 ASSERT(storage->next_->previous_ == storage); 252 ASSERT(storage->previous_->next_ == storage); 253 storage->Unlink(); 254 storage->LinkTo(&free_list_); 255 } 256 257 258 Isolate* Isolate::default_isolate_ = NULL; 259 Thread::LocalStorageKey Isolate::isolate_key_; 260 Thread::LocalStorageKey Isolate::thread_id_key_; 261 Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_; 262 Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex(); 263 Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL; 264 265 266 class IsolateInitializer { 267 public: 268 IsolateInitializer() { 269 Isolate::EnsureDefaultIsolate(); 270 } 271 }; 272 273 static IsolateInitializer* EnsureDefaultIsolateAllocated() { 274 // TODO(isolates): Use the system threading API to do this once? 275 static IsolateInitializer static_initializer; 276 return &static_initializer; 277 } 278 279 // This variable only needed to trigger static intialization. 280 static IsolateInitializer* static_initializer = EnsureDefaultIsolateAllocated(); 281 282 283 284 285 286 Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData( 287 ThreadId thread_id) { 288 ASSERT(!thread_id.Equals(ThreadId::Invalid())); 289 PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id); 290 { 291 ScopedLock lock(process_wide_mutex_); 292 ASSERT(thread_data_table_->Lookup(this, thread_id) == NULL); 293 thread_data_table_->Insert(per_thread); 294 ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread); 295 } 296 return per_thread; 297 } 298 299 300 Isolate::PerIsolateThreadData* 301 Isolate::FindOrAllocatePerThreadDataForThisThread() { 302 ThreadId thread_id = ThreadId::Current(); 303 PerIsolateThreadData* per_thread = NULL; 304 { 305 ScopedLock lock(process_wide_mutex_); 306 per_thread = thread_data_table_->Lookup(this, thread_id); 307 if (per_thread == NULL) { 308 per_thread = AllocatePerIsolateThreadData(thread_id); 309 } 310 } 311 return per_thread; 312 } 313 314 315 void Isolate::EnsureDefaultIsolate() { 316 ScopedLock lock(process_wide_mutex_); 317 if (default_isolate_ == NULL) { 318 isolate_key_ = Thread::CreateThreadLocalKey(); 319 thread_id_key_ = Thread::CreateThreadLocalKey(); 320 per_isolate_thread_data_key_ = Thread::CreateThreadLocalKey(); 321 thread_data_table_ = new Isolate::ThreadDataTable(); 322 default_isolate_ = new Isolate(); 323 } 324 // Can't use SetIsolateThreadLocals(default_isolate_, NULL) here 325 // becase a non-null thread data may be already set. 326 Thread::SetThreadLocal(isolate_key_, default_isolate_); 327 } 328 329 330 Debugger* Isolate::GetDefaultIsolateDebugger() { 331 EnsureDefaultIsolate(); 332 return default_isolate_->debugger(); 333 } 334 335 336 StackGuard* Isolate::GetDefaultIsolateStackGuard() { 337 EnsureDefaultIsolate(); 338 return default_isolate_->stack_guard(); 339 } 340 341 342 void Isolate::EnterDefaultIsolate() { 343 EnsureDefaultIsolate(); 344 ASSERT(default_isolate_ != NULL); 345 346 PerIsolateThreadData* data = CurrentPerIsolateThreadData(); 347 // If not yet in default isolate - enter it. 348 if (data == NULL || data->isolate() != default_isolate_) { 349 default_isolate_->Enter(); 350 } 351 } 352 353 354 Isolate* Isolate::GetDefaultIsolateForLocking() { 355 EnsureDefaultIsolate(); 356 return default_isolate_; 357 } 358 359 360 Isolate::ThreadDataTable::ThreadDataTable() 361 : list_(NULL) { 362 } 363 364 365 Isolate::PerIsolateThreadData* 366 Isolate::ThreadDataTable::Lookup(Isolate* isolate, 367 ThreadId thread_id) { 368 for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) { 369 if (data->Matches(isolate, thread_id)) return data; 370 } 371 return NULL; 372 } 373 374 375 void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) { 376 if (list_ != NULL) list_->prev_ = data; 377 data->next_ = list_; 378 list_ = data; 379 } 380 381 382 void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) { 383 if (list_ == data) list_ = data->next_; 384 if (data->next_ != NULL) data->next_->prev_ = data->prev_; 385 if (data->prev_ != NULL) data->prev_->next_ = data->next_; 386 } 387 388 389 void Isolate::ThreadDataTable::Remove(Isolate* isolate, 390 ThreadId thread_id) { 391 PerIsolateThreadData* data = Lookup(isolate, thread_id); 392 if (data != NULL) { 393 Remove(data); 394 } 395 } 396 397 398 #ifdef DEBUG 399 #define TRACE_ISOLATE(tag) \ 400 do { \ 401 if (FLAG_trace_isolates) { \ 402 PrintF("Isolate %p " #tag "\n", reinterpret_cast<void*>(this)); \ 403 } \ 404 } while (false) 405 #else 406 #define TRACE_ISOLATE(tag) 407 #endif 408 409 410 Isolate::Isolate() 411 : state_(UNINITIALIZED), 412 entry_stack_(NULL), 413 stack_trace_nesting_level_(0), 414 incomplete_message_(NULL), 415 preallocated_memory_thread_(NULL), 416 preallocated_message_space_(NULL), 417 bootstrapper_(NULL), 418 runtime_profiler_(NULL), 419 compilation_cache_(NULL), 420 counters_(NULL), 421 code_range_(NULL), 422 // Must be initialized early to allow v8::SetResourceConstraints calls. 423 break_access_(OS::CreateMutex()), 424 debugger_initialized_(false), 425 // Must be initialized early to allow v8::Debug calls. 426 debugger_access_(OS::CreateMutex()), 427 logger_(NULL), 428 stats_table_(NULL), 429 stub_cache_(NULL), 430 deoptimizer_data_(NULL), 431 capture_stack_trace_for_uncaught_exceptions_(false), 432 stack_trace_for_uncaught_exceptions_frame_limit_(0), 433 stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview), 434 transcendental_cache_(NULL), 435 memory_allocator_(NULL), 436 keyed_lookup_cache_(NULL), 437 context_slot_cache_(NULL), 438 descriptor_lookup_cache_(NULL), 439 handle_scope_implementer_(NULL), 440 unicode_cache_(NULL), 441 in_use_list_(0), 442 free_list_(0), 443 preallocated_storage_preallocated_(false), 444 pc_to_code_cache_(NULL), 445 write_input_buffer_(NULL), 446 global_handles_(NULL), 447 context_switcher_(NULL), 448 thread_manager_(NULL), 449 ast_sentinels_(NULL), 450 string_tracker_(NULL), 451 regexp_stack_(NULL), 452 frame_element_constant_list_(0), 453 result_constant_list_(0) { 454 TRACE_ISOLATE(constructor); 455 456 memset(isolate_addresses_, 0, 457 sizeof(isolate_addresses_[0]) * (k_isolate_address_count + 1)); 458 459 heap_.isolate_ = this; 460 zone_.isolate_ = this; 461 stack_guard_.isolate_ = this; 462 463 #if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \ 464 defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__) 465 simulator_initialized_ = false; 466 simulator_i_cache_ = NULL; 467 simulator_redirection_ = NULL; 468 #endif 469 470 thread_manager_ = new ThreadManager(); 471 thread_manager_->isolate_ = this; 472 473 #ifdef DEBUG 474 // heap_histograms_ initializes itself. 475 memset(&js_spill_information_, 0, sizeof(js_spill_information_)); 476 memset(code_kind_statistics_, 0, 477 sizeof(code_kind_statistics_[0]) * Code::NUMBER_OF_KINDS); 478 #endif 479 480 #ifdef ENABLE_DEBUGGER_SUPPORT 481 debug_ = NULL; 482 debugger_ = NULL; 483 #endif 484 485 #ifdef ENABLE_LOGGING_AND_PROFILING 486 producer_heap_profile_ = NULL; 487 #endif 488 489 handle_scope_data_.Initialize(); 490 491 #define ISOLATE_INIT_EXECUTE(type, name, initial_value) \ 492 name##_ = (initial_value); 493 ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE) 494 #undef ISOLATE_INIT_EXECUTE 495 496 #define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length) \ 497 memset(name##_, 0, sizeof(type) * length); 498 ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE) 499 #undef ISOLATE_INIT_ARRAY_EXECUTE 500 } 501 502 void Isolate::TearDown() { 503 TRACE_ISOLATE(tear_down); 504 505 // Temporarily set this isolate as current so that various parts of 506 // the isolate can access it in their destructors without having a 507 // direct pointer. We don't use Enter/Exit here to avoid 508 // initializing the thread data. 509 PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData(); 510 Isolate* saved_isolate = UncheckedCurrent(); 511 SetIsolateThreadLocals(this, NULL); 512 513 Deinit(); 514 515 if (!IsDefaultIsolate()) { 516 delete this; 517 } 518 519 // Restore the previous current isolate. 520 SetIsolateThreadLocals(saved_isolate, saved_data); 521 } 522 523 524 void Isolate::Deinit() { 525 if (state_ == INITIALIZED) { 526 TRACE_ISOLATE(deinit); 527 528 if (FLAG_hydrogen_stats) HStatistics::Instance()->Print(); 529 530 // We must stop the logger before we tear down other components. 531 logger_->EnsureTickerStopped(); 532 533 delete deoptimizer_data_; 534 deoptimizer_data_ = NULL; 535 if (FLAG_preemption) { 536 v8::Locker locker; 537 v8::Locker::StopPreemption(); 538 } 539 builtins_.TearDown(); 540 bootstrapper_->TearDown(); 541 542 // Remove the external reference to the preallocated stack memory. 543 delete preallocated_message_space_; 544 preallocated_message_space_ = NULL; 545 PreallocatedMemoryThreadStop(); 546 547 HeapProfiler::TearDown(); 548 CpuProfiler::TearDown(); 549 if (runtime_profiler_ != NULL) { 550 runtime_profiler_->TearDown(); 551 delete runtime_profiler_; 552 runtime_profiler_ = NULL; 553 } 554 heap_.TearDown(); 555 logger_->TearDown(); 556 557 // The default isolate is re-initializable due to legacy API. 558 state_ = UNINITIALIZED; 559 } 560 } 561 562 563 void Isolate::SetIsolateThreadLocals(Isolate* isolate, 564 PerIsolateThreadData* data) { 565 Thread::SetThreadLocal(isolate_key_, isolate); 566 Thread::SetThreadLocal(per_isolate_thread_data_key_, data); 567 } 568 569 570 Isolate::~Isolate() { 571 TRACE_ISOLATE(destructor); 572 573 #ifdef ENABLE_LOGGING_AND_PROFILING 574 delete producer_heap_profile_; 575 producer_heap_profile_ = NULL; 576 #endif 577 578 delete unicode_cache_; 579 unicode_cache_ = NULL; 580 581 delete regexp_stack_; 582 regexp_stack_ = NULL; 583 584 delete ast_sentinels_; 585 ast_sentinels_ = NULL; 586 587 delete descriptor_lookup_cache_; 588 descriptor_lookup_cache_ = NULL; 589 delete context_slot_cache_; 590 context_slot_cache_ = NULL; 591 delete keyed_lookup_cache_; 592 keyed_lookup_cache_ = NULL; 593 594 delete transcendental_cache_; 595 transcendental_cache_ = NULL; 596 delete stub_cache_; 597 stub_cache_ = NULL; 598 delete stats_table_; 599 stats_table_ = NULL; 600 601 delete logger_; 602 logger_ = NULL; 603 604 delete counters_; 605 counters_ = NULL; 606 607 delete handle_scope_implementer_; 608 handle_scope_implementer_ = NULL; 609 delete break_access_; 610 break_access_ = NULL; 611 612 delete compilation_cache_; 613 compilation_cache_ = NULL; 614 delete bootstrapper_; 615 bootstrapper_ = NULL; 616 delete pc_to_code_cache_; 617 pc_to_code_cache_ = NULL; 618 delete write_input_buffer_; 619 write_input_buffer_ = NULL; 620 621 delete context_switcher_; 622 context_switcher_ = NULL; 623 delete thread_manager_; 624 thread_manager_ = NULL; 625 626 delete string_tracker_; 627 string_tracker_ = NULL; 628 629 delete memory_allocator_; 630 memory_allocator_ = NULL; 631 delete code_range_; 632 code_range_ = NULL; 633 delete global_handles_; 634 global_handles_ = NULL; 635 636 #ifdef ENABLE_DEBUGGER_SUPPORT 637 delete debugger_; 638 debugger_ = NULL; 639 delete debug_; 640 debug_ = NULL; 641 #endif 642 } 643 644 645 void Isolate::InitializeThreadLocal() { 646 thread_local_top_.Initialize(); 647 clear_pending_exception(); 648 clear_pending_message(); 649 clear_scheduled_exception(); 650 } 651 652 653 void Isolate::PropagatePendingExceptionToExternalTryCatch() { 654 ASSERT(has_pending_exception()); 655 656 bool external_caught = IsExternallyCaught(); 657 thread_local_top_.external_caught_exception_ = external_caught; 658 659 if (!external_caught) return; 660 661 if (thread_local_top_.pending_exception_ == Failure::OutOfMemoryException()) { 662 // Do not propagate OOM exception: we should kill VM asap. 663 } else if (thread_local_top_.pending_exception_ == 664 heap()->termination_exception()) { 665 try_catch_handler()->can_continue_ = false; 666 try_catch_handler()->exception_ = heap()->null_value(); 667 } else { 668 // At this point all non-object (failure) exceptions have 669 // been dealt with so this shouldn't fail. 670 ASSERT(!pending_exception()->IsFailure()); 671 try_catch_handler()->can_continue_ = true; 672 try_catch_handler()->exception_ = pending_exception(); 673 if (!thread_local_top_.pending_message_obj_->IsTheHole()) { 674 try_catch_handler()->message_ = thread_local_top_.pending_message_obj_; 675 } 676 } 677 } 678 679 680 void Isolate::InitializeLoggingAndCounters() { 681 if (logger_ == NULL) { 682 logger_ = new Logger; 683 } 684 if (counters_ == NULL) { 685 counters_ = new Counters; 686 } 687 } 688 689 690 void Isolate::InitializeDebugger() { 691 #ifdef ENABLE_DEBUGGER_SUPPORT 692 ScopedLock lock(debugger_access_); 693 if (NoBarrier_Load(&debugger_initialized_)) return; 694 InitializeLoggingAndCounters(); 695 debug_ = new Debug(this); 696 debugger_ = new Debugger(this); 697 Release_Store(&debugger_initialized_, true); 698 #endif 699 } 700 701 702 bool Isolate::Init(Deserializer* des) { 703 ASSERT(state_ != INITIALIZED); 704 ASSERT(Isolate::Current() == this); 705 TRACE_ISOLATE(init); 706 707 #ifdef DEBUG 708 // The initialization process does not handle memory exhaustion. 709 DisallowAllocationFailure disallow_allocation_failure; 710 #endif 711 712 InitializeLoggingAndCounters(); 713 714 InitializeDebugger(); 715 716 memory_allocator_ = new MemoryAllocator(this); 717 code_range_ = new CodeRange(this); 718 719 // Safe after setting Heap::isolate_, initializing StackGuard and 720 // ensuring that Isolate::Current() == this. 721 heap_.SetStackLimits(); 722 723 #define C(name) isolate_addresses_[Isolate::k_##name] = \ 724 reinterpret_cast<Address>(name()); 725 ISOLATE_ADDRESS_LIST(C) 726 ISOLATE_ADDRESS_LIST_PROF(C) 727 #undef C 728 729 string_tracker_ = new StringTracker(); 730 string_tracker_->isolate_ = this; 731 compilation_cache_ = new CompilationCache(this); 732 transcendental_cache_ = new TranscendentalCache(); 733 keyed_lookup_cache_ = new KeyedLookupCache(); 734 context_slot_cache_ = new ContextSlotCache(); 735 descriptor_lookup_cache_ = new DescriptorLookupCache(); 736 unicode_cache_ = new UnicodeCache(); 737 pc_to_code_cache_ = new PcToCodeCache(this); 738 write_input_buffer_ = new StringInputBuffer(); 739 global_handles_ = new GlobalHandles(this); 740 bootstrapper_ = new Bootstrapper(); 741 handle_scope_implementer_ = new HandleScopeImplementer(); 742 stub_cache_ = new StubCache(this); 743 ast_sentinels_ = new AstSentinels(); 744 regexp_stack_ = new RegExpStack(); 745 regexp_stack_->isolate_ = this; 746 747 #ifdef ENABLE_LOGGING_AND_PROFILING 748 producer_heap_profile_ = new ProducerHeapProfile(); 749 producer_heap_profile_->isolate_ = this; 750 #endif 751 752 // Enable logging before setting up the heap 753 logger_->Setup(); 754 755 CpuProfiler::Setup(); 756 HeapProfiler::Setup(); 757 758 // Initialize other runtime facilities 759 #if defined(USE_SIMULATOR) 760 #if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) 761 Simulator::Initialize(); 762 #endif 763 #endif 764 765 { // NOLINT 766 // Ensure that the thread has a valid stack guard. The v8::Locker object 767 // will ensure this too, but we don't have to use lockers if we are only 768 // using one thread. 769 ExecutionAccess lock(this); 770 stack_guard_.InitThread(lock); 771 } 772 773 // Setup the object heap. 774 const bool create_heap_objects = (des == NULL); 775 ASSERT(!heap_.HasBeenSetup()); 776 if (!heap_.Setup(create_heap_objects)) { 777 V8::SetFatalError(); 778 return false; 779 } 780 781 bootstrapper_->Initialize(create_heap_objects); 782 builtins_.Setup(create_heap_objects); 783 784 InitializeThreadLocal(); 785 786 // Only preallocate on the first initialization. 787 if (FLAG_preallocate_message_memory && preallocated_message_space_ == NULL) { 788 // Start the thread which will set aside some memory. 789 PreallocatedMemoryThreadStart(); 790 preallocated_message_space_ = 791 new NoAllocationStringAllocator( 792 preallocated_memory_thread_->data(), 793 preallocated_memory_thread_->length()); 794 PreallocatedStorageInit(preallocated_memory_thread_->length() / 4); 795 } 796 797 if (FLAG_preemption) { 798 v8::Locker locker; 799 v8::Locker::StartPreemption(100); 800 } 801 802 #ifdef ENABLE_DEBUGGER_SUPPORT 803 debug_->Setup(create_heap_objects); 804 #endif 805 stub_cache_->Initialize(create_heap_objects); 806 807 // If we are deserializing, read the state into the now-empty heap. 808 if (des != NULL) { 809 des->Deserialize(); 810 stub_cache_->Clear(); 811 } 812 813 // Deserializing may put strange things in the root array's copy of the 814 // stack guard. 815 heap_.SetStackLimits(); 816 817 deoptimizer_data_ = new DeoptimizerData; 818 runtime_profiler_ = new RuntimeProfiler(this); 819 runtime_profiler_->Setup(); 820 821 // If we are deserializing, log non-function code objects and compiled 822 // functions found in the snapshot. 823 if (des != NULL && FLAG_log_code) { 824 HandleScope scope; 825 LOG(this, LogCodeObjects()); 826 LOG(this, LogCompiledFunctions()); 827 } 828 829 state_ = INITIALIZED; 830 return true; 831 } 832 833 834 // Initialized lazily to allow early 835 // v8::V8::SetAddHistogramSampleFunction calls. 836 StatsTable* Isolate::stats_table() { 837 if (stats_table_ == NULL) { 838 stats_table_ = new StatsTable; 839 } 840 return stats_table_; 841 } 842 843 844 void Isolate::Enter() { 845 Isolate* current_isolate = NULL; 846 PerIsolateThreadData* current_data = CurrentPerIsolateThreadData(); 847 if (current_data != NULL) { 848 current_isolate = current_data->isolate_; 849 ASSERT(current_isolate != NULL); 850 if (current_isolate == this) { 851 ASSERT(Current() == this); 852 ASSERT(entry_stack_ != NULL); 853 ASSERT(entry_stack_->previous_thread_data == NULL || 854 entry_stack_->previous_thread_data->thread_id().Equals( 855 ThreadId::Current())); 856 // Same thread re-enters the isolate, no need to re-init anything. 857 entry_stack_->entry_count++; 858 return; 859 } 860 } 861 862 // Threads can have default isolate set into TLS as Current but not yet have 863 // PerIsolateThreadData for it, as it requires more advanced phase of the 864 // initialization. For example, a thread might be the one that system used for 865 // static initializers - in this case the default isolate is set in TLS but 866 // the thread did not yet Enter the isolate. If PerisolateThreadData is not 867 // there, use the isolate set in TLS. 868 if (current_isolate == NULL) { 869 current_isolate = Isolate::UncheckedCurrent(); 870 } 871 872 PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread(); 873 ASSERT(data != NULL); 874 ASSERT(data->isolate_ == this); 875 876 EntryStackItem* item = new EntryStackItem(current_data, 877 current_isolate, 878 entry_stack_); 879 entry_stack_ = item; 880 881 SetIsolateThreadLocals(this, data); 882 883 // In case it's the first time some thread enters the isolate. 884 set_thread_id(data->thread_id()); 885 } 886 887 888 void Isolate::Exit() { 889 ASSERT(entry_stack_ != NULL); 890 ASSERT(entry_stack_->previous_thread_data == NULL || 891 entry_stack_->previous_thread_data->thread_id().Equals( 892 ThreadId::Current())); 893 894 if (--entry_stack_->entry_count > 0) return; 895 896 ASSERT(CurrentPerIsolateThreadData() != NULL); 897 ASSERT(CurrentPerIsolateThreadData()->isolate_ == this); 898 899 // Pop the stack. 900 EntryStackItem* item = entry_stack_; 901 entry_stack_ = item->previous_item; 902 903 PerIsolateThreadData* previous_thread_data = item->previous_thread_data; 904 Isolate* previous_isolate = item->previous_isolate; 905 906 delete item; 907 908 // Reinit the current thread for the isolate it was running before this one. 909 SetIsolateThreadLocals(previous_isolate, previous_thread_data); 910 } 911 912 913 void Isolate::ResetEagerOptimizingData() { 914 compilation_cache_->ResetEagerOptimizingData(); 915 } 916 917 918 #ifdef DEBUG 919 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ 920 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); 921 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) 922 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) 923 #undef ISOLATE_FIELD_OFFSET 924 #endif 925 926 } } // namespace v8::internal 927