Revert "Background finalization."

This reverts commit 082829a00b.

Review URL: https://codereview.chromium.org/2041373004 .
This commit is contained in:
Ryan Macnak 2016-06-07 17:21:06 -07:00
parent 6b9581e228
commit 7d9e75e0b6
11 changed files with 44 additions and 210 deletions

View file

@ -1206,28 +1206,6 @@ TEST_CASE(MalformedStringToUTF8) {
}
// Helper class to ensure new gen GC is triggered without any side effects.
// The normal call to CollectGarbage(Heap::kNew) could potentially trigger
// an old gen collection if there is a promotion failure and this could
// perturb the test.
class GCTestHelper : public AllStatic {
public:
static void CollectNewSpace(Heap::ApiCallbacks api_callbacks) {
bool invoke_api_callbacks = (api_callbacks == Heap::kInvokeApiCallbacks);
Isolate::Current()->heap()->new_space()->Scavenge(invoke_api_callbacks);
}
static void WaitForFinalizationTasks() {
Thread* thread = Thread::Current();
Heap* heap = thread->isolate()->heap();
MonitorLocker ml(heap->finalization_tasks_lock());
while (heap->finalization_tasks() > 0) {
ml.WaitWithSafepointCheck(thread);
}
}
};
static void ExternalStringCallbackFinalizer(void* peer) {
*static_cast<int*>(peer) *= 2;
}
@ -1264,11 +1242,9 @@ TEST_CASE(ExternalStringCallback) {
EXPECT_EQ(40, peer8);
EXPECT_EQ(41, peer16);
Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
GCTestHelper::WaitForFinalizationTasks();
EXPECT_EQ(40, peer8);
EXPECT_EQ(41, peer16);
Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
GCTestHelper::WaitForFinalizationTasks();
EXPECT_EQ(80, peer8);
EXPECT_EQ(82, peer16);
}
@ -2405,10 +2381,8 @@ TEST_CASE(ExternalTypedDataCallback) {
TransitionNativeToVM transition(thread);
EXPECT(peer == 0);
Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
GCTestHelper::WaitForFinalizationTasks();
EXPECT(peer == 0);
Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
GCTestHelper::WaitForFinalizationTasks();
EXPECT(peer == 42);
}
}
@ -2465,7 +2439,6 @@ TEST_CASE(Float32x4List) {
{
TransitionNativeToVM transition(thread);
Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
GCTestHelper::WaitForFinalizationTasks();
EXPECT(peer == 42);
}
}
@ -2628,6 +2601,19 @@ UNIT_TEST_CASE(AssignToPersistentHandle) {
}
// Helper class to ensure new gen GC is triggered without any side effects.
// The normal call to CollectGarbage(Heap::kNew) could potentially trigger
// an old gen collection if there is a promotion failure and this could
// perturb the test.
class GCTestHelper : public AllStatic {
public:
static void CollectNewSpace(Heap::ApiCallbacks api_callbacks) {
bool invoke_api_callbacks = (api_callbacks == Heap::kInvokeApiCallbacks);
Isolate::Current()->heap()->new_space()->Scavenge(invoke_api_callbacks);
}
};
static Dart_Handle AsHandle(Dart_PersistentHandle weak) {
return Dart_HandleFromPersistent(weak);
}
@ -2742,7 +2728,6 @@ TEST_CASE(WeakPersistentHandle) {
TransitionNativeToVM transition(thread);
// Garbage collect new space again.
GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
GCTestHelper::WaitForFinalizationTasks();
}
{
@ -2758,7 +2743,6 @@ TEST_CASE(WeakPersistentHandle) {
TransitionNativeToVM transition(thread);
// Garbage collect old space again.
Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
GCTestHelper::WaitForFinalizationTasks();
}
{
@ -2803,7 +2787,6 @@ TEST_CASE(WeakPersistentHandleCallback) {
Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
EXPECT(peer == 0);
GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
GCTestHelper::WaitForFinalizationTasks();
EXPECT(peer == 42);
}
}
@ -2830,7 +2813,6 @@ TEST_CASE(WeakPersistentHandleNoCallback) {
Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
EXPECT(peer == 0);
GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
GCTestHelper::WaitForFinalizationTasks();
EXPECT(peer == 0);
}
}
@ -2891,7 +2873,6 @@ TEST_CASE(WeakPersistentHandleExternalAllocationSize) {
// Collect weakly referenced string, and promote strongly referenced string.
GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
GCTestHelper::CollectNewSpace(Heap::kIgnoreApiCallbacks);
GCTestHelper::WaitForFinalizationTasks();
EXPECT(heap->ExternalInWords(Heap::kNew) == 0);
EXPECT(heap->ExternalInWords(Heap::kOld) == kWeak2ExternalSize / kWordSize);
}
@ -2902,7 +2883,6 @@ TEST_CASE(WeakPersistentHandleExternalAllocationSize) {
{
TransitionNativeToVM transition(thread);
Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
GCTestHelper::WaitForFinalizationTasks();
EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
}
}
@ -2948,7 +2928,6 @@ TEST_CASE(WeakPersistentHandleExternalAllocationSizeNewspaceGC) {
{
TransitionNativeToVM transition(thread);
Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
GCTestHelper::WaitForFinalizationTasks();
EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
}
}

