Index: src/optimizing-compiler-thread.cc |
diff --git a/src/optimizing-compiler-thread.cc b/src/optimizing-compiler-thread.cc |
index 029c115fcab978f1beef82e7fcfdeca2c83efde3..2a327ffb663effb2fdb41bd329715c1846fa30d7 100644 |
--- a/src/optimizing-compiler-thread.cc |
+++ b/src/optimizing-compiler-thread.cc |
@@ -29,6 +29,7 @@ |
#include "v8.h" |
+#include "full-codegen.h" |
#include "hydrogen.h" |
#include "isolate.h" |
#include "v8threads.h" |
@@ -107,16 +108,20 @@ void OptimizingCompilerThread::CompileNext() { |
// The function may have already been optimized by OSR. Simply continue. |
// Use a mutex to make sure that functions marked for install |
// are always also queued. |
- if (!optimizing_compiler->info()->osr_ast_id().IsNone()) { |
- ASSERT(FLAG_concurrent_osr); |
- LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); |
- osr_candidates_.RemoveElement(optimizing_compiler); |
- ready_for_osr_.Add(optimizing_compiler); |
- } else { |
- LockGuard<Mutex> access_queue(&queue_mutex_); |
- output_queue_.Enqueue(optimizing_compiler); |
- isolate_->stack_guard()->RequestInstallCode(); |
+ LockGuard<Mutex> access_queue(&queue_mutex_); |
+ output_queue_.Enqueue(optimizing_compiler); |
+ isolate_->stack_guard()->RequestInstallCode(); |
+} |
+ |
+ |
+static void DisposeOptimizingCompiler(OptimizingCompiler* compiler, |
+ bool restore_function_code) { |
+ CompilationInfo* info = compiler->info(); |
+ if (restore_function_code) { |
+ Handle<JSFunction> function = info->closure(); |
+ function->ReplaceCode(function->shared()->code()); |
} |
+ delete info; |
} |
@@ -127,17 +132,12 @@ void OptimizingCompilerThread::FlushInputQueue(bool restore_function_code) { |
// This should not block, since we have one signal on the input queue |
// semaphore corresponding to each element in the input queue. |
input_queue_semaphore_.Wait(); |
- CompilationInfo* info = optimizing_compiler->info(); |
- if (restore_function_code) { |
- Handle<JSFunction> function = info->closure(); |
- function->ReplaceCode(function->shared()->code()); |
+ if (optimizing_compiler->info()->osr_ast_id().IsNone()) { |
+ // OSR jobs are dealt with separately. |
+ DisposeOptimizingCompiler(optimizing_compiler, restore_function_code); |
} |
- delete info; |
} |
Release_Store(&queue_length_, static_cast<AtomicWord>(0)); |
- |
- LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); |
- osr_candidates_.Clear(); |
} |
@@ -148,15 +148,23 @@ void OptimizingCompilerThread::FlushOutputQueue(bool restore_function_code) { |
{ LockGuard<Mutex> access_queue(&queue_mutex_); |
if (!output_queue_.Dequeue(&optimizing_compiler)) break; |
} |
- CompilationInfo* info = optimizing_compiler->info(); |
- if (restore_function_code) { |
- Handle<JSFunction> function = info->closure(); |
- function->ReplaceCode(function->shared()->code()); |
+ if (optimizing_compiler->info()->osr_ast_id().IsNone()) { |
+ // OSR jobs are dealt with separately. |
+ DisposeOptimizingCompiler(optimizing_compiler, restore_function_code); |
} |
- delete info; |
} |
+} |
- RemoveStaleOSRCandidates(0); |
+ |
+void OptimizingCompilerThread::FlushOsrBuffer(bool restore_function_code) { |
+ OptimizingCompiler* optimizing_compiler; |
+ for (int i = 0; i < osr_buffer_size_; i++) { |
+ optimizing_compiler = osr_buffer_[i]; |
+ if (optimizing_compiler != NULL) { |
+ DisposeOptimizingCompiler(optimizing_compiler, restore_function_code); |
+ } |
+ } |
+ osr_cursor_ = 0; |
} |
@@ -166,6 +174,7 @@ void OptimizingCompilerThread::Flush() { |
input_queue_semaphore_.Signal(); |
stop_semaphore_.Wait(); |
FlushOutputQueue(true); |
+ if (FLAG_concurrent_osr) FlushOsrBuffer(true); |
} |
@@ -186,12 +195,15 @@ void OptimizingCompilerThread::Stop() { |
FlushOutputQueue(false); |
} |
+ if (FLAG_concurrent_osr) FlushOsrBuffer(false); |
+ |
if (FLAG_trace_concurrent_recompilation) { |
double percentage = time_spent_compiling_.PercentOf(time_spent_total_); |
PrintF(" ** Compiler thread did %.2f%% useful work\n", percentage); |
} |
- if (FLAG_trace_osr && FLAG_concurrent_osr) { |
+ if ((FLAG_trace_osr || FLAG_trace_concurrent_recompilation) && |
+ FLAG_concurrent_osr) { |
PrintF("[COSR hit rate %d / %d]\n", osr_hits_, osr_attempts_); |
} |
@@ -208,12 +220,20 @@ void OptimizingCompilerThread::InstallOptimizedFunctions() { |
{ LockGuard<Mutex> access_queue(&queue_mutex_); |
if (!output_queue_.Dequeue(&compiler)) break; |
} |
- Compiler::InstallOptimizedCode(compiler); |
+ CompilationInfo* info = compiler->info(); |
+ if (info->osr_ast_id().IsNone()) { |
+ Compiler::InstallOptimizedCode(compiler); |
+ } else { |
+ if (FLAG_trace_osr) { |
+ PrintF("[COSR - "); |
+ info->closure()->PrintName(); |
+ PrintF(" is ready for install and entry at AST id %d]\n", |
+ info->osr_ast_id().ToInt()); |
+ } |
+ compiler->WaitForInstall(); |
+ BackEdgeTable::RemoveStackCheck(info); |
+ } |
} |
- |
- // Remove the oldest OSR candidates that are ready so that we |
- // only have limited number of them waiting. |
- if (FLAG_concurrent_osr) RemoveStaleOSRCandidates(); |
} |
@@ -222,12 +242,18 @@ void OptimizingCompilerThread::QueueForOptimization( |
ASSERT(IsQueueAvailable()); |
ASSERT(!IsOptimizerThread()); |
Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(1)); |
- if (optimizing_compiler->info()->osr_ast_id().IsNone()) { |
- optimizing_compiler->info()->closure()->MarkInRecompileQueue(); |
+ CompilationInfo* info = optimizing_compiler->info(); |
+ if (info->osr_ast_id().IsNone()) { |
+ info->closure()->MarkInRecompileQueue(); |
} else { |
- LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); |
- osr_candidates_.Add(optimizing_compiler); |
+ if (FLAG_trace_concurrent_recompilation) { |
+ PrintF(" ** Queueing "); |
+ info->closure()->PrintName(); |
+ PrintF(" for concurrent on-stack replacement.\n"); |
+ } |
+ AddToOsrBuffer(optimizing_compiler); |
osr_attempts_++; |
+ BackEdgeTable::AddStackCheck(info); |
} |
input_queue_.Enqueue(optimizing_compiler); |
input_queue_semaphore_.Signal(); |
@@ -238,27 +264,27 @@ OptimizingCompiler* OptimizingCompilerThread::FindReadyOSRCandidate( |
Handle<JSFunction> function, uint32_t osr_pc_offset) { |
ASSERT(!IsOptimizerThread()); |
OptimizingCompiler* result = NULL; |
- { LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); |
- for (int i = 0; i < ready_for_osr_.length(); i++) { |
- if (ready_for_osr_[i]->info()->HasSameOsrEntry(function, osr_pc_offset)) { |
- osr_hits_++; |
- result = ready_for_osr_.Remove(i); |
- break; |
- } |
+ for (int i = 0; i < osr_buffer_size_; i++) { |
+ result = osr_buffer_[i]; |
+ if (result == NULL) continue; |
+ if (result->IsWaitingForInstall() && |
+ result->info()->HasSameOsrEntry(function, osr_pc_offset)) { |
+ osr_hits_++; |
+ osr_buffer_[i] = NULL; |
+ return result; |
} |
} |
- RemoveStaleOSRCandidates(); |
- return result; |
+ return NULL; |
} |
bool OptimizingCompilerThread::IsQueuedForOSR(Handle<JSFunction> function, |
uint32_t osr_pc_offset) { |
ASSERT(!IsOptimizerThread()); |
- LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); |
- for (int i = 0; i < osr_candidates_.length(); i++) { |
- if (osr_candidates_[i]->info()->HasSameOsrEntry(function, osr_pc_offset)) { |
- return true; |
+ for (int i = 0; i < osr_buffer_size_; i++) { |
+ if (osr_buffer_[i] != NULL && |
+ osr_buffer_[i]->info()->HasSameOsrEntry(function, osr_pc_offset)) { |
+ return !osr_buffer_[i]->IsWaitingForInstall(); |
} |
} |
return false; |
@@ -267,30 +293,40 @@ bool OptimizingCompilerThread::IsQueuedForOSR(Handle<JSFunction> function, |
bool OptimizingCompilerThread::IsQueuedForOSR(JSFunction* function) { |
ASSERT(!IsOptimizerThread()); |
- LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); |
- for (int i = 0; i < osr_candidates_.length(); i++) { |
- if (*osr_candidates_[i]->info()->closure() == function) { |
- return true; |
+ for (int i = 0; i < osr_buffer_size_; i++) { |
+ if (osr_buffer_[i] != NULL && |
+ *osr_buffer_[i]->info()->closure() == function) { |
+ return !osr_buffer_[i]->IsWaitingForInstall(); |
} |
} |
return false; |
} |
-void OptimizingCompilerThread::RemoveStaleOSRCandidates(int limit) { |
+void OptimizingCompilerThread::AddToOsrBuffer(OptimizingCompiler* compiler) { |
ASSERT(!IsOptimizerThread()); |
- LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); |
- while (ready_for_osr_.length() > limit) { |
- OptimizingCompiler* compiler = ready_for_osr_.Remove(0); |
- CompilationInfo* throw_away = compiler->info(); |
- if (FLAG_trace_osr) { |
- PrintF("[COSR - Discarded "); |
- throw_away->closure()->PrintName(); |
- PrintF(", AST id %d]\n", |
- throw_away->osr_ast_id().ToInt()); |
+ // Store into next empty slot or replace next stale OSR job that's waiting |
+ // in vain. Dispose in the latter case. |
+ OptimizingCompiler* stale; |
+ while (true) { |
+ stale = osr_buffer_[osr_cursor_]; |
+ if (stale == NULL) break; |
+ if (stale->IsWaitingForInstall()) { |
+ CompilationInfo* info = stale->info(); |
+ if (FLAG_trace_osr) { |
+ PrintF("[COSR - Discarded "); |
+ info->closure()->PrintName(); |
+ PrintF(", AST id %d]\n", info->osr_ast_id().ToInt()); |
+ } |
+ BackEdgeTable::RemoveStackCheck(info); |
+ DisposeOptimizingCompiler(stale, false); |
+ break; |
} |
- delete throw_away; |
+ AdvanceOsrCursor(); |
} |
+ |
+ osr_buffer_[osr_cursor_] = compiler; |
+ AdvanceOsrCursor(); |
} |