Make number of available threads isolate-dependent and expose it to ResourceConstraints.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 19 Nov 2013 11:52:47 +0000 (11:52 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 19 Nov 2013 11:52:47 +0000 (11:52 +0000)
R=svenpanne@chromium.org
BUG=v8:2991
LOG=Y

Review URL: https://codereview.chromium.org/68203029

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17866 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

21 files changed:
include/v8.h
src/api.cc
src/compiler.h
src/execution.cc
src/heap-profiler.cc
src/heap.cc
src/heap.h
src/hydrogen.cc
src/isolate.cc
src/isolate.h
src/mark-compact.cc
src/objects.cc
src/optimizing-compiler-thread.cc
src/optimizing-compiler-thread.h
src/runtime-profiler.cc
src/runtime.cc
src/sweeper-thread.cc
src/sweeper-thread.h
src/v8.cc
test/cctest/test-deoptimization.cc
test/cctest/test-heap.cc

index f0b627e..1955058 100644 (file)
@@ -3817,17 +3817,23 @@ class V8_EXPORT ResourceConstraints {
   void set_max_young_space_size(int value) { max_young_space_size_ = value; }
   int max_old_space_size() const { return max_old_space_size_; }
   void set_max_old_space_size(int value) { max_old_space_size_ = value; }
-  int max_executable_size() { return max_executable_size_; }
+  int max_executable_size() const { return max_executable_size_; }
   void set_max_executable_size(int value) { max_executable_size_ = value; }
   uint32_t* stack_limit() const { return stack_limit_; }
   // Sets an address beyond which the VM's stack may not grow.
   void set_stack_limit(uint32_t* value) { stack_limit_ = value; }
+  int max_available_threads() const { return max_available_threads_; }
+  // Set the number of threads available to V8, assuming at least 1.
+  void set_max_available_threads(int value) {
+    max_available_threads_ = value;
+  }
 
  private:
   int max_young_space_size_;
   int max_old_space_size_;
   int max_executable_size_;
   uint32_t* stack_limit_;
+  int max_available_threads_;
 };
 
 
index 736f0b0..7966e2c 100644 (file)
@@ -563,7 +563,8 @@ ResourceConstraints::ResourceConstraints()
   : max_young_space_size_(0),
     max_old_space_size_(0),
     max_executable_size_(0),
-    stack_limit_(NULL) { }
+    stack_limit_(NULL),
+    max_available_threads_(0) { }
 
 
 void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory) {
@@ -599,6 +600,8 @@ void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory) {
     set_max_old_space_size(700 * lump_of_memory);
     set_max_executable_size(256 * lump_of_memory);
   }
+
+  set_max_available_threads(0);
 }
 
 
@@ -627,6 +630,8 @@ bool SetResourceConstraints(Isolate* v8_isolate,
     uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
     isolate->stack_guard()->SetStackLimit(limit);
   }
+
+  isolate->set_max_available_threads(constraints->max_available_threads());
   return true;
 }
 