View file

@ -1,56 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/dart_api_state.h"
#include "platform/assert.h"
#include "platform/utils.h"
#include "vm/heap.h"
#include "vm/isolate.h"
#include "vm/lockers.h"
#include "vm/thread.h"
#include "vm/timeline.h"
namespace dart {
BackgroundFinalizer::BackgroundFinalizer(Isolate* isolate,
FinalizationQueue* queue) :
isolate_(isolate),
queue_(queue) {
MonitorLocker ml(isolate->heap()->finalization_tasks_lock());
isolate->heap()->set_finalization_tasks(
isolate->heap()->finalization_tasks() + 1);
ml.Notify();
}
void BackgroundFinalizer::Run() {
bool result = Thread::EnterIsolateAsHelper(isolate_,
Thread::kFinalizerTask,
true /* bypass_safepoint */);
ASSERT(result);
{
TIMELINE_FUNCTION_GC_DURATION(Thread::Current(),
"BackgroundFinalization");
for (intptr_t i = 0; i < queue_->length(); i++) {
FinalizablePersistentHandle* handle = (*queue_)[i];
FinalizablePersistentHandle::Finalize(isolate_, handle);
}
delete queue_;
}
// Exit isolate cleanly *before* notifying it, to avoid shutdown race.
Thread::ExitIsolateAsHelper();
{
Heap* heap = isolate_->heap();
MonitorLocker ml(heap->finalization_tasks_lock());
heap->set_finalization_tasks(heap->finalization_tasks() - 1);
ml.Notify();
}
}
} // namespace dart

View file

