Files
sdk/runtime/vm/store_buffer.cc
T
vegorov@google.com 6c60285f23 Drain StoreBufferBlock into store buffer instead of iterating over it directly.
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
2013-04-19 20:14:44 +00:00

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