From: yangguo@chromium.org Date: Thu, 14 Mar 2013 16:35:32 +0000 (+0000) Subject: Parallel recompilation: fix concurrency issues. X-Git-Tag: upstream/4.7.83~14844 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=44c059f1c1f92ec0896bc4a85fff74dc010ec222;p=platform%2Fupstream%2Fv8.git Parallel recompilation: fix concurrency issues. BUG= Review URL: https://chromiumcodereview.appspot.com/12831003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13949 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/compiler.cc b/src/compiler.cc index 47ae439..e51fb42 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -946,7 +946,6 @@ void Compiler::RecompileParallel(Handle closure) { // Do a scavenge to put off the next scavenge as far as possible. // This may ease the issue that GVN blocks the next scavenge. isolate->heap()->CollectGarbage(NEW_SPACE, "parallel recompile"); - closure->MarkInRecompileQueue(); shared->code()->set_profiler_ticks(0); info.Detach(); isolate->optimizing_compiler_thread()->QueueForOptimization(compiler); @@ -978,12 +977,17 @@ void Compiler::RecompileParallel(Handle closure) { void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) { SmartPointer info(optimizing_compiler->info()); - ASSERT(info->closure()->IsMarkedForInstallingRecompiledCode()); - // While waiting for the optimizer thread, OSR may have already done all - // the work and disabled optimization of this function for some reason. + // The function may have already been optimized by OSR. Simply continue. + // Except when OSR already disabled optimization for some reason. if (info->shared_info()->optimization_disabled()) { info->SetCode(Handle(info->shared_info()->code())); InstallFullCode(*info); + if (FLAG_trace_parallel_recompilation) { + PrintF(" ** aborting optimization for "); + info->closure()->PrintName(); + PrintF(" as it has been disabled.\n"); + } + ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode()); return; } @@ -1025,6 +1029,7 @@ void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) { // Optimized code is finally replacing unoptimized code. Reset the latter's // profiler ticks to prevent too soon re-opt after a deopt. info->shared_info()->code()->set_profiler_ticks(0); + ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode()); } diff --git a/src/optimizing-compiler-thread.cc b/src/optimizing-compiler-thread.cc index 7952fca..b982b94 100644 --- a/src/optimizing-compiler-thread.cc +++ b/src/optimizing-compiler-thread.cc @@ -80,24 +80,16 @@ void OptimizingCompilerThread::CompileNext() { input_queue_.Dequeue(&optimizing_compiler); Barrier_AtomicIncrement(&queue_length_, static_cast(-1)); - ASSERT(optimizing_compiler->info()->closure()->IsInRecompileQueue()); - + // The function may have already been optimized by OSR. Simply continue. OptimizingCompiler::Status status = optimizing_compiler->OptimizeGraph(); + USE(status); // Prevent an unused-variable error in release mode. ASSERT(status != OptimizingCompiler::FAILED); - // Prevent an unused-variable error in release mode. - USE(status); - - output_queue_.Enqueue(optimizing_compiler); - // The execution thread can call InstallOptimizedFunctions() at any time, - // including at this point, after queuing for install and before marking - // for install. To avoid race condition, functions that are queued but not - // yet marked for install are not processed by InstallOptimizedFunctions(). - - ASSERT(optimizing_compiler->info()->closure()->IsInRecompileQueue()); - // Mark function to generate and install optimized code. We assume this - // write to be atomic. + // The function may have already been optimized by OSR. Simply continue. + // Mark it for installing before queuing so that we can be sure of the write + // order: marking first and (after being queued) installing code second. optimizing_compiler->info()->closure()->MarkForInstallingRecompiledCode(); + output_queue_.Enqueue(optimizing_compiler); } @@ -108,10 +100,6 @@ void OptimizingCompilerThread::Stop() { stop_semaphore_->Wait(); if (FLAG_parallel_recompilation_delay != 0) { - // Execution ended before we managed to compile and install the remaining - // functions in the queue. We still want to do that for debugging though. - // At this point the optimizing thread already stopped, so we finish - // processing the queue in the main thread. InstallOptimizedFunctions(); // Barrier when loading queue length is not necessary since the write // happens in CompileNext on the same thread. @@ -135,23 +123,9 @@ void OptimizingCompilerThread::InstallOptimizedFunctions() { HandleScope handle_scope(isolate_); int functions_installed = 0; while (!output_queue_.IsEmpty()) { - OptimizingCompiler* compiler = *output_queue_.Peek(); - - if (compiler->info()->closure()->IsInRecompileQueue()) { - // A function may be queued for install, but not marked as such yet. - // We continue with the output queue the next to avoid race condition. - break; - } + OptimizingCompiler* compiler; output_queue_.Dequeue(&compiler); - -#ifdef DEBUG - // Create new closure handle since the deferred handle is about to die. - Handle closure(*compiler->info()->closure()); -#endif // DEBUG - Compiler::InstallOptimizedCode(compiler); - // Assert that the marker builtin has been replaced by actual code. - ASSERT(!closure->IsInRecompileQueue()); functions_installed++; } } @@ -162,6 +136,7 @@ void OptimizingCompilerThread::QueueForOptimization( ASSERT(IsQueueAvailable()); ASSERT(!IsOptimizerThread()); Barrier_AtomicIncrement(&queue_length_, static_cast(1)); + optimizing_compiler->info()->closure()->MarkInRecompileQueue(); input_queue_.Enqueue(optimizing_compiler); input_queue_semaphore_->Signal(); } diff --git a/src/runtime.cc b/src/runtime.cc index 6c2664b..12777e7 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -7729,7 +7729,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ParallelRecompile) { CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); if (!AllowOptimization(isolate, function)) { function->ReplaceCode(function->shared()->code()); - return function->code(); + return isolate->heap()->undefined_value(); } function->shared()->code()->set_profiler_ticks(0); ASSERT(FLAG_parallel_recompilation); @@ -7742,10 +7742,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InstallRecompiledCode) { HandleScope handle_scope(isolate); ASSERT(args.length() == 1); CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); - if (!V8::UseCrankshaft()) return isolate->heap()->undefined_value(); - ASSERT(FLAG_parallel_recompilation); + ASSERT(V8::UseCrankshaft() && FLAG_parallel_recompilation); OptimizingCompilerThread* opt_thread = isolate->optimizing_compiler_thread(); - opt_thread->InstallOptimizedFunctions(); + do { + // The function could have been marked for installing, but not queued just + // yet. In this case, retry until installed. + opt_thread->InstallOptimizedFunctions(); + } while (function->IsMarkedForInstallingRecompiledCode()); return function->code(); }