@ -15,9 +15,8 @@
#include "vm/handles.h"
#include "vm/object.h"
#include "vm/os.h"
#include "vm/os_thread.h"
#include "vm/raw_object.h"
#include "vm/thread_pool.h"
#include "vm/os_thread.h"
#include "vm/visitor.h"
#include "vm/weak_table.h"
@ -25,25 +24,6 @@
namespace dart {
class FinalizablePersistentHandle;
typedef MallocGrowableArray<FinalizablePersistentHandle*> FinalizationQueue;
class BackgroundFinalizer : public ThreadPool::Task {
public:
BackgroundFinalizer(Isolate* isolate, FinalizationQueue* queue);
virtual ~BackgroundFinalizer() { }
void Run();
private:
Isolate* isolate_;
FinalizationQueue* queue_;
DISALLOW_IMPLICIT_CONSTRUCTORS(BackgroundFinalizer);
};
// Implementation of Zone support for very fast allocation of small chunks
// of memory. The chunks cannot be deallocated individually, but instead
// zones support deallocating all chunks in one fast operation when the
@ -247,14 +227,9 @@ class FinalizablePersistentHandle {
}
// Called when the referent becomes unreachable.
void UpdateUnreachable(Isolate* isolate, FinalizationQueue* queue) {
void UpdateUnreachable(Isolate* isolate) {
EnsureFreeExternal(isolate);
if (queue == NULL) {
Finalize(isolate, this);
} else {
MarkForFinalization();
queue->Add(this);
}
Finalize(isolate, this);
}
// Called when the referent has moved, potentially between generations.
@ -324,11 +299,6 @@ class FinalizablePersistentHandle {
callback_ = NULL;
}
void MarkForFinalization() {
raw_ = Object::null();
ASSERT(callback_ != NULL);
}
void set_raw(RawObject* raw) { raw_ = raw; }
void set_raw(const LocalHandle& ref) { raw_ = ref.raw(); }
void set_raw(const Object& object) { raw_ = object.raw(); }
@ -363,13 +333,10 @@ class FinalizablePersistentHandle {
Heap::kNew : Heap::kOld;
}
friend class BackgroundFinalizer;
RawObject* raw_;
void* peer_;
uword external_data_;
Dart_WeakPersistentHandleFinalizer callback_;
DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods.
DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandle);
};
@ -534,11 +501,9 @@ class FinalizablePersistentHandles
: Handles<kFinalizablePersistentHandleSizeInWords,
kFinalizablePersistentHandlesPerChunk,
kOffsetOfRawPtrInFinalizablePersistentHandle>(),
free_list_(NULL), mutex_(new Mutex()) { }
free_list_(NULL) { }
~FinalizablePersistentHandles() {
free_list_ = NULL;
delete mutex_;
mutex_ = NULL;
}
// Accessors.
@ -565,31 +530,25 @@ class FinalizablePersistentHandles
// by calling FreeHandle.
FinalizablePersistentHandle* AllocateHandle() {
FinalizablePersistentHandle* handle;
{
MutexLocker ml(mutex_);
if (free_list_ != NULL) {
handle = free_list_;
free_list_ = handle->Next();
handle->set_raw(Object::null());
return handle;
}
}
handle = reinterpret_cast<FinalizablePersistentHandle*>(
if (free_list_ != NULL) {
handle = free_list_;
free_list_ = handle->Next();
handle->set_raw(Object::null());
} else {
handle = reinterpret_cast<FinalizablePersistentHandle*>(
AllocateScopedHandle());
handle->Clear();
handle->Clear();
}
return handle;
}
void FreeHandle(FinalizablePersistentHandle* handle) {
MutexLocker ml(mutex_);
handle->FreeHandle(free_list());
set_free_list(handle);
}
// Validate if passed in handle is a Persistent Handle.
bool IsValidHandle(Dart_WeakPersistentHandle object) const {
MutexLocker ml(mutex_);
return IsValidScopedHandle(reinterpret_cast<uword>(object));
}
@ -600,7 +559,6 @@ class FinalizablePersistentHandles
private:
FinalizablePersistentHandle* free_list_;
Mutex* mutex_;
DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandles);
};

View file

