Fix disabling of code flusher while marking.

This fixes a corner case when the code flusher is disabled while
incremental marking is running. The list of candidates needs to be
evicted to prevent list fragments without a head floating around.

R=ulan@chromium.org
BUG=chromium:159140

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12894 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mstarzinger@chromium.org 2012-11-08 10:26:50 +00:00
parent 63b5392717
commit 8e7ae24b40
3 changed files with 95 additions and 0 deletions

View File

@ -952,6 +952,34 @@ void CodeFlusher::EvictCandidate(JSFunction* function) {
}
void CodeFlusher::EvictJSFunctionCandidates() {
Object* undefined = isolate_->heap()->undefined_value();
JSFunction* candidate = jsfunction_candidates_head_;
JSFunction* next_candidate;
while (candidate != NULL) {
next_candidate = GetNextCandidate(candidate);
ClearNextCandidate(candidate, undefined);
candidate = next_candidate;
}
jsfunction_candidates_head_ = NULL;
}
void CodeFlusher::EvictSharedFunctionInfoCandidates() {
SharedFunctionInfo* candidate = shared_function_info_candidates_head_;
SharedFunctionInfo* next_candidate;
while (candidate != NULL) {
next_candidate = GetNextCandidate(candidate);
ClearNextCandidate(candidate);
candidate = next_candidate;
}
shared_function_info_candidates_head_ = NULL;
}
void CodeFlusher::IteratePointersToFromSpace(ObjectVisitor* v) {
Heap* heap = isolate_->heap();
@ -3629,6 +3657,7 @@ void MarkCompactCollector::EnableCodeFlushing(bool enable) {
code_flusher_ = new CodeFlusher(heap()->isolate());
} else {
if (code_flusher_ == NULL) return;
code_flusher_->EvictAllCandidates();
delete code_flusher_;
code_flusher_ = NULL;
}

View File

@ -441,11 +441,18 @@ class CodeFlusher {
ProcessJSFunctionCandidates();
}
void EvictAllCandidates() {
EvictJSFunctionCandidates();
EvictSharedFunctionInfoCandidates();
}
void IteratePointersToFromSpace(ObjectVisitor* v);
private:
void ProcessJSFunctionCandidates();
void ProcessSharedFunctionInfoCandidates();
void EvictJSFunctionCandidates();
void EvictSharedFunctionInfoCandidates();
static JSFunction** GetNextCandidateSlot(JSFunction* candidate) {
return reinterpret_cast<JSFunction**>(

View File

@ -1133,6 +1133,65 @@ TEST(TestCodeFlushingIncrementalScavenge) {
}
TEST(TestCodeFlushingIncrementalAbort) {
// If we do not flush code this test is invalid.
if (!FLAG_flush_code || !FLAG_flush_code_incrementally) return;
i::FLAG_allow_natives_syntax = true;
InitializeVM();
v8::HandleScope scope;
const char* source = "function foo() {"
" var x = 42;"
" var y = 42;"
" var z = x + y;"
"};"
"foo()";
Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo");
// This compile will add the code to the compilation cache.
{ v8::HandleScope scope;
CompileRun(source);
}
// Check function is compiled.
Object* func_value = Isolate::Current()->context()->global_object()->
GetProperty(*foo_name)->ToObjectChecked();
CHECK(func_value->IsJSFunction());
Handle<JSFunction> function(JSFunction::cast(func_value));
CHECK(function->shared()->is_compiled());
// The code will survive at least two GCs.
HEAP->CollectAllGarbage(Heap::kNoGCFlags);
HEAP->CollectAllGarbage(Heap::kNoGCFlags);
CHECK(function->shared()->is_compiled());
// Bump the code age so that flushing is triggered.
const int kAgingThreshold = 6;
function->shared()->set_code_age(kAgingThreshold);
// Simulate incremental marking so that the function is enqueued as
// code flushing candidate.
SimulateIncrementalMarking();
// Enable the debugger and add a breakpoint while incremental marking
// is running so that incremental marking aborts and code flushing is
// disabled.
int position = 0;
Handle<Object> breakpoint_object(Smi::FromInt(0));
ISOLATE->debug()->SetBreakPoint(function, breakpoint_object, &position);
ISOLATE->debug()->ClearAllBreakPoints();
// Force optimization now that code flushing is disabled.
{ v8::HandleScope scope;
CompileRun("%OptimizeFunctionOnNextCall(foo); foo();");
}
// Simulate one final GC to make sure the candidate queue is sane.
HEAP->CollectAllGarbage(Heap::kNoGCFlags);
CHECK(function->shared()->is_compiled() || !function->IsOptimized());
CHECK(function->is_compiled() || !function->IsOptimized());
}
// Count the number of native contexts in the weak list of native contexts.
int CountNativeContexts() {
int count = 0;