diff options
Diffstat (limited to 'deps/v8/src/isolate.cc')
-rw-r--r-- | deps/v8/src/isolate.cc | 387 |
1 files changed, 95 insertions, 292 deletions
diff --git a/deps/v8/src/isolate.cc b/deps/v8/src/isolate.cc index 71cd301581..ca324603f7 100644 --- a/deps/v8/src/isolate.cc +++ b/deps/v8/src/isolate.cc @@ -29,7 +29,6 @@ #include "v8.h" -#include "allocation-inl.h" #include "ast.h" #include "bootstrapper.h" #include "codegen.h" @@ -131,205 +130,6 @@ v8::TryCatch* ThreadLocalTop::TryCatchHandler() { } -int SystemThreadManager::NumberOfParallelSystemThreads( - ParallelSystemComponent type) { - int number_of_threads = Min(CPU::NumberOfProcessorsOnline(), kMaxThreads); - ASSERT(number_of_threads > 0); - if (number_of_threads == 1) { - return 0; - } - if (type == PARALLEL_SWEEPING) { - return number_of_threads; - } else if (type == CONCURRENT_SWEEPING) { - return number_of_threads - 1; - } - return 1; -} - - -// 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() - : Thread("v8:PreallocMem"), - keep_running_(true), - wait_for_ever_semaphore_(new Semaphore(0)), - data_ready_semaphore_(new Semaphore(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; -} - - -void Isolate::PreallocatedStorageInit(size_t size) { - ASSERT(free_list_.next_ == &free_list_); - ASSERT(free_list_.previous_ == &free_list_); - PreallocatedStorage* free_chunk = - reinterpret_cast<PreallocatedStorage*>(new char[size]); - free_list_.next_ = free_list_.previous_ = free_chunk; - free_chunk->next_ = free_chunk->previous_ = &free_list_; - free_chunk->size_ = size - sizeof(PreallocatedStorage); - preallocated_storage_preallocated_ = true; -} - - -void* Isolate::PreallocatedStorageNew(size_t size) { - if (!preallocated_storage_preallocated_) { - return FreeStoreAllocationPolicy().New(size); - } - ASSERT(free_list_.next_ != &free_list_); - ASSERT(free_list_.previous_ != &free_list_); - - size = (size + kPointerSize - 1) & ~(kPointerSize - 1); - // Search for exact fit. - for (PreallocatedStorage* storage = free_list_.next_; - storage != &free_list_; - storage = storage->next_) { - if (storage->size_ == size) { - storage->Unlink(); - storage->LinkTo(&in_use_list_); - return reinterpret_cast<void*>(storage + 1); - } - } - // Search for first fit. - for (PreallocatedStorage* storage = free_list_.next_; - storage != &free_list_; - storage = storage->next_) { - if (storage->size_ >= size + sizeof(PreallocatedStorage)) { - storage->Unlink(); - storage->LinkTo(&in_use_list_); - PreallocatedStorage* left_over = - reinterpret_cast<PreallocatedStorage*>( - reinterpret_cast<char*>(storage + 1) + size); - left_over->size_ = storage->size_ - size - sizeof(PreallocatedStorage); - ASSERT(size + left_over->size_ + sizeof(PreallocatedStorage) == - storage->size_); - storage->size_ = size; - left_over->LinkTo(&free_list_); - return reinterpret_cast<void*>(storage + 1); - } - } - // Allocation failure. - ASSERT(false); - return NULL; -} - - -// We don't attempt to coalesce. -void Isolate::PreallocatedStorageDelete(void* p) { - if (p == NULL) { - return; - } - if (!preallocated_storage_preallocated_) { - FreeStoreAllocationPolicy::Delete(p); - return; - } - PreallocatedStorage* storage = reinterpret_cast<PreallocatedStorage*>(p) - 1; - ASSERT(storage->next_->previous_ == storage); - ASSERT(storage->previous_->next_ == storage); - storage->Unlink(); - storage->LinkTo(&free_list_); -} - Isolate* Isolate::default_isolate_ = NULL; Thread::LocalStorageKey Isolate::isolate_key_; Thread::LocalStorageKey Isolate::thread_id_key_; @@ -853,24 +653,12 @@ Handle<JSArray> Isolate::CaptureCurrentStackTrace( } -void Isolate::PrintStack() { - PrintStack(stdout); -} - - void Isolate::PrintStack(FILE* out) { if (stack_trace_nesting_level_ == 0) { stack_trace_nesting_level_++; - - StringAllocator* allocator; - if (preallocated_message_space_ == NULL) { - allocator = new HeapStringAllocator(); - } else { - allocator = preallocated_message_space_; - } - StringStream::ClearMentionedObjectCache(this); - StringStream accumulator(allocator); + HeapStringAllocator allocator; + StringStream accumulator(&allocator); incomplete_message_ = &accumulator; PrintStack(&accumulator); accumulator.OutputToFile(out); @@ -878,10 +666,6 @@ void Isolate::PrintStack(FILE* out) { accumulator.Log(this); incomplete_message_ = NULL; stack_trace_nesting_level_ = 0; - if (preallocated_message_space_ == NULL) { - // Remove the HeapStringAllocator created above. - delete allocator; - } } else if (stack_trace_nesting_level_ == 1) { stack_trace_nesting_level_++; OS::PrintError( @@ -994,7 +778,7 @@ static MayAccessDecision MayAccessPreCheck(Isolate* isolate, bool Isolate::MayNamedAccess(JSObject* receiver, Object* key, v8::AccessType type) { - ASSERT(receiver->IsAccessCheckNeeded()); + ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); // The callers of this method are not expecting a GC. DisallowHeapAllocation no_gc; @@ -1045,7 +829,7 @@ bool Isolate::MayNamedAccess(JSObject* receiver, Object* key, bool Isolate::MayIndexedAccess(JSObject* receiver, uint32_t index, v8::AccessType type) { - ASSERT(receiver->IsAccessCheckNeeded()); + ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); // Check for compatibility between the security tokens in the // current lexical context and the accessed object. ASSERT(context()); @@ -1162,6 +946,7 @@ Failure* Isolate::ReThrow(MaybeObject* exception) { Failure* Isolate::ThrowIllegalOperation() { + if (FLAG_stack_trace_on_illegal) PrintStack(stdout); return Throw(heap_.illegal_access_string()); } @@ -1338,8 +1123,6 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) { // while the bootstrapper is active since the infrastructure may not have // been properly initialized. if (!bootstrapping) { - Handle<String> stack_trace; - if (FLAG_trace_exception) stack_trace = StackTraceString(); Handle<JSArray> stack_trace_object; if (capture_stack_trace_for_uncaught_exceptions_) { if (IsErrorObject(exception_handle)) { @@ -1379,7 +1162,6 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) { "uncaught_exception", location, HandleVector<Object>(&exception_arg, 1), - stack_trace, stack_trace_object); thread_local_top()->pending_message_obj_ = *message_obj; if (location != NULL) { @@ -1398,7 +1180,7 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) { fatal_exception_depth++; PrintF(stderr, "%s\n\nFROM\n", - *MessageHandler::GetLocalizedMessage(this, message_obj)); + MessageHandler::GetLocalizedMessage(this, message_obj).get()); PrintCurrentStackTrace(stderr); OS::Abort(); } @@ -1413,13 +1195,13 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) { if (exception->IsString() && location->script()->name()->IsString()) { OS::PrintError( "Extension or internal compilation error: %s in %s at line %d.\n", - *String::cast(exception)->ToCString(), - *String::cast(location->script()->name())->ToCString(), + String::cast(exception)->ToCString().get(), + String::cast(location->script()->name())->ToCString().get(), line_number + 1); } else if (location->script()->name()->IsString()) { OS::PrintError( "Extension or internal compilation error in %s at line %d.\n", - *String::cast(location->script()->name())->ToCString(), + String::cast(location->script()->name())->ToCString().get(), line_number + 1); } else { OS::PrintError("Extension or internal compilation error.\n"); @@ -1539,11 +1321,6 @@ MessageLocation Isolate::GetMessageLocation() { } -void Isolate::TraceException(bool flag) { - FLAG_trace_exception = flag; // TODO(isolates): This is an unfortunate use. -} - - bool Isolate::OptionalRescheduleException(bool is_bottom_call) { ASSERT(has_pending_exception()); PropagatePendingExceptionToExternalTryCatch(); @@ -1735,13 +1512,11 @@ void Isolate::ThreadDataTable::RemoveAllThreads(Isolate* isolate) { Isolate::Isolate() - : state_(UNINITIALIZED), - embedder_data_(NULL), + : embedder_data_(), + state_(UNINITIALIZED), entry_stack_(NULL), stack_trace_nesting_level_(0), incomplete_message_(NULL), - preallocated_memory_thread_(NULL), - preallocated_message_space_(NULL), bootstrapper_(NULL), runtime_profiler_(NULL), compilation_cache_(NULL), @@ -1752,10 +1527,10 @@ Isolate::Isolate() stats_table_(NULL), stub_cache_(NULL), deoptimizer_data_(NULL), + materialized_object_store_(NULL), capture_stack_trace_for_uncaught_exceptions_(false), stack_trace_for_uncaught_exceptions_frame_limit_(0), stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview), - transcendental_cache_(NULL), memory_allocator_(NULL), keyed_lookup_cache_(NULL), context_slot_cache_(NULL), @@ -1763,14 +1538,10 @@ Isolate::Isolate() handle_scope_implementer_(NULL), unicode_cache_(NULL), runtime_zone_(this), - in_use_list_(0), - free_list_(0), - preallocated_storage_preallocated_(false), inner_pointer_to_code_cache_(NULL), write_iterator_(NULL), global_handles_(NULL), eternal_handles_(NULL), - context_switcher_(NULL), thread_manager_(NULL), fp_stubs_generated_(false), has_installed_extensions_(false), @@ -1778,6 +1549,7 @@ Isolate::Isolate() regexp_stack_(NULL), date_cache_(NULL), code_stub_interface_descriptors_(NULL), + call_descriptors_(NULL), // TODO(bmeurer) Initialized lazily because it depends on flags; can // be fixed once the default isolate cleanup is done. random_number_generator_(NULL), @@ -1790,7 +1562,10 @@ Isolate::Isolate() deferred_handles_head_(NULL), optimizing_compiler_thread_(NULL), sweeper_thread_(NULL), - stress_deopt_count_(0) { + num_sweeper_threads_(0), + max_available_threads_(0), + stress_deopt_count_(0), + next_optimization_id_(0) { id_ = NoBarrier_AtomicIncrement(&isolate_counter_, 1); TRACE_ISOLATE(constructor); @@ -1806,6 +1581,7 @@ Isolate::Isolate() thread_manager_->isolate_ = this; #if V8_TARGET_ARCH_ARM && !defined(__arm__) || \ + V8_TARGET_ARCH_A64 && !defined(__aarch64__) || \ V8_TARGET_ARCH_MIPS && !defined(__mips__) simulator_initialized_ = false; simulator_i_cache_ = NULL; @@ -1882,17 +1658,23 @@ void Isolate::Deinit() { debugger()->UnloadDebugger(); #endif - if (FLAG_concurrent_recompilation) { + if (concurrent_recompilation_enabled()) { optimizing_compiler_thread_->Stop(); delete optimizing_compiler_thread_; + optimizing_compiler_thread_ = NULL; } - if (FLAG_sweeper_threads > 0) { - for (int i = 0; i < FLAG_sweeper_threads; i++) { - sweeper_thread_[i]->Stop(); - delete sweeper_thread_[i]; - } - delete[] sweeper_thread_; + for (int i = 0; i < num_sweeper_threads_; i++) { + sweeper_thread_[i]->Stop(); + delete sweeper_thread_[i]; + sweeper_thread_[i] = NULL; + } + delete[] sweeper_thread_; + sweeper_thread_ = NULL; + + if (FLAG_job_based_sweeping && + heap_.mark_compact_collector()->IsConcurrentSweepingInProgress()) { + heap_.mark_compact_collector()->WaitUntilSweepingCompleted(); } if (FLAG_hydrogen_stats) GetHStatistics()->Print(); @@ -1907,20 +1689,10 @@ void Isolate::Deinit() { delete deoptimizer_data_; deoptimizer_data_ = NULL; - if (FLAG_preemption) { - v8::Locker locker(reinterpret_cast<v8::Isolate*>(this)); - v8::Locker::StopPreemption(reinterpret_cast<v8::Isolate*>(this)); - } builtins_.TearDown(); bootstrapper_->TearDown(); - // Remove the external reference to the preallocated stack memory. - delete preallocated_message_space_; - preallocated_message_space_ = NULL; - PreallocatedMemoryThreadStop(); - if (runtime_profiler_ != NULL) { - runtime_profiler_->TearDown(); delete runtime_profiler_; runtime_profiler_ = NULL; } @@ -1992,6 +1764,9 @@ Isolate::~Isolate() { delete[] code_stub_interface_descriptors_; code_stub_interface_descriptors_ = NULL; + delete[] call_descriptors_; + call_descriptors_ = NULL; + delete regexp_stack_; regexp_stack_ = NULL; @@ -2002,13 +1777,14 @@ Isolate::~Isolate() { delete keyed_lookup_cache_; keyed_lookup_cache_ = NULL; - delete transcendental_cache_; - transcendental_cache_ = NULL; delete stub_cache_; stub_cache_ = NULL; delete stats_table_; stats_table_ = NULL; + delete materialized_object_store_; + materialized_object_store_ = NULL; + delete logger_; logger_ = NULL; @@ -2027,8 +1803,6 @@ Isolate::~Isolate() { delete write_iterator_; write_iterator_ = NULL; - delete context_switcher_; - context_switcher_ = NULL; delete thread_manager_; thread_manager_ = NULL; @@ -2170,7 +1944,6 @@ bool Isolate::Init(Deserializer* des) { string_tracker_ = new StringTracker(); string_tracker_->isolate_ = this; compilation_cache_ = new CompilationCache(this); - transcendental_cache_ = new TranscendentalCache(this); keyed_lookup_cache_ = new KeyedLookupCache(); context_slot_cache_ = new ContextSlotCache(); descriptor_lookup_cache_ = new DescriptorLookupCache(); @@ -2182,11 +1955,14 @@ bool Isolate::Init(Deserializer* des) { bootstrapper_ = new Bootstrapper(this); handle_scope_implementer_ = new HandleScopeImplementer(this); stub_cache_ = new StubCache(this); + materialized_object_store_ = new MaterializedObjectStore(this); regexp_stack_ = new RegExpStack(); regexp_stack_->isolate_ = this; date_cache_ = new DateCache(); code_stub_interface_descriptors_ = new CodeStubInterfaceDescriptor[CodeStub::NUMBER_OF_IDS]; + call_descriptors_ = + new CallInterfaceDescriptor[NUMBER_OF_CALL_DESCRIPTORS]; cpu_profiler_ = new CpuProfiler(this); heap_profiler_ = new HeapProfiler(heap()); @@ -2195,7 +1971,7 @@ bool Isolate::Init(Deserializer* des) { // Initialize other runtime facilities #if defined(USE_SIMULATOR) -#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS +#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_A64 || V8_TARGET_ARCH_MIPS Simulator::Initialize(this); #endif #endif @@ -2217,11 +1993,6 @@ bool Isolate::Init(Deserializer* des) { deoptimizer_data_ = new DeoptimizerData(memory_allocator_); - if (FLAG_concurrent_recompilation) { - optimizing_compiler_thread_ = new OptimizingCompilerThread(this); - optimizing_compiler_thread_->Start(); - } - const bool create_heap_objects = (des == NULL); if (create_heap_objects && !heap_.CreateHeapObjects()) { V8::FatalProcessOutOfMemory("heap object creation"); @@ -2238,20 +2009,32 @@ bool Isolate::Init(Deserializer* des) { bootstrapper_->Initialize(create_heap_objects); builtins_.SetUp(this, create_heap_objects); - // 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()); - PreallocatedStorageInit(preallocated_memory_thread_->length() / 4); + // Set default value if not yet set. + // TODO(yangguo): move this to ResourceConstraints::ConfigureDefaults + // once ResourceConstraints becomes an argument to the Isolate constructor. + if (max_available_threads_ < 1) { + // Choose the default between 1 and 4. + max_available_threads_ = Max(Min(CPU::NumberOfProcessorsOnline(), 4), 1); + } + + if (!FLAG_job_based_sweeping) { + num_sweeper_threads_ = + SweeperThread::NumberOfThreads(max_available_threads_); } - if (FLAG_preemption) { - v8::Locker locker(reinterpret_cast<v8::Isolate*>(this)); - v8::Locker::StartPreemption(reinterpret_cast<v8::Isolate*>(this), 100); + if (FLAG_trace_hydrogen || FLAG_trace_hydrogen_stubs) { + PrintF("Concurrent recompilation has been disabled for tracing.\n"); + } else if (OptimizingCompilerThread::Enabled(max_available_threads_)) { + optimizing_compiler_thread_ = new OptimizingCompilerThread(this); + optimizing_compiler_thread_->Start(); + } + + if (num_sweeper_threads_ > 0) { + sweeper_thread_ = new SweeperThread*[num_sweeper_threads_]; + for (int i = 0; i < num_sweeper_threads_; i++) { + sweeper_thread_[i] = new SweeperThread(this); + sweeper_thread_[i]->Start(); + } } #ifdef ENABLE_DEBUGGER_SUPPORT @@ -2277,17 +2060,26 @@ bool Isolate::Init(Deserializer* des) { if (!create_heap_objects) Assembler::QuietNaN(heap_.nan_value()); runtime_profiler_ = new RuntimeProfiler(this); - runtime_profiler_->SetUp(); // If we are deserializing, log non-function code objects and compiled // functions found in the snapshot. if (!create_heap_objects && - (FLAG_log_code || FLAG_ll_prof || logger_->is_logging_code_events())) { + (FLAG_log_code || + FLAG_ll_prof || + FLAG_perf_jit_prof || + FLAG_perf_basic_prof || + logger_->is_logging_code_events())) { HandleScope scope(this); LOG(this, LogCodeObjects()); LOG(this, LogCompiledFunctions()); } + // If we are profiling with the Linux perf tool, we need to disable + // code relocation. + if (FLAG_perf_jit_prof || FLAG_perf_basic_prof) { + FLAG_compact_code_space = false; + } + CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, embedder_data_)), Internals::kIsolateEmbedderDataOffset); CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.roots_)), @@ -2321,22 +2113,20 @@ bool Isolate::Init(Deserializer* des) { DONT_TRACK_ALLOCATION_SITE, 0); stub.InitializeInterfaceDescriptor( this, code_stub_interface_descriptor(CodeStub::FastCloneShallowArray)); - BinaryOpStub::InitializeForIsolate(this); + BinaryOpICStub::InstallDescriptors(this); + BinaryOpWithAllocationSiteStub::InstallDescriptors(this); CompareNilICStub::InitializeForIsolate(this); ToBooleanStub::InitializeForIsolate(this); ArrayConstructorStubBase::InstallDescriptors(this); InternalArrayConstructorStubBase::InstallDescriptors(this); FastNewClosureStub::InstallDescriptors(this); + FastNewContextStub::InstallDescriptors(this); NumberToStringStub::InstallDescriptors(this); + StringAddStub::InstallDescriptors(this); + RegExpConstructResultStub::InstallDescriptors(this); } - if (FLAG_sweeper_threads > 0) { - sweeper_thread_ = new SweeperThread*[FLAG_sweeper_threads]; - for (int i = 0; i < FLAG_sweeper_threads; i++) { - sweeper_thread_[i] = new SweeperThread(this); - sweeper_thread_[i]->Start(); - } - } + CallDescriptors::InitializeForIsolate(this); initialized_from_snapshot_ = (des != NULL); @@ -2465,6 +2255,12 @@ HTracer* Isolate::GetHTracer() { } +CodeTracer* Isolate::GetCodeTracer() { + if (code_tracer() == NULL) set_code_tracer(new CodeTracer(id())); + return code_tracer(); +} + + Map* Isolate::get_initial_js_array_map(ElementsKind kind) { Context* native_context = context()->native_context(); Object* maybe_map_array = native_context->js_array_maps(); @@ -2509,6 +2305,13 @@ CodeStubInterfaceDescriptor* } +CallInterfaceDescriptor* + Isolate::call_descriptor(CallDescriptorKey index) { + ASSERT(0 <= index && index < NUMBER_OF_CALL_DESCRIPTORS); + return &call_descriptors_[index]; +} + + Object* Isolate::FindCodeObject(Address a) { return inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(a); } |