Index: runtime/vm/compiler.cc |
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc |
index f3d879a8c90bf2a28d645b2b1974441517858ac5..8c1b0628e8f48d76e760f2b57167cbf28f71c3cd 100644 |
--- a/runtime/vm/compiler.cc |
+++ b/runtime/vm/compiler.cc |
@@ -35,6 +35,7 @@ |
#include "vm/scanner.h" |
#include "vm/symbols.h" |
#include "vm/tags.h" |
+#include "vm/thread_registry.h" |
#include "vm/timer.h" |
namespace dart { |
@@ -390,8 +391,7 @@ RawError* Compiler::CompileClass(const Class& cls) { |
static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
ParsedFunction* parsed_function, |
bool optimized, |
- intptr_t osr_id, |
- BackgroundCompilationResult* result) { |
+ intptr_t osr_id) { |
const Function& function = parsed_function->function(); |
if (optimized && !function.IsOptimizable()) { |
return false; |
@@ -403,6 +403,13 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
CSTAT_TIMER_SCOPE(thread, codegen_timer); |
HANDLESCOPE(thread); |
+ // Get current generetion count to check in background compilation |
+ // if the code may got invalidated while compiling. |
siva
2015/11/18 17:46:27
The comment does not read well, maybe
Get current
srdjan
2015/11/18 19:04:53
Done.
|
+ uint32_t cha_invalidation_gen_at_start = isolate->cha_invalidation_gen(); |
+ uint32_t field_invalidation_gen_at_start = isolate->field_invalidation_gen(); |
+ uint32_t prefix_invalidation_gen_at_start = |
+ isolate->prefix_invalidation_gen(); |
+ |
// We may reattempt compilation if the function needs to be assembled using |
// far branches on ARM and MIPS. In the else branch of the setjmp call, |
// done is set to false, and use_far_branches is set to true if there is a |
@@ -738,6 +745,15 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
pipeline->FinalizeCompilation(); |
} |
{ |
+ // This part of compilation must be at a safepoint. |
+ if (!Thread::Current()->IsMutatorThread()) { |
+ // Stop mutator thread while in background compilation. |
siva
2015/11/18 17:46:27
Stop mutator thread before creating the instructio
srdjan
2015/11/18 19:04:53
Stop mutator thread before creating the instructio
|
+ // Mutator thread may not run code while we are creating the |
+ // instruction object, since the creation of instruction object |
+ // changes code page access permissions (makes them temporary not |
+ // executable). |
+ isolate->thread_registry()->SafepointThreads(); |
+ } |
CSTAT_TIMER_SCOPE(thread, codefinalizer_timer); |
// CreateDeoptInfo uses the object pool and needs to be done before |
// FinalizeCode. |
@@ -776,63 +792,66 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
graph_compiler.FinalizeStaticCallTargetsTable(code); |
if (optimized) { |
- if (result != NULL) { |
- // Background compilation, store compilation result in 'result'. |
- ASSERT(!Thread::Current()->IsMutatorThread()); |
- // Do not install code, but return it instead. |
- // Since code dependencies (CHA, fields) are defined eagerly, |
- // the code may be disabled before installing it. |
- code.set_owner(function); |
- result->set_result_code(code); |
- // Disable invalidation counters that are not relevant. |
- if (thread->cha()->leaf_classes().is_empty()) { |
- result->ClearCHAInvalidationGen(); |
+ if (thread->IsMutatorThread()) { |
+ const bool is_osr = osr_id != Compiler::kNoOSRDeoptId; |
+ function.InstallOptimizedCode(code, is_osr); |
siva
2015/11/18 17:46:27
Maybe add a comment here that there won't be concu
srdjan
2015/11/18 19:04:53
Adding that comment above at FinalizeCode:
|
+ } else { |
+ // Background compilation |
siva
2015/11/18 17:46:27
Background compilation.
srdjan
2015/11/18 19:04:53
Done and added:
// Before installing c
|
+ bool code_is_valid = true; |
+ if (!thread->cha()->leaf_classes().is_empty()) { |
+ if (cha_invalidation_gen_at_start != |
+ isolate->cha_invalidation_gen()) { |
+ code_is_valid = false; |
+ } |
} |
- if (flow_graph->guarded_fields()->is_empty()) { |
- result->ClearFieldInvalidationGen(); |
+ if (!flow_graph->guarded_fields()->is_empty()) { |
+ if (field_invalidation_gen_at_start != |
+ isolate->field_invalidation_gen()) { |
+ code_is_valid = false; |
+ } |
} |
- if (!parsed_function->HasDeferredPrefixes()) { |
- result->ClearPrefixInvalidationGen(); |
+ if (parsed_function->HasDeferredPrefixes()) { |
+ if (prefix_invalidation_gen_at_start != |
+ isolate->prefix_invalidation_gen()) { |
+ code_is_valid = false; |
+ } |
+ } |
+ if (code_is_valid) { |
+ const bool is_osr = osr_id != Compiler::kNoOSRDeoptId; |
+ ASSERT(!is_osr); // OSR is compiled in background. |
+ function.InstallOptimizedCode(code, is_osr); |
+ } |
+ if (function.usage_counter() < 0) { |
+ // Reset to 0 so that it can be recompiled if needed. |
+ function.set_usage_counter(0); |
} |
- } else { |
- const bool is_osr = osr_id != Compiler::kNoOSRDeoptId; |
- function.InstallOptimizedCode(code, is_osr); |
} |
// Register code with the classes it depends on because of CHA and |
// fields it depends on because of store guards, unless we cannot |
// deopt. |
if (Compiler::allow_recompilation()) { |
- if (result != NULL) { |
- // Background compilation: delay registering code until we are |
- // in the MutatorThread. |
- result->SetLeafClasses(thread->cha()->leaf_classes()); |
- result->SetGuardedFields(*flow_graph->guarded_fields()); |
- result->SetDeoptimizeDependentFields( |
- flow_graph->deoptimize_dependent_code()); |
- } else { |
- // Deoptimize field dependent code first, before registering |
- // this yet uninstalled code as dependent on a field. |
- // TODO(srdjan): Debugging dart2js crashes; |
- // FlowGraphOptimizer::VisitStoreInstanceField populates |
- // deoptimize_dependent_code() list, currently disabled. |
- for (intptr_t i = 0; |
- i < flow_graph->deoptimize_dependent_code().length(); |
- i++) { |
- const Field* field = flow_graph->deoptimize_dependent_code()[i]; |
- field->DeoptimizeDependentCode(); |
- } |
- for (intptr_t i = 0; |
- i < thread->cha()->leaf_classes().length(); |
- ++i) { |
- thread->cha()->leaf_classes()[i]->RegisterCHACode(code); |
- } |
- for (intptr_t i = 0; |
- i < flow_graph->guarded_fields()->length(); |
- i++) { |
- const Field* field = (*flow_graph->guarded_fields())[i]; |
- field->RegisterDependentCode(code); |
- } |
+ // Deoptimize field dependent code first, before registering |
+ // this yet uninstalled code as dependent on a field. |
+ // TODO(srdjan): Debugging dart2js crashes; |
+ // FlowGraphOptimizer::VisitStoreInstanceField populates |
+ // deoptimize_dependent_code() list, currently disabled. |
+ for (intptr_t i = 0; |
+ i < flow_graph->deoptimize_dependent_code().length(); |
+ i++) { |
+ const Field* field = flow_graph->deoptimize_dependent_code()[i]; |
+ field->DeoptimizeDependentCode(); |
+ } |
+ for (intptr_t i = 0; |
+ i < thread->cha()->leaf_classes().length(); |
+ ++i) { |
+ thread->cha()->leaf_classes()[i]->RegisterCHACode(code); |
+ } |
+ for (intptr_t i = 0; |
+ i < flow_graph->guarded_fields()->length(); |
+ i++) { |
+ const Field* field = (*flow_graph->guarded_fields())[i]; |
+ field->RegisterDependentCode(code); |
} |
} |
} else { // not optimized. |
@@ -853,6 +872,10 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
(*prefixes)[i]->RegisterDependentCode(code); |
} |
} |
+ if (!Thread::Current()->IsMutatorThread()) { |
+ // Background compilation. |
+ isolate->thread_registry()->ResumeAllThreads(); |
+ } |
} |
// Mark that this isolate now has compiled code. |
isolate->set_has_compiled_code(true); |
@@ -1058,8 +1081,7 @@ static void CheckInliningIntervals(const Function& function) { |
static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, |
const Function& function, |
bool optimized, |
- intptr_t osr_id, |
- BackgroundCompilationResult* result) { |
+ intptr_t osr_id) { |
// Check that we optimize if 'Compiler::always_optimize()' is set to true, |
// except if the function is marked as not optimizable. |
ASSERT(!function.IsOptimizable() || |
@@ -1101,8 +1123,7 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, |
const bool success = CompileParsedFunctionHelper(pipeline, |
parsed_function, |
optimized, |
- osr_id, |
- result); |
+ osr_id); |
if (!success) { |
if (optimized) { |
ASSERT(!Compiler::always_optimize()); // Optimized is the only code. |
@@ -1142,9 +1163,7 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, |
DisassembleCode(function, optimized); |
} else if (FLAG_disassemble_optimized && |
optimized && |
- FlowGraphPrinter::ShouldPrint(function) && |
- (result == NULL) /* no background compilation*/ ) { |
- // With background compilation, print when installing the code. |
+ FlowGraphPrinter::ShouldPrint(function)) { |
// TODO(fschneider): Print unoptimized code along with the optimized code. |
THR_Print("*** BEGIN CODE\n"); |
DisassembleCode(function, true); |
@@ -1196,8 +1215,7 @@ RawError* Compiler::CompileFunction(Thread* thread, |
return CompileFunctionHelper(pipeline, |
function, |
optimized, |
- kNoOSRDeoptId, /* not OSR */ |
- NULL /* no result code */); |
+ kNoOSRDeoptId); |
} |
@@ -1216,8 +1234,7 @@ RawError* Compiler::EnsureUnoptimizedCode(Thread* thread, |
CompileFunctionHelper(pipeline, |
function, |
false, /* not optimized */ |
- kNoOSRDeoptId, /* not OSR */ |
- NULL /* no result code */)); |
+ kNoOSRDeoptId)); |
if (!error.IsNull()) { |
return error.raw(); |
} |
@@ -1237,8 +1254,7 @@ RawError* Compiler::EnsureUnoptimizedCode(Thread* thread, |
RawError* Compiler::CompileOptimizedFunction(Thread* thread, |
const Function& function, |
- intptr_t osr_id, |
- BackgroundCompilationResult* res) { |
+ intptr_t osr_id) { |
VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId); |
TIMELINE_FUNCTION_COMPILATION_DURATION(thread, |
"OptimizedFunction", function); |
@@ -1252,8 +1268,7 @@ RawError* Compiler::CompileOptimizedFunction(Thread* thread, |
return CompileFunctionHelper(pipeline, |
function, |
true, /* optimized */ |
- osr_id, |
- res); |
+ osr_id); |
} |
@@ -1267,8 +1282,7 @@ RawError* Compiler::CompileParsedFunction( |
CompileParsedFunctionHelper(&pipeline, |
parsed_function, |
false, |
- kNoOSRDeoptId, |
- NULL /* no result code */); |
+ kNoOSRDeoptId); |
if (FLAG_disassemble) { |
DisassembleCode(parsed_function->function(), false); |
} |
@@ -1374,8 +1388,7 @@ void Compiler::CompileStaticInitializer(const Field& field) { |
CompileParsedFunctionHelper(&pipeline, |
parsed_function, |
false, // optimized |
- kNoOSRDeoptId, |
- NULL /* no result code */); |
+ kNoOSRDeoptId); |
const Function& initializer = parsed_function->function(); |
field.SetPrecompiledInitializer(initializer); |
@@ -1406,8 +1419,7 @@ RawObject* Compiler::EvaluateStaticInitializer(const Field& field) { |
CompileParsedFunctionHelper(&pipeline, |
parsed_function, |
false, // optimized |
- kNoOSRDeoptId, |
- NULL /* no result code */); |
+ kNoOSRDeoptId); |
initializer = parsed_function->function().raw(); |
Code::Handle(initializer.unoptimized_code()).set_var_descriptors( |
Object::empty_var_descriptors()); |
@@ -1477,8 +1489,7 @@ RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) { |
CompileParsedFunctionHelper(&pipeline, |
parsed_function, |
false, |
- kNoOSRDeoptId, |
- NULL /* no result code */); |
+ kNoOSRDeoptId); |
Code::Handle(func.unoptimized_code()).set_var_descriptors( |
Object::empty_var_descriptors()); |
@@ -1503,73 +1514,28 @@ class QueueElement { |
public: |
explicit QueueElement(const Function& function) |
: next_(NULL), |
- obj_(function.raw()), |
- leaf_classes_(Array::null()), |
- guarded_fields_(Array::null()), |
- deoptimize_dependent_fields_(Array::null()), |
- cha_invalidation_gen_(Isolate::kInvalidGen), |
- field_invalidation_gen_(Isolate::kInvalidGen), |
- prefix_invalidation_gen_(Isolate::kInvalidGen) { |
+ function_(function.raw()) { |
ASSERT(Thread::Current()->IsMutatorThread()); |
} |
~QueueElement() { |
- ASSERT(Thread::Current()->IsMutatorThread()); |
- obj_ = Object::null(); |
+ function_ = Function::null(); |
} |
- RawFunction* Function() const { return Function::RawCast(obj_); } |
- RawCode* Code() const { return Code::RawCast(obj_); } |
+ RawFunction* Function() const { return function_; } |
- RawArray* leaf_classes() const { return leaf_classes_; } |
- RawArray* guarded_fields() const { return guarded_fields_; } |
- RawArray* deoptimize_dependent_fields() const { |
- return deoptimize_dependent_fields_; |
- } |
- |
- uint32_t cha_invalidation_gen() const { return cha_invalidation_gen_; } |
- uint32_t field_invalidation_gen() const { return field_invalidation_gen_; } |
- uint32_t prefix_invalidation_gen() const { return prefix_invalidation_gen_; } |
void set_next(QueueElement* elem) { next_ = elem; } |
QueueElement* next() const { return next_; } |
- RawObject* obj() const { return obj_; } |
- RawObject** obj_ptr() { return &obj_; } |
- |
- RawObject** leaf_classses_ptr() { |
- return reinterpret_cast<RawObject**>(&leaf_classes_); |
- } |
- |
- RawObject** guarded_fields_ptr() { |
- return reinterpret_cast<RawObject**>(&guarded_fields_); |
- } |
- |
- RawObject** deoptimize_dependent_fields_ptr() { |
- return reinterpret_cast<RawObject**>(&deoptimize_dependent_fields_); |
- } |
- |
- void SetFromResult(const BackgroundCompilationResult& value) { |
- ASSERT(!value.result_code().IsNull()); |
- obj_ = value.result_code().raw(); |
- leaf_classes_ = value.leaf_classes().raw(); |
- guarded_fields_ = value.guarded_fields().raw(); |
- deoptimize_dependent_fields_ = value.deoptimize_dependent_fields().raw(); |
- cha_invalidation_gen_ = value.cha_invalidation_gen(); |
- field_invalidation_gen_ = value.field_invalidation_gen(); |
- prefix_invalidation_gen_ = value.prefix_invalidation_gen(); |
+ RawObject* function() const { return function_; } |
+ RawObject** function_ptr() { |
+ return reinterpret_cast<RawObject**>(&function_); |
} |
private: |
QueueElement* next_; |
- |
- RawObject* obj_; // Code or Function. |
- RawArray* leaf_classes_; |
- RawArray* guarded_fields_; |
- RawArray* deoptimize_dependent_fields_; |
- uint32_t cha_invalidation_gen_; |
- uint32_t field_invalidation_gen_; |
- uint32_t prefix_invalidation_gen_; |
+ RawFunction* function_; |
DISALLOW_COPY_AND_ASSIGN(QueueElement); |
}; |
@@ -1592,10 +1558,7 @@ class BackgroundCompilationQueue { |
ASSERT(visitor != NULL); |
QueueElement* p = first_; |
while (p != NULL) { |
- visitor->VisitPointer(p->obj_ptr()); |
- visitor->VisitPointer(p->leaf_classses_ptr()); |
- visitor->VisitPointer(p->guarded_fields_ptr()); |
- visitor->VisitPointer(p->deoptimize_dependent_fields_ptr()); |
+ visitor->VisitPointer(p->function_ptr()); |
p = p->next(); |
} |
} |
@@ -1639,7 +1602,7 @@ class BackgroundCompilationQueue { |
bool ContainsObj(const Object& obj) const { |
QueueElement* p = first_; |
while (p != NULL) { |
- if (p->obj() == obj.raw()) { |
+ if (p->function() == obj.raw()) { |
return true; |
} |
p = p->next(); |
@@ -1655,120 +1618,10 @@ class BackgroundCompilationQueue { |
}; |
-BackgroundCompilationResult::BackgroundCompilationResult() |
- : result_code_(Code::Handle()), |
- leaf_classes_(Array::Handle()), |
- guarded_fields_(Array::Handle()), |
- deoptimize_dependent_fields_(Array::Handle()), |
- cha_invalidation_gen_(Isolate::kInvalidGen), |
- field_invalidation_gen_(Isolate::kInvalidGen), |
- prefix_invalidation_gen_(Isolate::kInvalidGen) { |
-} |
- |
- |
-void BackgroundCompilationResult::Init() { |
- Isolate* i = Isolate::Current(); |
- result_code_ = Code::null(); |
- leaf_classes_ = Array::null(); |
- guarded_fields_ = Array::null(); |
- deoptimize_dependent_fields_ = Array::null(); |
- cha_invalidation_gen_ = i->cha_invalidation_gen(); |
- field_invalidation_gen_ = i->field_invalidation_gen(); |
- prefix_invalidation_gen_ = i->prefix_invalidation_gen(); |
-} |
- |
- |
-void BackgroundCompilationResult::SetFromQElement(QueueElement* value) { |
- ASSERT(value != NULL); |
- result_code_ = value->Code(); |
- leaf_classes_ = value->leaf_classes(); |
- guarded_fields_ = value->guarded_fields(); |
- deoptimize_dependent_fields_ = value->deoptimize_dependent_fields(); |
- cha_invalidation_gen_ = value->cha_invalidation_gen(); |
- field_invalidation_gen_ = value->field_invalidation_gen(); |
- prefix_invalidation_gen_ = value->prefix_invalidation_gen(); |
-} |
- |
- |
-void BackgroundCompilationResult::SetLeafClasses( |
- const GrowableArray<Class*>& leaf_classes) { |
- const Array& a = Array::Handle(Array::New(leaf_classes.length(), Heap::kOld)); |
- for (intptr_t i = 0; i < leaf_classes.length(); i++) { |
- a.SetAt(i, *leaf_classes[i]); |
- } |
- leaf_classes_ = a.raw(); |
-} |
- |
- |
-void BackgroundCompilationResult::SetGuardedFields( |
- const ZoneGrowableArray<const Field*>& guarded_fields) { |
- const Array& a = |
- Array::Handle(Array::New(guarded_fields.length(), Heap::kOld)); |
- for (intptr_t i = 0; i < guarded_fields.length(); i++) { |
- a.SetAt(i, *guarded_fields[i]); |
- } |
- guarded_fields_ = a.raw(); |
-} |
- |
- |
-void BackgroundCompilationResult::SetDeoptimizeDependentFields( |
- const GrowableArray<const Field*>& fields) { |
- const Array& a = Array::Handle(Array::New(fields.length(), Heap::kOld)); |
- for (intptr_t i = 0; i < fields.length(); i++) { |
- a.SetAt(i, *fields[i]); |
- } |
- deoptimize_dependent_fields_ = a.raw(); |
-} |
- |
- |
-bool BackgroundCompilationResult::IsValid() const { |
- if (result_code().IsNull() || result_code().IsDisabled()) { |
- return false; |
- } |
- Isolate* i = Isolate::Current(); |
- if ((cha_invalidation_gen_ != Isolate::kInvalidGen) && |
- (cha_invalidation_gen_ != i->cha_invalidation_gen())) { |
- return false; |
- } |
- if ((field_invalidation_gen_ != Isolate::kInvalidGen) && |
- (field_invalidation_gen_ != i->field_invalidation_gen())) { |
- return false; |
- } |
- if ((prefix_invalidation_gen_ != Isolate::kInvalidGen) && |
- (prefix_invalidation_gen_ != i->prefix_invalidation_gen())) { |
- return false; |
- } |
- return true; |
-} |
- |
- |
-void BackgroundCompilationResult::PrintValidity() const { |
- Object& o = Object::Handle(result_code().owner()); |
- THR_Print("BackgroundCompilationResult: %s\n", |
- Function::Cast(o).ToQualifiedCString()); |
- if (result_code().IsNull()) { |
- THR_Print(" result_code is NULL\n"); |
- return; |
- } |
- if (result_code().IsDisabled()) { |
- THR_Print(" result_code is disabled\n"); |
- return; |
- } |
- Isolate* i = Isolate::Current(); |
- THR_Print(" cha_invalidation_gen: %u (current: %u)\n", |
- cha_invalidation_gen_, i->cha_invalidation_gen()); |
- THR_Print(" field_invalidation_gen: %u (current: %u)\n", |
- field_invalidation_gen_, i->field_invalidation_gen()); |
- THR_Print(" prefix_invalidation_gen: %u (current: %u)\n", |
- prefix_invalidation_gen_, i->prefix_invalidation_gen()); |
-} |
- |
- |
BackgroundCompiler::BackgroundCompiler(Isolate* isolate) |
: isolate_(isolate), running_(true), done_(new bool()), |
queue_monitor_(new Monitor()), done_monitor_(new Monitor()), |
- function_queue_(new BackgroundCompilationQueue()), |
- result_queue_(new BackgroundCompilationQueue()) { |
+ function_queue_(new BackgroundCompilationQueue()) { |
*done_ = false; |
} |
@@ -1785,20 +1638,18 @@ void BackgroundCompiler::Run() { |
HANDLESCOPE(thread); |
Function& function = Function::Handle(zone); |
function = function_queue()->PeekFunction(); |
- BackgroundCompilationResult result; |
while (running_ && !function.IsNull()) { |
- result.Init(); |
const Error& error = Error::Handle(zone, |
Compiler::CompileOptimizedFunction(thread, |
function, |
- Compiler::kNoOSRDeoptId, |
- &result)); |
+ Compiler::kNoOSRDeoptId)); |
// TODO(srdjan): We do not expect errors while compiling optimized |
// code, any errors should have been caught when compiling |
// unoptimized code. Any issues while optimizing are flagged by |
// making the result invalid. |
ASSERT(error.IsNull()); |
- AddResult(result); |
+ QueueElement* qelem = function_queue()->Remove(); |
+ delete qelem; |
function = function_queue()->PeekFunction(); |
} |
} |
@@ -1821,20 +1672,6 @@ void BackgroundCompiler::Run() { |
} |
-// Use to first queue element to form the result element. |
-void BackgroundCompiler::AddResult(const BackgroundCompilationResult& result) { |
- ASSERT(!Thread::Current()->IsMutatorThread()); |
- MonitorLocker ml(queue_monitor_); |
- // Reuse the input QueueElement to return the result. |
- QueueElement* qelem = function_queue()->Remove(); |
- // Always add result, even if it is invalid, since the queue element is |
- // deleted in the mutator thread and potential field based deoptimizations |
- // (carried in the result) still must be done. |
- qelem->SetFromResult(result); |
- result_queue()->Add(qelem); |
-} |
- |
- |
void BackgroundCompiler::CompileOptimized(const Function& function) { |
ASSERT(Thread::Current()->IsMutatorThread()); |
MonitorLocker ml(queue_monitor_); |
@@ -1847,64 +1684,8 @@ void BackgroundCompiler::CompileOptimized(const Function& function) { |
} |
-void BackgroundCompiler::InstallGeneratedCode() { |
- ASSERT(Thread::Current()->IsMutatorThread()); |
- MonitorLocker ml(queue_monitor_); |
- Function& function = Function::Handle(); |
- while (result_queue()->Peek() != NULL) { |
- BackgroundCompilationResult result; |
- QueueElement* qelem = result_queue()->Remove(); |
- ASSERT(qelem != NULL); |
- result.SetFromQElement(qelem); |
- delete qelem; |
- |
- const Code& code = result.result_code(); |
- function ^= code.owner(); |
- Field& field = Field::Handle(); |
- // Always execute necessary deoptimizations, even if the result is invalid. |
- for (intptr_t i = 0; i < result.deoptimize_dependent_fields().Length(); |
- i++) { |
- field ^= result.deoptimize_dependent_fields().At(i); |
- field.DeoptimizeDependentCode(); |
- } |
- if (result.IsValid()) { |
- function.InstallOptimizedCode(result.result_code(), false /* not OSR */); |
- if (FLAG_trace_compiler) { |
- THR_Print("Installing optimized code for %s\n", |
- function.ToQualifiedCString()); |
- } |
- // Install leaf classes and fields dependencies. |
- Class& cls = Class::Handle(); |
- for (intptr_t i = 0; i < result.leaf_classes().Length(); i++) { |
- cls ^= result.leaf_classes().At(i); |
- cls.RegisterCHACode(code); |
- } |
- for (intptr_t i = 0; i < result.guarded_fields().Length(); i++) { |
- field ^= result.guarded_fields().At(i); |
- field.RegisterDependentCode(code); |
- } |
- } else if (FLAG_trace_compiler) { |
- THR_Print("Drop code generated in the background compiler:\n"); |
- result.PrintValidity(); |
- } |
- if (function.usage_counter() < 0) { |
- // Reset to 0 so that it can be recompiled if needed. |
- function.set_usage_counter(0); |
- } |
- if (result.IsValid() && |
- FLAG_disassemble_optimized && |
- FlowGraphPrinter::ShouldPrint(function)) { |
- THR_Print("*** BEGIN CODE\n"); |
- DisassembleCode(function, true); |
- THR_Print("*** END CODE\n"); |
- } |
- } |
-} |
- |
- |
void BackgroundCompiler::VisitPointers(ObjectPointerVisitor* visitor) { |
function_queue_->VisitObjectPointers(visitor); |
- result_queue_->VisitObjectPointers(visitor); |
} |
@@ -1914,7 +1695,6 @@ void BackgroundCompiler::Stop(BackgroundCompiler* task) { |
return; |
} |
BackgroundCompilationQueue* function_queue = task->function_queue(); |
- BackgroundCompilationQueue* result_queue = task->result_queue(); |
Monitor* queue_monitor = task->queue_monitor_; |
Monitor* done_monitor = task->done_monitor_; |
@@ -1931,14 +1711,15 @@ void BackgroundCompiler::Stop(BackgroundCompiler* task) { |
{ |
MonitorLocker ml_done(done_monitor); |
while (!(*task_done)) { |
- ml_done.Wait(); |
+ // In case that the compiler is waiting for safepoint. |
+ Isolate::Current()->thread_registry()->CheckSafepoint(); |
+ ml_done.Wait(1); |
} |
} |
delete task_done; |
delete done_monitor; |
delete queue_monitor; |
delete function_queue; |
- delete result_queue; |
Isolate::Current()->set_background_compiler(NULL); |
} |