6c60285f23
This will deduplicate its entries. StoreBufferBlock might be contain the same large object dozens of times and without deduplication this will severely degrade GC performance by revisiting the same large object for every time it is recorded in the StoreBufferBlock. BUG=dart:10048 Review URL: https://codereview.chromium.org//14348026 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@21766 260f80e4-7a28-3924-810f-c04153c831b5
108 lines
2.3 KiB
C++
108 lines
2.3 KiB
C++
// Copyright (c) 2012, 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/store_buffer.h"
|
|
|
|
#include "platform/assert.h"
|
|
#include "vm/runtime_entry.h"
|
|
|
|
namespace dart {
|
|
|
|
DEFINE_LEAF_RUNTIME_ENTRY(void, StoreBufferBlockProcess, Isolate* isolate) {
|
|
isolate->store_buffer_block()->ProcessBuffer(isolate);
|
|
}
|
|
END_LEAF_RUNTIME_ENTRY
|
|
|
|
|
|
void StoreBufferBlock::ProcessBuffer() {
|
|
ProcessBuffer(Isolate::Current());
|
|
}
|
|
|
|
|
|
void StoreBufferBlock::ProcessBuffer(Isolate* isolate) {
|
|
isolate->store_buffer()->ProcessBlock(this);
|
|
}
|
|
|
|
|
|
bool StoreBufferBlock::Contains(uword pointer) {
|
|
for (int32_t i = 0; i < top_; i++) {
|
|
if (pointers_[i] == pointer) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
StoreBuffer::~StoreBuffer() {
|
|
DedupSet* current = dedup_sets_;
|
|
dedup_sets_ = NULL;
|
|
while (current != NULL) {
|
|
DedupSet* next = current->next();
|
|
delete current;
|
|
current = next;
|
|
}
|
|
}
|
|
|
|
|
|
void StoreBuffer::Reset() {
|
|
DedupSet* current = DedupSets();
|
|
while (current != NULL) {
|
|
DedupSet* next = current->next();
|
|
delete current;
|
|
current = next;
|
|
}
|
|
}
|
|
|
|
|
|
bool StoreBuffer::AddPointerInternal(uword address) {
|
|
ASSERT(dedup_sets_ != NULL);
|
|
ASSERT(Isolate::Current()->heap()->OldContains(address));
|
|
ASSERT((address & kSmiTagMask) != kSmiTag);
|
|
if (!dedup_sets_->set()->Add(address)) {
|
|
// Add a new DedupSet.
|
|
dedup_sets_ = new DedupSet(dedup_sets_);
|
|
count_++;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void StoreBuffer::AddPointer(uword address) {
|
|
if (AddPointerInternal(address)) {
|
|
// Had to create a new DedupSet.
|
|
CheckThreshold();
|
|
}
|
|
}
|
|
|
|
|
|
bool StoreBuffer::DrainBlock(StoreBufferBlock* block) {
|
|
const intptr_t old_count = count_;
|
|
intptr_t entries = block->Count();
|
|
for (intptr_t i = 0; i < entries; i++) {
|
|
AddPointerInternal(block->At(i));
|
|
}
|
|
block->Reset();
|
|
return (count_ > old_count);
|
|
}
|
|
|
|
|
|
void StoreBuffer::CheckThreshold() {
|
|
// Schedule an interrupt if we have run over the max number of DedupSets.
|
|
// TODO(iposva): Fix magic number.
|
|
if (count_ > 100) {
|
|
Isolate::Current()->ScheduleInterrupts(Isolate::kStoreBufferInterrupt);
|
|
}
|
|
}
|
|
|
|
|
|
void StoreBuffer::ProcessBlock(StoreBufferBlock* block) {
|
|
if (DrainBlock(block)) {
|
|
CheckThreshold();
|
|
}
|
|
}
|
|
|
|
} // namespace dart
|