mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:58:29 +00:00
Reverts CLs related to the TLAB due to heap exhaustion.
Revert "Attempts to fix bugs introduced in 8b6fcf50e85d." This reverts commit7568e1f18e
. Revert "Changes calculation of Scavenger's UsedInWords" This reverts commit91470e7211
. Revert "Fixes the regression caused by 7568e1f18e." This reverts commit479db734e3
. BUG= Review-Url: https://codereview.chromium.org/2998663002 .
This commit is contained in:
parent
1d50f112dc
commit
91662ce579
|
@ -58,72 +58,23 @@ Heap::~Heap() {
|
|||
}
|
||||
}
|
||||
|
||||
void Heap::FillRemainingTLAB(Thread* thread) {
|
||||
uword start = thread->top();
|
||||
uword end = thread->end();
|
||||
ASSERT(end >= start);
|
||||
intptr_t size = end - start;
|
||||
ASSERT(Utils::IsAligned(size, kObjectAlignment));
|
||||
if (size >= kObjectAlignment) {
|
||||
FreeListElement::AsElement(start, size);
|
||||
ASSERT(RawObject::FromAddr(start)->Size() == size);
|
||||
ASSERT((start + size) == new_space_.top());
|
||||
}
|
||||
}
|
||||
|
||||
void Heap::AbandonRemainingTLAB(Thread* thread) {
|
||||
FillRemainingTLAB(thread);
|
||||
thread->set_top(0);
|
||||
thread->set_end(0);
|
||||
}
|
||||
|
||||
intptr_t Heap::CalculateTLABSize() {
|
||||
intptr_t size = new_space_.end() - new_space_.top();
|
||||
return Utils::RoundDown(size, kObjectAlignment);
|
||||
}
|
||||
|
||||
uword Heap::AllocateNew(intptr_t size) {
|
||||
ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0);
|
||||
// Currently, only the Dart thread may allocate in new space.
|
||||
isolate()->AssertCurrentThreadIsMutator();
|
||||
Thread* thread = Thread::Current();
|
||||
uword addr = new_space_.TryAllocateInTLAB(thread, size);
|
||||
if (addr != 0) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
intptr_t tlab_size = CalculateTLABSize();
|
||||
if ((tlab_size > 0) && (size > tlab_size)) {
|
||||
return AllocateOld(size, HeapPage::kData);
|
||||
}
|
||||
|
||||
AbandonRemainingTLAB(thread);
|
||||
if (tlab_size > 0) {
|
||||
uword tlab_top = new_space_.TryAllocateNewTLAB(thread, tlab_size);
|
||||
if (tlab_top != 0) {
|
||||
addr = new_space_.TryAllocateInTLAB(thread, size);
|
||||
ASSERT(addr != 0);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(!thread->HasActiveTLAB());
|
||||
|
||||
// This call to CollectGarbage might end up "reusing" a collection spawned
|
||||
// from a different thread and will be racing to allocate the requested
|
||||
// memory with other threads being released after the collection.
|
||||
CollectGarbage(kNew);
|
||||
tlab_size = CalculateTLABSize();
|
||||
uword tlab_top = new_space_.TryAllocateNewTLAB(thread, tlab_size);
|
||||
if (tlab_top != 0) {
|
||||
if (addr == 0) {
|
||||
// This call to CollectGarbage might end up "reusing" a collection spawned
|
||||
// from a different thread and will be racing to allocate the requested
|
||||
// memory with other threads being released after the collection.
|
||||
CollectGarbage(kNew);
|
||||
addr = new_space_.TryAllocateInTLAB(thread, size);
|
||||
// It is possible a GC doesn't clear enough space.
|
||||
// In that case, we must fall through and allocate into old space.
|
||||
if (addr != 0) {
|
||||
return addr;
|
||||
if (addr == 0) {
|
||||
return AllocateOld(size, HeapPage::kData);
|
||||
}
|
||||
}
|
||||
return AllocateOld(size, HeapPage::kData);
|
||||
return addr;
|
||||
}
|
||||
|
||||
uword Heap::AllocateOld(intptr_t size, HeapPage::PageType type) {
|
||||
|
@ -625,7 +576,7 @@ bool Heap::VerifyGC(MarkExpectation mark_expectation) const {
|
|||
StackZone stack_zone(Thread::Current());
|
||||
|
||||
// Change the new space's top_ with the more up-to-date thread's view of top_
|
||||
new_space_.MakeNewSpaceIterable();
|
||||
new_space_.FlushTLS();
|
||||
|
||||
ObjectSet* allocated_set =
|
||||
CreateAllocatedObjectSet(stack_zone.GetZone(), mark_expectation);
|
||||
|
|
|
@ -251,10 +251,6 @@ class Heap {
|
|||
old_space_.SetupImagePage(pointer, size, is_executable);
|
||||
}
|
||||
|
||||
intptr_t CalculateTLABSize();
|
||||
void FillRemainingTLAB(Thread* thread);
|
||||
void AbandonRemainingTLAB(Thread* thread);
|
||||
|
||||
private:
|
||||
class GCStats : public ValueObject {
|
||||
public:
|
||||
|
|
|
@ -2563,6 +2563,10 @@ Thread* Isolate::ScheduleThread(bool is_mutator, bool bypass_safepoint) {
|
|||
os_thread->set_thread(thread);
|
||||
if (is_mutator) {
|
||||
scheduled_mutator_thread_ = thread;
|
||||
if (this != Dart::vm_isolate()) {
|
||||
scheduled_mutator_thread_->set_top(heap()->new_space()->top());
|
||||
scheduled_mutator_thread_->set_end(heap()->new_space()->end());
|
||||
}
|
||||
}
|
||||
Thread::SetCurrent(thread);
|
||||
os_thread->EnableThreadInterrupts();
|
||||
|
@ -2601,6 +2605,12 @@ void Isolate::UnscheduleThread(Thread* thread,
|
|||
os_thread->set_thread(NULL);
|
||||
OSThread::SetCurrent(os_thread);
|
||||
if (is_mutator) {
|
||||
if (this != Dart::vm_isolate()) {
|
||||
heap()->new_space()->set_top(scheduled_mutator_thread_->top_);
|
||||
heap()->new_space()->set_end(scheduled_mutator_thread_->end_);
|
||||
}
|
||||
scheduled_mutator_thread_->top_ = 0;
|
||||
scheduled_mutator_thread_->end_ = 0;
|
||||
scheduled_mutator_thread_ = NULL;
|
||||
}
|
||||
thread->isolate_ = NULL;
|
||||
|
|
|
@ -394,6 +394,13 @@ SemiSpace* Scavenger::Prologue(Isolate* isolate, bool invoke_api_callbacks) {
|
|||
resolved_top_ = top_;
|
||||
end_ = to_->end();
|
||||
|
||||
// Throw out the old information about the from space
|
||||
if (isolate->IsMutatorThreadScheduled()) {
|
||||
Thread* mutator_thread = isolate->mutator_thread();
|
||||
mutator_thread->set_top(top_);
|
||||
mutator_thread->set_end(end_);
|
||||
}
|
||||
|
||||
return from;
|
||||
}
|
||||
|
||||
|
@ -403,10 +410,13 @@ void Scavenger::Epilogue(Isolate* isolate,
|
|||
// All objects in the to space have been copied from the from space at this
|
||||
// moment.
|
||||
|
||||
// Ensure the mutator thread will fail the next allocation. This will force
|
||||
// mutator to allocate a new TLAB
|
||||
Thread* mutator_thread = isolate->mutator_thread();
|
||||
ASSERT((mutator_thread == NULL) || (!mutator_thread->HasActiveTLAB()));
|
||||
// Ensure the mutator thread now has the up-to-date top_ and end_ of the
|
||||
// semispace
|
||||
if (isolate->IsMutatorThreadScheduled()) {
|
||||
Thread* thread = isolate->mutator_thread();
|
||||
thread->set_top(top_);
|
||||
thread->set_end(end_);
|
||||
}
|
||||
|
||||
double avg_frac = stats_history_.Get(0).PromoCandidatesSuccessFraction();
|
||||
if (stats_history_.Size() >= 2) {
|
||||
|
@ -712,22 +722,18 @@ void Scavenger::ProcessWeakReferences() {
|
|||
}
|
||||
}
|
||||
|
||||
void Scavenger::MakeNewSpaceIterable() const {
|
||||
void Scavenger::FlushTLS() const {
|
||||
ASSERT(heap_ != NULL);
|
||||
Thread* mutator_thread = heap_->isolate()->mutator_thread();
|
||||
if (mutator_thread != NULL && !scavenging_) {
|
||||
if (mutator_thread->HasActiveTLAB()) {
|
||||
ASSERT(mutator_thread->top() <=
|
||||
mutator_thread->heap()->new_space()->top());
|
||||
heap_->FillRemainingTLAB(mutator_thread);
|
||||
}
|
||||
if (heap_->isolate()->IsMutatorThreadScheduled()) {
|
||||
Thread* mutator_thread = heap_->isolate()->mutator_thread();
|
||||
mutator_thread->heap()->new_space()->set_top(mutator_thread->top());
|
||||
}
|
||||
}
|
||||
|
||||
void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
|
||||
ASSERT(Thread::Current()->IsAtSafepoint() ||
|
||||
(Thread::Current()->task_kind() == Thread::kMarkerTask));
|
||||
MakeNewSpaceIterable();
|
||||
FlushTLS();
|
||||
uword cur = FirstObjectStart();
|
||||
while (cur < top_) {
|
||||
RawObject* raw_obj = RawObject::FromAddr(cur);
|
||||
|
@ -738,7 +744,7 @@ void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
|
|||
void Scavenger::VisitObjects(ObjectVisitor* visitor) const {
|
||||
ASSERT(Thread::Current()->IsAtSafepoint() ||
|
||||
(Thread::Current()->task_kind() == Thread::kMarkerTask));
|
||||
MakeNewSpaceIterable();
|
||||
FlushTLS();
|
||||
uword cur = FirstObjectStart();
|
||||
while (cur < top_) {
|
||||
RawObject* raw_obj = RawObject::FromAddr(cur);
|
||||
|
@ -753,7 +759,7 @@ void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const {
|
|||
|
||||
RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const {
|
||||
ASSERT(!scavenging_);
|
||||
MakeNewSpaceIterable();
|
||||
FlushTLS();
|
||||
uword cur = FirstObjectStart();
|
||||
if (visitor->VisitRange(cur, top_)) {
|
||||
while (cur < top_) {
|
||||
|
@ -800,11 +806,6 @@ void Scavenger::Scavenge(bool invoke_api_callbacks) {
|
|||
int64_t post_safe_point = OS::GetCurrentMonotonicMicros();
|
||||
heap_->RecordTime(kSafePoint, post_safe_point - pre_safe_point);
|
||||
|
||||
Thread* mutator_thread = isolate->mutator_thread();
|
||||
if ((mutator_thread != NULL) && (mutator_thread->HasActiveTLAB())) {
|
||||
heap_->AbandonRemainingTLAB(mutator_thread);
|
||||
}
|
||||
|
||||
// TODO(koda): Make verification more compatible with concurrent sweep.
|
||||
if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) {
|
||||
OS::PrintErr("Verifying before Scavenge...");
|
||||
|
@ -916,6 +917,11 @@ void Scavenger::Evacuate() {
|
|||
// Forces the next scavenge to promote all the objects in the new space.
|
||||
survivor_end_ = top_;
|
||||
|
||||
if (heap_->isolate()->IsMutatorThreadScheduled()) {
|
||||
Thread* mutator_thread = heap_->isolate()->mutator_thread();
|
||||
survivor_end_ = mutator_thread->top();
|
||||
}
|
||||
|
||||
Scavenge();
|
||||
|
||||
// It is possible for objects to stay in the new space
|
||||
|
@ -923,17 +929,4 @@ void Scavenger::Evacuate() {
|
|||
ASSERT((UsedInWords() == 0) || failed_to_promote_);
|
||||
}
|
||||
|
||||
int64_t Scavenger::UsedInWords() const {
|
||||
int64_t free_space_in_tlab = 0;
|
||||
if (heap_->isolate()->IsMutatorThreadScheduled()) {
|
||||
Thread* mutator_thread = heap_->isolate()->mutator_thread();
|
||||
if (mutator_thread->HasActiveTLAB()) {
|
||||
free_space_in_tlab =
|
||||
(mutator_thread->end() - mutator_thread->top()) >> kWordSizeLog2;
|
||||
}
|
||||
}
|
||||
int64_t max_space_used = (top_ - FirstObjectStart()) >> kWordSizeLog2;
|
||||
return max_space_used - free_space_in_tlab;
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
|
|
@ -121,25 +121,6 @@ class Scavenger {
|
|||
|
||||
RawObject* FindObject(FindObjectVisitor* visitor) const;
|
||||
|
||||
uword TryAllocateNewTLAB(Thread* thread, intptr_t size) {
|
||||
ASSERT(Utils::IsAligned(size, kObjectAlignment));
|
||||
ASSERT(heap_ != Dart::vm_isolate()->heap());
|
||||
ASSERT(!scavenging_);
|
||||
uword result = top_;
|
||||
intptr_t remaining = end_ - top_;
|
||||
if (remaining < size) {
|
||||
return 0;
|
||||
}
|
||||
ASSERT(to_->Contains(result));
|
||||
ASSERT((result & kObjectAlignmentMask) == object_alignment_);
|
||||
top_ += size;
|
||||
ASSERT(to_->Contains(top_) || (top_ == to_->end()));
|
||||
ASSERT(result < top_);
|
||||
thread->set_top(result);
|
||||
thread->set_end(top_);
|
||||
return result;
|
||||
}
|
||||
|
||||
uword AllocateGC(intptr_t size) {
|
||||
ASSERT(Utils::IsAligned(size, kObjectAlignment));
|
||||
ASSERT(heap_ != Dart::vm_isolate()->heap());
|
||||
|
@ -153,7 +134,7 @@ class Scavenger {
|
|||
ASSERT(to_->Contains(result));
|
||||
ASSERT((result & kObjectAlignmentMask) == object_alignment_);
|
||||
top_ += size;
|
||||
ASSERT((to_->Contains(top_)) || (top_ == to_->end()));
|
||||
ASSERT(to_->Contains(top_) || (top_ == to_->end()));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -162,8 +143,6 @@ class Scavenger {
|
|||
ASSERT(heap_ != Dart::vm_isolate()->heap());
|
||||
ASSERT(thread->IsMutatorThread());
|
||||
ASSERT(thread->isolate()->IsMutatorThreadScheduled());
|
||||
ASSERT(thread->top() <= top_);
|
||||
ASSERT((thread->end() == 0) || (thread->end() == top_));
|
||||
#if defined(DEBUG)
|
||||
if (FLAG_gc_at_alloc) {
|
||||
ASSERT(!scavenging_);
|
||||
|
@ -180,7 +159,7 @@ class Scavenger {
|
|||
ASSERT(to_->Contains(result));
|
||||
ASSERT((result & kObjectAlignmentMask) == object_alignment_);
|
||||
top += size;
|
||||
ASSERT((to_->Contains(top)) || (top == to_->end()));
|
||||
ASSERT(to_->Contains(top) || (top == to_->end()));
|
||||
thread->set_top(top);
|
||||
return result;
|
||||
}
|
||||
|
@ -201,7 +180,9 @@ class Scavenger {
|
|||
end_ = value;
|
||||
}
|
||||
|
||||
int64_t UsedInWords() const;
|
||||
int64_t UsedInWords() const {
|
||||
return (top_ - FirstObjectStart()) >> kWordSizeLog2;
|
||||
}
|
||||
int64_t CapacityInWords() const { return to_->size_in_words(); }
|
||||
int64_t ExternalInWords() const { return external_size_ >> kWordSizeLog2; }
|
||||
SpaceUsage GetCurrentUsage() const {
|
||||
|
@ -234,8 +215,7 @@ class Scavenger {
|
|||
void AllocateExternal(intptr_t size);
|
||||
void FreeExternal(intptr_t size);
|
||||
|
||||
void MakeNewSpaceIterable() const;
|
||||
uword FirstObjectStart() const { return to_->start() | object_alignment_; }
|
||||
void FlushTLS() const;
|
||||
|
||||
private:
|
||||
// Ids for time and data records in Heap::GCStats.
|
||||
|
@ -254,6 +234,7 @@ class Scavenger {
|
|||
kToKBAfterStoreBuffer = 3
|
||||
};
|
||||
|
||||
uword FirstObjectStart() const { return to_->start() | object_alignment_; }
|
||||
SemiSpace* Prologue(Isolate* isolate, bool invoke_api_callbacks);
|
||||
void IterateStoreBuffers(Isolate* isolate, ScavengerVisitor* visitor);
|
||||
void IterateObjectIdTable(Isolate* isolate, ScavengerVisitor* visitor);
|
||||
|
|
|
@ -366,17 +366,17 @@ class Thread : public BaseThread {
|
|||
static intptr_t heap_offset() { return OFFSET_OF(Thread, heap_); }
|
||||
|
||||
void set_top(uword value) {
|
||||
ASSERT(heap_ != NULL);
|
||||
top_ = value;
|
||||
}
|
||||
void set_end(uword value) {
|
||||
ASSERT(heap_ != NULL);
|
||||
end_ = value;
|
||||
}
|
||||
|
||||
uword top() { return top_; }
|
||||
uword end() { return end_; }
|
||||
|
||||
bool HasActiveTLAB() { return end_ > 0; }
|
||||
|
||||
static intptr_t top_offset() { return OFFSET_OF(Thread, top_); }
|
||||
static intptr_t end_offset() { return OFFSET_OF(Thread, end_); }
|
||||
|
||||
|
|
Loading…
Reference in a new issue