| Index: src/isolate.cc
|
| ===================================================================
|
| --- src/isolate.cc (revision 4906)
|
| +++ src/isolate.cc (working copy)
|
| @@ -46,6 +46,117 @@
|
| namespace internal {
|
|
|
|
|
| +// Create a dummy thread that will wait forever on a semaphore. The only
|
| +// purpose for this thread is to have some stack area to save essential data
|
| +// into for use by a stacks only core dump (aka minidump).
|
| +class PreallocatedMemoryThread: public Thread {
|
| + public:
|
| + char* data() {
|
| + if (data_ready_semaphore_ != NULL) {
|
| + // Initial access is guarded until the data has been published.
|
| + data_ready_semaphore_->Wait();
|
| + delete data_ready_semaphore_;
|
| + data_ready_semaphore_ = NULL;
|
| + }
|
| + return data_;
|
| + }
|
| +
|
| + unsigned length() {
|
| + if (data_ready_semaphore_ != NULL) {
|
| + // Initial access is guarded until the data has been published.
|
| + data_ready_semaphore_->Wait();
|
| + delete data_ready_semaphore_;
|
| + data_ready_semaphore_ = NULL;
|
| + }
|
| + return length_;
|
| + }
|
| +
|
| + // Stop the PreallocatedMemoryThread and release its resources.
|
| + void StopThread() {
|
| + keep_running_ = false;
|
| + wait_for_ever_semaphore_->Signal();
|
| +
|
| + // Wait for the thread to terminate.
|
| + Join();
|
| +
|
| + if (data_ready_semaphore_ != NULL) {
|
| + delete data_ready_semaphore_;
|
| + data_ready_semaphore_ = NULL;
|
| + }
|
| +
|
| + delete wait_for_ever_semaphore_;
|
| + wait_for_ever_semaphore_ = NULL;
|
| + }
|
| +
|
| + protected:
|
| + // When the thread starts running it will allocate a fixed number of bytes
|
| + // on the stack and publish the location of this memory for others to use.
|
| + void Run() {
|
| + EmbeddedVector<char, 15 * 1024> local_buffer;
|
| +
|
| + // Initialize the buffer with a known good value.
|
| + OS::StrNCpy(local_buffer, "Trace data was not generated.\n",
|
| + local_buffer.length());
|
| +
|
| + // Publish the local buffer and signal its availability.
|
| + data_ = local_buffer.start();
|
| + length_ = local_buffer.length();
|
| + data_ready_semaphore_->Signal();
|
| +
|
| + while (keep_running_) {
|
| + // This thread will wait here until the end of time.
|
| + wait_for_ever_semaphore_->Wait();
|
| + }
|
| +
|
| + // Make sure we access the buffer after the wait to remove all possibility
|
| + // of it being optimized away.
|
| + OS::StrNCpy(local_buffer, "PreallocatedMemoryThread shutting down.\n",
|
| + local_buffer.length());
|
| + }
|
| +
|
| +
|
| + private:
|
| + PreallocatedMemoryThread()
|
| + : keep_running_(true),
|
| + wait_for_ever_semaphore_(OS::CreateSemaphore(0)),
|
| + data_ready_semaphore_(OS::CreateSemaphore(0)),
|
| + data_(NULL),
|
| + length_(0) {
|
| + }
|
| +
|
| + // Used to make sure that the thread keeps looping even for spurious wakeups.
|
| + bool keep_running_;
|
| +
|
| + // This semaphore is used by the PreallocatedMemoryThread to wait for ever.
|
| + Semaphore* wait_for_ever_semaphore_;
|
| + // Semaphore to signal that the data has been initialized.
|
| + Semaphore* data_ready_semaphore_;
|
| +
|
| + // Location and size of the preallocated memory block.
|
| + char* data_;
|
| + unsigned length_;
|
| +
|
| + friend class Isolate;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(PreallocatedMemoryThread);
|
| +};
|
| +
|
| +
|
| +void Isolate::PreallocatedMemoryThreadStart() {
|
| + if (preallocated_memory_thread_ != NULL) return;
|
| + preallocated_memory_thread_ = new PreallocatedMemoryThread();
|
| + preallocated_memory_thread_->Start();
|
| +}
|
| +
|
| +
|
| +void Isolate::PreallocatedMemoryThreadStop() {
|
| + if (preallocated_memory_thread_ == NULL) return;
|
| + preallocated_memory_thread_->StopThread();
|
| + // Done with the thread entirely.
|
| + delete preallocated_memory_thread_;
|
| + preallocated_memory_thread_ = NULL;
|
| +}
|
| +
|
| #ifdef V8_USE_TLS_FOR_GLOBAL_ISOLATE
|
| Thread::LocalStorageKey Isolate::global_isolate_key_;
|
|
|
| @@ -57,6 +168,7 @@
|
| }
|
| #endif
|
|
|
| +
|
| Isolate* Isolate::global_isolate_ = NULL;
|
| int Isolate::number_of_isolates_ = 0;
|
|
|
| @@ -68,7 +180,6 @@
|
| }
|
| };
|
|
|
| -
|
| static IsolateInitializer isolate_initializer;
|
|
|
|
|
| @@ -109,6 +220,10 @@
|
|
|
| Isolate::Isolate()
|
| : state_(UNINITIALIZED),
|
| + stack_trace_nesting_level_(0),
|
| + incomplete_message_(NULL),
|
| + preallocated_memory_thread_(NULL),
|
| + preallocated_message_space_(NULL),
|
| bootstrapper_(NULL),
|
| compilation_cache_(new CompilationCache()),
|
| cpu_features_(NULL),
|
| @@ -120,6 +235,9 @@
|
| descriptor_lookup_cache_(new DescriptorLookupCache()),
|
| handle_scope_implementer_(NULL),
|
| scanner_character_classes_(new ScannerCharacterClasses()) {
|
| + memset(isolate_addresses_, 0,
|
| + sizeof(isolate_addresses_[0]) * (k_isolate_address_count + 1));
|
| +
|
| heap_.isolate_ = this;
|
| stack_guard_.isolate_ = this;
|
|
|
| @@ -137,7 +255,37 @@
|
| }
|
|
|
|
|
| +void Isolate::TearDownAndRecreateGlobalIsolate() {
|
| + if (global_isolate_ != NULL) {
|
| + delete global_isolate_;
|
| + global_isolate_ = NULL;
|
| + }
|
| +
|
| + global_isolate_ = new Isolate();
|
| + global_isolate_->PreInit();
|
| +}
|
| +
|
| +
|
| Isolate::~Isolate() {
|
| + if (state_ == INITIALIZED) {
|
| + OProfileAgent::TearDown();
|
| + if (FLAG_preemption) {
|
| + v8::Locker locker;
|
| + v8::Locker::StopPreemption();
|
| + }
|
| + Builtins::TearDown();
|
| + bootstrapper_->TearDown();
|
| +
|
| + // Remove the external reference to the preallocated stack memory.
|
| + delete preallocated_message_space_;
|
| + preallocated_message_space_ = NULL;
|
| + PreallocatedMemoryThreadStop();
|
| +
|
| + HeapProfiler::TearDown();
|
| + CpuProfiler::TearDown();
|
| + heap_.TearDown();
|
| + Logger::TearDown();
|
| + }
|
| delete scanner_character_classes_;
|
| scanner_character_classes_ = NULL;
|
|
|
| @@ -178,6 +326,13 @@
|
| #ifdef DEBUG
|
| DisallowAllocationFailure disallow_allocation_failure;
|
| #endif
|
| +
|
| +#define C(name) isolate_addresses_[Isolate::k_##name] = \
|
| + reinterpret_cast<Address>(name());
|
| + ISOLATE_ADDRESS_LIST(C)
|
| + ISOLATE_ADDRESS_LIST_PROF(C)
|
| +#undef C
|
| +
|
| bootstrapper_ = new Bootstrapper();
|
| cpu_features_ = new CpuFeatures();
|
| handle_scope_implementer_ = new HandleScopeImplementer();
|
| @@ -187,8 +342,17 @@
|
| }
|
|
|
|
|
| +void Isolate::InitializeThreadLocal() {
|
| + thread_local_top_.Initialize();
|
| + clear_pending_exception();
|
| + clear_pending_message();
|
| + clear_scheduled_exception();
|
| +}
|
| +
|
| +
|
| bool Isolate::Init(Deserializer* des) {
|
| ASSERT(global_isolate_ == this);
|
| + ASSERT(state_ != INITIALIZED);
|
|
|
| bool create_heap_objects = des == NULL;
|
|
|
| @@ -230,8 +394,20 @@
|
|
|
| bootstrapper_->Initialize(create_heap_objects);
|
| Builtins::Setup(create_heap_objects);
|
| - Top::Initialize();
|
|
|
| + InitializeThreadLocal();
|
| +
|
| + // Only preallocate on the first initialization.
|
| + if (FLAG_preallocate_message_memory && preallocated_message_space_ == NULL) {
|
| + // Start the thread which will set aside some memory.
|
| + PreallocatedMemoryThreadStart();
|
| + preallocated_message_space_ =
|
| + new NoAllocationStringAllocator(
|
| + preallocated_memory_thread_->data(),
|
| + preallocated_memory_thread_->length());
|
| + PreallocatedStorage::Init(preallocated_memory_thread_->length() / 4);
|
| + }
|
| +
|
| if (FLAG_preemption) {
|
| v8::Locker locker;
|
| v8::Locker::StartPreemption(100);
|
|
|