@ -422,21 +422,19 @@ static bool IsUnreachable(const RawObject* raw_obj) {
class MarkingWeakVisitor : public HandleVisitor {
public:
MarkingWeakVisitor(Thread* thread, FinalizationQueue* queue) :
HandleVisitor(thread), queue_(queue) { }
MarkingWeakVisitor() : HandleVisitor(Thread::Current()) {
}
void VisitHandle(uword addr) {
FinalizablePersistentHandle* handle =
reinterpret_cast<FinalizablePersistentHandle*>(addr);
RawObject* raw_obj = handle->raw();
if (IsUnreachable(raw_obj)) {
handle->UpdateUnreachable(thread()->isolate(), queue_);
handle->UpdateUnreachable(thread()->isolate());
}
}
private:
FinalizationQueue* queue_;
DISALLOW_COPY_AND_ASSIGN(MarkingWeakVisitor);
};
@ -670,14 +668,8 @@ void GCMarker::MarkObjects(Isolate* isolate,
mark.DrainMarkingStack();
{
TIMELINE_FUNCTION_GC_DURATION(thread, "WeakHandleProcessing");
FinalizationQueue* queue = new FinalizationQueue();
MarkingWeakVisitor mark_weak(thread, queue);
MarkingWeakVisitor mark_weak;
IterateWeakRoots(isolate, &mark_weak);
if (queue->length() > 0) {
Dart::thread_pool()->Run(new BackgroundFinalizer(isolate, queue));
} else {
delete queue;
}
}
// All marking done; detach code, etc.
FinalizeResultsFrom(&mark);
@ -701,14 +693,8 @@ void GCMarker::MarkObjects(Isolate* isolate,
// Phase 2: Weak processing on main thread.
{
TIMELINE_FUNCTION_GC_DURATION(thread, "WeakHandleProcessing");
FinalizationQueue* queue = new FinalizationQueue();
MarkingWeakVisitor mark_weak(thread, queue);
MarkingWeakVisitor mark_weak;
IterateWeakRoots(isolate, &mark_weak);
if (queue->length() > 0) {
Dart::thread_pool()->Run(new BackgroundFinalizer(isolate, queue));
} else {
delete queue;
}
}
barrier.Sync();

View file

@ -35,8 +35,6 @@ Heap::Heap(Isolate* isolate,
old_space_(this, max_old_gen_words, max_external_words),
barrier_(new Monitor()),
barrier_done_(new Monitor()),
finalization_tasks_lock_(new Monitor()),
finalization_tasks_(0),
read_only_(false),
gc_new_space_in_progress_(false),
gc_old_space_in_progress_(false),
@ -54,7 +52,6 @@ Heap::Heap(Isolate* isolate,
Heap::~Heap() {
delete barrier_;
delete barrier_done_;
delete finalization_tasks_lock_;
for (int sel = 0;
sel < kNumWeakSelectors;

View file

@ -256,10 +256,6 @@ class Heap {
Monitor* barrier() const { return barrier_; }
Monitor* barrier_done() const { return barrier_done_; }
Monitor* finalization_tasks_lock() const { return finalization_tasks_lock_; }
intptr_t finalization_tasks() const { return finalization_tasks_; }
void set_finalization_tasks(intptr_t count) { finalization_tasks_ = count; }
bool ShouldPretenure(intptr_t class_id) const;
void SetupExternalPage(void* pointer, uword size, bool is_executable) {
@ -357,9 +353,6 @@ class Heap {
Monitor* barrier_;
Monitor* barrier_done_;
Monitor* finalization_tasks_lock_;
intptr_t finalization_tasks_;
// GC stats collection.
GCStats stats_;

View file

@ -1552,8 +1552,7 @@ class FinalizeWeakPersistentHandlesVisitor : public HandleVisitor {
void VisitHandle(uword addr) {
FinalizablePersistentHandle* handle =
reinterpret_cast<FinalizablePersistentHandle*>(addr);
FinalizationQueue* queue = NULL; // Finalize in the foreground.
handle->UpdateUnreachable(thread()->isolate(), queue);
handle->UpdateUnreachable(thread()->isolate());
}
private:
@ -1676,20 +1675,10 @@ void Isolate::Shutdown() {
if (heap_ != NULL) {
// Wait for any concurrent GC tasks to finish before shutting down.
// TODO(koda): Support faster sweeper shutdown (e.g., after current page).
{
PageSpace* old_space = heap_->old_space();
MonitorLocker ml(old_space->tasks_lock());
while (old_space->tasks() > 0) {
ml.Wait();
}
}
// Wait for background finalization to finish before shutting down.
{
MonitorLocker ml(heap_->finalization_tasks_lock());
while (heap_->finalization_tasks() > 0) {
ml.Wait();
}
PageSpace* old_space = heap_->old_space();
MonitorLocker ml(old_space->tasks_lock());
while (old_space->tasks() > 0) {
ml.Wait();
}
}

View file

@ -356,8 +356,8 @@ class Sample {
kTruncatedTraceBit = 5,
kClassAllocationSampleBit = 6,
kContinuationSampleBit = 7,
kThreadTaskBit = 8, // 5 bits.
kNextFreeBit = 13,
kThreadTaskBit = 8, // 4 bits.
kNextFreeBit = 12,
};
class HeadSampleBit : public BitField<uword, bool, kHeadSampleBit, 1> {};
class LeafFrameIsDart :
@ -373,7 +373,7 @@ class Sample {
class ContinuationSampleBit
: public BitField<uword, bool, kContinuationSampleBit, 1> {};
class ThreadTaskBit
: public BitField<uword, Thread::TaskKind, kThreadTaskBit, 5> {};
: public BitField<uword, Thread::TaskKind, kThreadTaskBit, 4> {};
int64_t timestamp_;
ThreadId tid_;

View file

@ -193,13 +193,10 @@ class ScavengerVisitor : public ObjectPointerVisitor {
class ScavengerWeakVisitor : public HandleVisitor {
public:
ScavengerWeakVisitor(Thread* thread,
Scavenger* scavenger,
FinalizationQueue* finalization_queue) :
HandleVisitor(thread),
scavenger_(scavenger),
queue_(finalization_queue) {
ASSERT(scavenger->heap_->isolate() == thread->isolate());
explicit ScavengerWeakVisitor(Scavenger* scavenger)
: HandleVisitor(Thread::Current()),
scavenger_(scavenger) {
ASSERT(scavenger->heap_->isolate() == Thread::Current()->isolate());
}
void VisitHandle(uword addr) {
@ -207,7 +204,7 @@ class ScavengerWeakVisitor : public HandleVisitor {
reinterpret_cast<FinalizablePersistentHandle*>(addr);
RawObject** p = handle->raw_addr();
if (scavenger_->IsUnreachable(p)) {
handle->UpdateUnreachable(thread()->isolate(), queue_);
handle->UpdateUnreachable(thread()->isolate());
} else {
handle->UpdateRelocated(thread()->isolate());
}
@ -215,7 +212,6 @@ class ScavengerWeakVisitor : public HandleVisitor {
private:
Scavenger* scavenger_;
FinalizationQueue* queue_;
DISALLOW_COPY_AND_ASSIGN(ScavengerWeakVisitor);
};
@ -816,14 +812,8 @@ void Scavenger::Scavenge(bool invoke_api_callbacks) {
int64_t middle = OS::GetCurrentTimeMicros();
{
TIMELINE_FUNCTION_GC_DURATION(thread, "WeakHandleProcessing");
FinalizationQueue* queue = new FinalizationQueue();
ScavengerWeakVisitor weak_visitor(thread, this, queue);
ScavengerWeakVisitor weak_visitor(this);
IterateWeakRoots(isolate, &weak_visitor);
if (queue->length() > 0) {
Dart::thread_pool()->Run(new BackgroundFinalizer(isolate, queue));
} else {
delete queue;
}
}
ProcessWeakReferences();
page_space->ReleaseDataLock();

View file

@ -145,7 +145,6 @@ class Thread : public BaseThread {
kCompilerTask = 0x2,
kSweeperTask = 0x4,
kMarkerTask = 0x8,
kFinalizerTask = 0x10,
};
~Thread();

View file

@ -136,7 +136,6 @@
'dart_api_impl_test.cc',
'dart_api_message.cc',
'dart_api_message.h',
'dart_api_state.cc',
'dart_api_state.h',
'dart_entry.cc',
'dart_entry.h',