index 5ebcfd9..080907e 100644 (file)
@@ -302,12 +302,12 @@ class CompilationInfo {
   }
 
   void AbortDueToDependencyChange() {
-    ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
+    ASSERT(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
     abort_due_to_dependency_ = true;
   }
 
   bool HasAbortedDueToDependencyChange() {
-    ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
+    ASSERT(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
     return abort_due_to_dependency_;
   }
 
index 979641a..8febbbf 100644 (file)
@@ -951,7 +951,7 @@ MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) {
     Deoptimizer::DeoptimizeAll(isolate);
   }
   if (stack_guard->IsInstallCodeRequest()) {
-    ASSERT(FLAG_concurrent_recompilation);
+    ASSERT(isolate->concurrent_recompilation_enabled());
     stack_guard->Continue(INSTALL_CODE);
     isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
   }
index 46320b6..b45e97b 100644 (file)
@@ -177,7 +177,7 @@ void HeapProfiler::DropCompiledCode() {
   Isolate* isolate = heap()->isolate();
   HandleScope scope(isolate);
 
-  if (FLAG_concurrent_recompilation) {
+  if (isolate->concurrent_recompilation_enabled()) {
     isolate->optimizing_compiler_thread()->Flush();
   }
 
index 90bb2cd..b75f751 100644 (file)
@@ -465,7 +465,7 @@ void Heap::GarbageCollectionPrologue() {
 
   store_buffer()->GCPrologue();
 
-  if (FLAG_concurrent_osr) {
+  if (isolate()->concurrent_osr_enabled()) {
     isolate()->optimizing_compiler_thread()->AgeBufferedOsrJobs();
   }
 }
@@ -662,7 +662,7 @@ void Heap::CollectAllAvailableGarbage(const char* gc_reason) {
   // Note: as weak callbacks can execute arbitrary code, we cannot
   // hope that eventually there will be no weak callbacks invocations.
   // Therefore stop recollecting after several attempts.
-  if (FLAG_concurrent_recompilation) {
+  if (isolate()->concurrent_recompilation_enabled()) {
     // The optimizing compiler may be unnecessarily holding on to memory.
     DisallowHeapAllocation no_recursive_gc;
     isolate()->optimizing_compiler_thread()->Flush();
@@ -763,7 +763,7 @@ bool Heap::CollectGarbage(AllocationSpace space,
 
 
 int Heap::NotifyContextDisposed() {
-  if (FLAG_concurrent_recompilation) {
+  if (isolate()->concurrent_recompilation_enabled()) {
     // Flush the queued recompilation tasks.
     isolate()->optimizing_compiler_thread()->Flush();
   }
@@ -6583,6 +6583,14 @@ intptr_t Heap::PromotedSpaceSizeOfObjects() {
 }
 
 
+bool Heap::AdvanceSweepers(int step_size) {
+  ASSERT(isolate()->num_sweeper_threads() == 0);
+  bool sweeping_complete = old_data_space()->AdvanceSweeper(step_size);
+  sweeping_complete &= old_pointer_space()->AdvanceSweeper(step_size);
+  return sweeping_complete;
+}
+
+
 intptr_t Heap::PromotedExternalMemorySize() {
   if (amount_of_external_allocated_memory_
       <= amount_of_external_allocated_memory_at_last_global_gc_) return 0;
@@ -6729,9 +6737,6 @@ bool Heap::SetUp() {
   store_buffer()->SetUp();
 
   if (FLAG_concurrent_recompilation) relocation_mutex_ = new Mutex;
-#ifdef DEBUG
-  relocation_mutex_locked_by_optimizer_thread_ = false;
-#endif  // DEBUG
 
   return true;
 }
@@ -6876,6 +6881,7 @@ void Heap::TearDown() {
   isolate_->memory_allocator()->TearDown();
 
   delete relocation_mutex_;
+  relocation_mutex_ = NULL;
 }
 
 
@@ -7955,15 +7961,4 @@ void Heap::CheckpointObjectStats() {
   ClearObjectStats();
 }
 
-
-Heap::RelocationLock::RelocationLock(Heap* heap) : heap_(heap) {
-  if (FLAG_concurrent_recompilation) {
-    heap_->relocation_mutex_->Lock();
-#ifdef DEBUG
-    heap_->relocation_mutex_locked_by_optimizer_thread_ =
-        heap_->isolate()->optimizing_compiler_thread()->IsOptimizerThread();
-#endif  // DEBUG
-  }
-}
-
 } }  // namespace v8::internal
index 0570557..752a1ed 100644 (file)
@@ -1699,12 +1699,7 @@ class Heap {
            old_pointer_space()->IsLazySweepingComplete();
   }
 
-  bool AdvanceSweepers(int step_size) {
-    ASSERT(!FLAG_parallel_sweeping && !FLAG_concurrent_sweeping);
-    bool sweeping_complete = old_data_space()->AdvanceSweeper(step_size);
-    sweeping_complete &= old_pointer_space()->AdvanceSweeper(step_size);
-    return sweeping_complete;
-  }
+  bool AdvanceSweepers(int step_size);
 
   bool EnsureSweepersProgressed(int step_size) {
     bool sweeping_complete = old_data_space()->EnsureSweeperProgress(step_size);
@@ -1833,23 +1828,19 @@ class Heap {
   // only when FLAG_concurrent_recompilation is true.
   class RelocationLock {
    public:
-    explicit RelocationLock(Heap* heap);
+    explicit RelocationLock(Heap* heap) : heap_(heap) {
+      if (FLAG_concurrent_recompilation) {
+        heap_->relocation_mutex_->Lock();
+      }
+    }
+
 
     ~RelocationLock() {
       if (FLAG_concurrent_recompilation) {
-#ifdef DEBUG
-        heap_->relocation_mutex_locked_by_optimizer_thread_ = false;
-#endif  // DEBUG
         heap_->relocation_mutex_->Unlock();
       }
     }
 
-#ifdef DEBUG
-    static bool IsLockedByOptimizerThread(Heap* heap) {
-      return heap->relocation_mutex_locked_by_optimizer_thread_;
-    }
-#endif  // DEBUG
-
    private:
     Heap* heap_;
   };
index b5fd2df..61211ec 100644 (file)
@@ -2906,7 +2906,7 @@ HBasicBlock* HGraph::CreateBasicBlock() {
 
 void HGraph::FinalizeUniqueness() {
   DisallowHeapAllocation no_gc;
-  ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
+  ASSERT(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
   for (int i = 0; i < blocks()->length(); ++i) {
     for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
       it.Current()->FinalizeUniqueness();
@@ -10331,7 +10331,7 @@ void HTracer::TraceCompilation(CompilationInfo* info) {
 
 
 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
-  ASSERT(!FLAG_concurrent_recompilation);
+  ASSERT(!chunk->isolate()->concurrent_recompilation_enabled());
   AllowHandleDereference allow_deref;
   AllowDeferredHandleDereference allow_deferred_deref;
   Trace(name, chunk->graph(), chunk);
@@ -10339,7 +10339,7 @@ void HTracer::TraceLithium(const char* name, LChunk* chunk) {
 
 
 void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
-  ASSERT(!FLAG_concurrent_recompilation);
+  ASSERT(!graph->isolate()->concurrent_recompilation_enabled());
   AllowHandleDereference allow_deref;
   AllowDeferredHandleDereference allow_deferred_deref;
   Trace(name, graph, NULL);
index 07bb2ae..700ca87 100644 (file)
@@ -131,22 +131,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).
@@ -1790,6 +1774,8 @@ Isolate::Isolate()
       deferred_handles_head_(NULL),
       optimizing_compiler_thread_(NULL),
       sweeper_thread_(NULL),
+      num_sweeper_threads_(0),
+      max_available_threads_(0),
       stress_deopt_count_(0) {
   id_ = NoBarrier_AtomicIncrement(&isolate_counter_, 1);
   TRACE_ISOLATE(constructor);
@@ -1882,18 +1868,20 @@ 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_hydrogen_stats) GetHStatistics()->Print();
 
@@ -2217,11 +2205,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");
@@ -2240,6 +2223,31 @@ bool Isolate::Init(Deserializer* des) {
 
   if (create_heap_objects) heap_.CreateStubsRequiringBuiltins();
 
+  // 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);
+  }
+
+  num_sweeper_threads_ = SweeperThread::NumberOfThreads(max_available_threads_);
+
+  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();
+    }
+  }
+
   // Only preallocate on the first initialization.
   if (FLAG_preallocate_message_memory && preallocated_message_space_ == NULL) {
     // Start the thread which will set aside some memory.
@@ -2334,14 +2342,6 @@ bool Isolate::Init(Deserializer* des) {
     NewStringAddStub::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();
-    }
-  }
-
   initialized_from_snapshot_ = (des != NULL);
 
   return true;
index c13714f..7544a9c 100644 (file)
@@ -301,20 +301,6 @@ class ThreadLocalTop BASE_EMBEDDED {
 };
 
 
-class SystemThreadManager {
- public:
-  enum ParallelSystemComponent {
-    PARALLEL_SWEEPING,
-    CONCURRENT_SWEEPING,
-    CONCURRENT_RECOMPILATION
-  };
-
-  static int NumberOfParallelSystemThreads(ParallelSystemComponent type);
-
-  static const int kMaxThreads = 4;
-};
-
-
 #ifdef ENABLE_DEBUGGER_SUPPORT
 
 #define ISOLATE_DEBUGGER_INIT_LIST(V)                                          \
@@ -1111,19 +1097,41 @@ class Isolate {
   bool IsDeferredHandle(Object** location);
 #endif  // DEBUG
 
+  void set_max_available_threads(int value) {
+    max_available_threads_ = value;
+  }
+
+  bool concurrent_recompilation_enabled() {
+    // Thread is only available with flag enabled.
+    ASSERT(optimizing_compiler_thread_ == NULL ||
+           FLAG_concurrent_recompilation);
+    return optimizing_compiler_thread_ != NULL;
+  }
+
+  bool concurrent_osr_enabled() {
+    // Thread is only available with flag enabled.
+    ASSERT(optimizing_compiler_thread_ == NULL ||
+           FLAG_concurrent_recompilation);
+    return optimizing_compiler_thread_ != NULL && FLAG_concurrent_osr;
+  }
+
   OptimizingCompilerThread* optimizing_compiler_thread() {
     return optimizing_compiler_thread_;
   }
 
-  // PreInits and returns a default isolate. Needed when a new thread tries
-  // to create a Locker for the first time (the lock itself is in the isolate).
-  // TODO(svenpanne) This method is on death row...
-  static v8::Isolate* GetDefaultIsolateForLocking();
+  bool num_sweeper_threads() {
+    return num_sweeper_threads_;
+  }
 
   SweeperThread** sweeper_threads() {
     return sweeper_thread_;
   }
 
+  // PreInits and returns a default isolate. Needed when a new thread tries
+  // to create a Locker for the first time (the lock itself is in the isolate).
+  // TODO(svenpanne) This method is on death row...
+  static v8::Isolate* GetDefaultIsolateForLocking();
+
   int id() const { return static_cast<int>(id_); }
 
   HStatistics* GetHStatistics();
@@ -1373,6 +1381,11 @@ class Isolate {
   DeferredHandles* deferred_handles_head_;
   OptimizingCompilerThread* optimizing_compiler_thread_;
   SweeperThread** sweeper_thread_;
+  int num_sweeper_threads_;
+
+  // TODO(yangguo): This will become obsolete once ResourceConstraints
+  // becomes an argument to Isolate constructor.
+  int max_available_threads_;
 
   // Counts deopt points if deopt_every_n_times is enabled.
   unsigned int stress_deopt_count_;
index 6d03d43..acd36a9 100644 (file)
@@ -564,7 +564,7 @@ void MarkCompactCollector::ClearMarkbits() {
 
 void MarkCompactCollector::StartSweeperThreads() {
   sweeping_pending_ = true;
-  for (int i = 0; i < FLAG_sweeper_threads; i++) {
+  for (int i = 0; i < isolate()->num_sweeper_threads(); i++) {
     isolate()->sweeper_threads()[i]->StartSweeping();
   }
 }
@@ -572,7 +572,7 @@ void MarkCompactCollector::StartSweeperThreads() {
 
 void MarkCompactCollector::WaitUntilSweepingCompleted() {
   ASSERT(sweeping_pending_ == true);
-  for (int i = 0; i < FLAG_sweeper_threads; i++) {
+  for (int i = 0; i < isolate()->num_sweeper_threads(); i++) {
     isolate()->sweeper_threads()[i]->WaitForSweeperThread();
   }
   sweeping_pending_ = false;
@@ -586,7 +586,7 @@ void MarkCompactCollector::WaitUntilSweepingCompleted() {
 intptr_t MarkCompactCollector::
              StealMemoryFromSweeperThreads(PagedSpace* space) {
   intptr_t freed_bytes = 0;
-  for (int i = 0; i < FLAG_sweeper_threads; i++) {
+  for (int i = 0; i < isolate()->num_sweeper_threads(); i++) {
     freed_bytes += isolate()->sweeper_threads()[i]->StealMemory(space);
   }
   space->AddToAccountingStats(freed_bytes);
@@ -4112,8 +4112,10 @@ void MarkCompactCollector::SweepSpaces() {
 #endif
   SweeperType how_to_sweep =
       FLAG_lazy_sweeping ? LAZY_CONSERVATIVE : CONSERVATIVE;
-  if (FLAG_parallel_sweeping) how_to_sweep = PARALLEL_CONSERVATIVE;
-  if (FLAG_concurrent_sweeping) how_to_sweep = CONCURRENT_CONSERVATIVE;
+  if (isolate()->num_sweeper_threads() > 0) {
+    if (FLAG_parallel_sweeping) how_to_sweep = PARALLEL_CONSERVATIVE;
+    if (FLAG_concurrent_sweeping) how_to_sweep = CONCURRENT_CONSERVATIVE;
+  }
   if (FLAG_expose_gc) how_to_sweep = CONSERVATIVE;
   if (sweep_precisely_) how_to_sweep = PRECISE;
 
index 6cb5e21..04ae673 100644 (file)
@@ -9498,7 +9498,7 @@ void JSFunction::MarkForConcurrentRecompilation() {
   ASSERT(!IsOptimized());
   ASSERT(shared()->allows_lazy_compilation() || code()->optimizable());
   ASSERT(!shared()->is_generator());
-  ASSERT(FLAG_concurrent_recompilation);
+  ASSERT(GetIsolate()->concurrent_recompilation_enabled());
   if (FLAG_trace_concurrent_recompilation) {
     PrintF("  ** Marking ");
     PrintName();
@@ -9516,7 +9516,7 @@ void JSFunction::MarkInRecompileQueue() {
   ASSERT(!GetIsolate()->DebuggerHasBreakPoints());
   ASSERT(IsMarkedForConcurrentRecompilation() && !IsOptimized());
   ASSERT(shared()->allows_lazy_compilation() || code()->optimizable());
-  ASSERT(FLAG_concurrent_recompilation);
+  ASSERT(GetIsolate()->concurrent_recompilation_enabled());
   if (FLAG_trace_concurrent_recompilation) {
     PrintF("  ** Queueing ");
     PrintName();
index fbc4f05..32a7f97 100644 (file)
@@ -370,8 +370,13 @@ void OptimizingCompilerThread::AddToOsrBuffer(RecompileJob* job) {
 
 
 #ifdef DEBUG
+bool OptimizingCompilerThread::IsOptimizerThread(Isolate* isolate) {
+  return isolate->concurrent_recompilation_enabled() &&
+         isolate->optimizing_compiler_thread()->IsOptimizerThread();
+}
+
+
 bool OptimizingCompilerThread::IsOptimizerThread() {
-  if (!FLAG_concurrent_recompilation) return false;
   LockGuard<Mutex> lock_guard(&thread_id_mutex_);
   return ThreadId::Current().ToInteger() == thread_id_;
 }
index 754aece..795fa65 100644 (file)
@@ -96,7 +96,12 @@ class OptimizingCompilerThread : public Thread {
     AddToOsrBuffer(NULL);
   }
 
+  static bool Enabled(int max_available) {
+    return (FLAG_concurrent_recompilation && max_available > 1);
+  }
+
 #ifdef DEBUG
+  static bool IsOptimizerThread(Isolate* isolate);
   bool IsOptimizerThread();
 #endif
 
index 7c900b3..691fc66 100644 (file)
@@ -139,8 +139,9 @@ void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) {
   }
 
 
-  if (FLAG_concurrent_recompilation && !isolate_->bootstrapper()->IsActive()) {
-    if (FLAG_concurrent_osr &&
+  if (isolate_->concurrent_recompilation_enabled() &&
+      !isolate_->bootstrapper()->IsActive()) {
+    if (isolate_->concurrent_osr_enabled() &&
         isolate_->optimizing_compiler_thread()->IsQueuedForOSR(function)) {
       // Do not attempt regular recompilation if we already queued this for OSR.
       // TODO(yangguo): This is necessary so that we don't install optimized
index 449d8a3..213166a 100644 (file)
@@ -8424,7 +8424,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ConcurrentRecompile) {
     return isolate->heap()->undefined_value();
   }
   function->shared()->code()->set_profiler_ticks(0);
-  ASSERT(FLAG_concurrent_recompilation);
+  ASSERT(isolate->concurrent_recompilation_enabled());
   if (!Compiler::RecompileConcurrent(function)) {
     function->ReplaceCode(function->shared()->code());
   }
@@ -8561,7 +8561,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
 
 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsConcurrentRecompilationSupported) {
   HandleScope scope(isolate);
-  return FLAG_concurrent_recompilation
+  return isolate->concurrent_recompilation_enabled()
       ? isolate->heap()->true_value() : isolate->heap()->false_value();
 }
 
@@ -8619,7 +8619,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
     }
   }
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
-  if (FLAG_concurrent_recompilation && sync_with_compiler_thread) {
+  if (isolate->concurrent_recompilation_enabled() &&
+      sync_with_compiler_thread) {
     while (function->IsInRecompileQueue()) {
       isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
       OS::Sleep(50);
@@ -8697,7 +8698,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
   Handle<Code> result = Handle<Code>::null();
   BailoutId ast_id = BailoutId::None();
 
-  if (FLAG_concurrent_osr) {
+  if (isolate->concurrent_osr_enabled()) {
     if (isolate->optimizing_compiler_thread()->
             IsQueuedForOSR(function, pc_offset)) {
       // Still waiting for the optimizing compiler thread to finish.  Carry on.
index 58c684a..6f3baed 100644 (file)
@@ -105,4 +105,14 @@ void SweeperThread::StartSweeping() {
 void SweeperThread::WaitForSweeperThread() {
   end_sweeping_semaphore_.Wait();
 }
+
+
+int SweeperThread::NumberOfThreads(int max_available) {
+  if (!FLAG_concurrent_sweeping && !FLAG_parallel_sweeping) return 0;
+  if (FLAG_sweeper_threads > 0) return FLAG_sweeper_threads;
+  if (FLAG_concurrent_sweeping) return max_available - 1;
+  ASSERT(FLAG_parallel_sweeping);
+  return max_available;
+}
+
 } }  // namespace v8::internal
index c36cfc3..96255a0 100644 (file)
@@ -51,6 +51,8 @@ class SweeperThread : public Thread {
   void WaitForSweeperThread();
   intptr_t StealMemory(PagedSpace* space);
 
+  static int NumberOfThreads(int max_available);
+
  private:
   Isolate* isolate_;
   Heap* heap_;
index c35230d..17007a2 100644 (file)
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -179,38 +179,6 @@ void V8::InitializeOncePerProcessImpl() {
     FLAG_max_new_space_size = (1 << (kPageSizeBits - 10)) * 2;
   }
 
-  if (FLAG_concurrent_recompilation &&
-      (FLAG_trace_hydrogen || FLAG_trace_hydrogen_stubs)) {
-    FLAG_concurrent_recompilation = false;
-    FLAG_concurrent_osr = false;
-    PrintF("Concurrent recompilation has been disabled for tracing.\n");
-  }
-
-  if (FLAG_sweeper_threads <= 0) {
-    if (FLAG_concurrent_sweeping) {
-      FLAG_sweeper_threads = SystemThreadManager::
-          NumberOfParallelSystemThreads(
-              SystemThreadManager::CONCURRENT_SWEEPING);
-    } else if (FLAG_parallel_sweeping) {
-      FLAG_sweeper_threads = SystemThreadManager::
-          NumberOfParallelSystemThreads(
-              SystemThreadManager::PARALLEL_SWEEPING);
-    }
-    if (FLAG_sweeper_threads == 0) {
-      FLAG_concurrent_sweeping = false;
-      FLAG_parallel_sweeping = false;
-    }
-  } else if (!FLAG_concurrent_sweeping && !FLAG_parallel_sweeping) {
-    FLAG_sweeper_threads = 0;
-  }
-
-  if (FLAG_concurrent_recompilation &&
-      SystemThreadManager::NumberOfParallelSystemThreads(
-          SystemThreadManager::CONCURRENT_RECOMPILATION) == 0) {
-    FLAG_concurrent_recompilation = false;
-    FLAG_concurrent_osr = false;
-  }
-
   Sampler::SetUp();
   CPU::SetUp();
   OS::PostSetUp();
index 765b1ce..c9200ed 100644 (file)
@@ -77,27 +77,23 @@ class AlwaysOptimizeAllowNativesSyntaxNoInlining {
 
 // Utility class to set --allow-natives-syntax and --nouse-inlining when
 // constructed and return to their default state when destroyed.
-class AllowNativesSyntaxNoInliningNoConcurrent {
+class AllowNativesSyntaxNoInlining {
  public:
-  AllowNativesSyntaxNoInliningNoConcurrent()
+  AllowNativesSyntaxNoInlining()
       : allow_natives_syntax_(i::FLAG_allow_natives_syntax),
-        use_inlining_(i::FLAG_use_inlining),
-        concurrent_recompilation_(i::FLAG_concurrent_recompilation) {
+        use_inlining_(i::FLAG_use_inlining) {
     i::FLAG_allow_natives_syntax = true;
     i::FLAG_use_inlining = false;
-    i::FLAG_concurrent_recompilation = false;
   }
 
-  ~AllowNativesSyntaxNoInliningNoConcurrent() {
+  ~AllowNativesSyntaxNoInlining() {
     i::FLAG_allow_natives_syntax = allow_natives_syntax_;
     i::FLAG_use_inlining = use_inlining_;
-    i::FLAG_concurrent_recompilation = concurrent_recompilation_;
   }
 
  private:
   bool allow_natives_syntax_;
   bool use_inlining_;
-  bool concurrent_recompilation_;
 };
 
 
@@ -341,13 +337,14 @@ TEST(DeoptimizeConstructorMultiple) {
 
 
 TEST(DeoptimizeBinaryOperationADDString) {
+  i::FLAG_concurrent_recompilation = false;
+  AllowNativesSyntaxNoInlining options;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
   const char* f_source = "function f(x, y) { return x + y; };";
 
   {
-    AllowNativesSyntaxNoInliningNoConcurrent options;
     // Compile function f and collect to type feedback to insert binary op stub
     // call in the optimized code.
     i::FLAG_prepare_always_opt = true;
@@ -405,7 +402,7 @@ static void TestDeoptimizeBinaryOpHelper(LocalContext* env,
                binary_op);
   char* f_source = f_source_buffer.start();
 
-  AllowNativesSyntaxNoInliningNoConcurrent options;
+  AllowNativesSyntaxNoInlining options;
   // Compile function f and collect to type feedback to insert binary op stub
   // call in the optimized code.
   i::FLAG_prepare_always_opt = true;
@@ -431,6 +428,7 @@ static void TestDeoptimizeBinaryOpHelper(LocalContext* env,
 
 
 TEST(DeoptimizeBinaryOperationADD) {
+  i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -443,6 +441,7 @@ TEST(DeoptimizeBinaryOperationADD) {
 
 
 TEST(DeoptimizeBinaryOperationSUB) {
+  i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -455,6 +454,7 @@ TEST(DeoptimizeBinaryOperationSUB) {
 
 
 TEST(DeoptimizeBinaryOperationMUL) {
+  i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -467,6 +467,7 @@ TEST(DeoptimizeBinaryOperationMUL) {
 
 
 TEST(DeoptimizeBinaryOperationDIV) {
+  i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -479,6 +480,7 @@ TEST(DeoptimizeBinaryOperationDIV) {
 
 
 TEST(DeoptimizeBinaryOperationMOD) {
+  i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -491,13 +493,14 @@ TEST(DeoptimizeBinaryOperationMOD) {
 
 
 TEST(DeoptimizeCompare) {
+  i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
   const char* f_source = "function f(x, y) { return x < y; };";
 
   {
-    AllowNativesSyntaxNoInliningNoConcurrent options;
+    AllowNativesSyntaxNoInlining options;
     // Compile function f and collect to type feedback to insert compare ic
     // call in the optimized code.
     i::FLAG_prepare_always_opt = true;
@@ -534,6 +537,7 @@ TEST(DeoptimizeCompare) {
 
 
 TEST(DeoptimizeLoadICStoreIC) {
+  i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -544,7 +548,7 @@ TEST(DeoptimizeLoadICStoreIC) {
   const char* g2_source = "function g2(x, y) { x[y] = 1; };";
 
   {
-    AllowNativesSyntaxNoInliningNoConcurrent options;
+    AllowNativesSyntaxNoInlining options;
     // Compile functions and collect to type feedback to insert ic
     // calls in the optimized code.
     i::FLAG_prepare_always_opt = true;
@@ -614,6 +618,7 @@ TEST(DeoptimizeLoadICStoreIC) {
 
 
 TEST(DeoptimizeLoadICStoreICNested) {
+  i::FLAG_concurrent_recompilation = false;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
 
@@ -624,7 +629,7 @@ TEST(DeoptimizeLoadICStoreICNested) {
   const char* g2_source = "function g2(x, y) { x[y] = 1; };";
 
   {
-    AllowNativesSyntaxNoInliningNoConcurrent options;
+    AllowNativesSyntaxNoInlining options;
     // Compile functions and collect to type feedback to insert ic
     // calls in the optimized code.
     i::FLAG_prepare_always_opt = true;
index 799146e..cf371d6 100644 (file)
@@ -2963,8 +2963,6 @@ void ReleaseStackTraceDataTest(const char* source, const char* accessor) {
   // after the first time the accessor is fired.  We use external string
   // to check whether the data is being released since the external string
   // resource's callback is fired when the external string is GC'ed.
-  FLAG_use_ic = false;  // ICs retain objects.
-  FLAG_concurrent_recompilation = false;
   v8::HandleScope scope(CcTest::isolate());
   SourceResource* resource = new SourceResource(i::StrDup(source));
   {
@@ -2987,6 +2985,8 @@ void ReleaseStackTraceDataTest(const char* source, const char* accessor) {
 
 
 TEST(ReleaseStackTraceData) {
+  FLAG_use_ic = false;  // ICs retain objects.
+  FLAG_concurrent_recompilation = false;
   CcTest::InitializeVM();
   static const char* source1 = "var error = null;            "
   /* Normal Error */           "try {                        "