Verify the symbol table contents before and after all
GCs (not just mark-compacts) and make the mark-compact shortcutting of cons-strings identical to the scavenge version. Review URL: http://codereview.chromium.org/67125 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1699 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
850d5ed380
commit
bca37da6af
37
src/heap.cc
37
src/heap.cc
@ -374,9 +374,34 @@ void Heap::PerformScavenge() {
|
||||
}
|
||||
|
||||
|
||||
static void VerifySymbolTable() {
|
||||
#ifdef DEBUG
|
||||
// Helper class for verifying the symbol table.
|
||||
class SymbolTableVerifier : public ObjectVisitor {
|
||||
public:
|
||||
SymbolTableVerifier() { }
|
||||
void VisitPointers(Object** start, Object** end) {
|
||||
// Visit all HeapObject pointers in [start, end).
|
||||
for (Object** p = start; p < end; p++) {
|
||||
if ((*p)->IsHeapObject()) {
|
||||
// Check that the symbol is actually a symbol.
|
||||
ASSERT((*p)->IsNull() || (*p)->IsUndefined() || (*p)->IsSymbol());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SymbolTableVerifier verifier;
|
||||
SymbolTable* symbol_table = SymbolTable::cast(Heap::symbol_table());
|
||||
symbol_table->IterateElements(&verifier);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
|
||||
void Heap::PerformGarbageCollection(AllocationSpace space,
|
||||
GarbageCollector collector,
|
||||
GCTracer* tracer) {
|
||||
VerifySymbolTable();
|
||||
if (collector == MARK_COMPACTOR && global_gc_prologue_callback_) {
|
||||
ASSERT(!allocation_allowed_);
|
||||
global_gc_prologue_callback_();
|
||||
@ -421,6 +446,7 @@ void Heap::PerformGarbageCollection(AllocationSpace space,
|
||||
ASSERT(!allocation_allowed_);
|
||||
global_gc_epilogue_callback_();
|
||||
}
|
||||
VerifySymbolTable();
|
||||
}
|
||||
|
||||
|
||||
@ -813,18 +839,9 @@ void Heap::ScavengeObject(HeapObject** p, HeapObject* object) {
|
||||
|
||||
|
||||
static inline bool IsShortcutCandidate(HeapObject* object, Map* map) {
|
||||
// A ConsString with an empty string as the right side is a
|
||||
// candidate for being shortcut by the scavenger unless it is a
|
||||
// symbol. It's not common to have non-flat symbols, so we do not
|
||||
// shortcut them thereby avoiding turning symbols into strings.
|
||||
ASSERT(kNotStringTag != 0 && kSymbolTag != 0);
|
||||
static const uint32_t kShortcutTypeMask =
|
||||
kIsNotStringMask |
|
||||
kIsSymbolMask |
|
||||
kStringRepresentationMask;
|
||||
ASSERT(object->map() == map);
|
||||
InstanceType type = map->instance_type();
|
||||
if ((type & kShortcutTypeMask) != kConsStringTag) return false;
|
||||
if ((type & kShortcutTypeMask) != kShortcutTypeTag) return false;
|
||||
ASSERT(object->IsString() && !object->IsSymbol());
|
||||
return ConsString::cast(object)->unchecked_second() == Heap::empty_string();
|
||||
}
|
||||
|
@ -96,24 +96,6 @@ void MarkCompactCollector::CollectGarbage() {
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
// Helper class for verifying the symbol table.
|
||||
class SymbolTableVerifier : public ObjectVisitor {
|
||||
public:
|
||||
SymbolTableVerifier() { }
|
||||
void VisitPointers(Object** start, Object** end) {
|
||||
// Visit all HeapObject pointers in [start, end).
|
||||
for (Object** p = start; p < end; p++) {
|
||||
if ((*p)->IsHeapObject()) {
|
||||
// Check that the symbol is actually a symbol.
|
||||
ASSERT((*p)->IsNull() || (*p)->IsUndefined() || (*p)->IsSymbol());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif // DEBUG
|
||||
|
||||
|
||||
void MarkCompactCollector::Prepare(GCTracer* tracer) {
|
||||
// Rather than passing the tracer around we stash it in a static member
|
||||
// variable.
|
||||
@ -166,10 +148,6 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) {
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
SymbolTable* symbol_table = SymbolTable::cast(Heap::symbol_table());
|
||||
SymbolTableVerifier v;
|
||||
symbol_table->IterateElements(&v);
|
||||
|
||||
live_bytes_ = 0;
|
||||
live_young_objects_ = 0;
|
||||
live_old_pointer_objects_ = 0;
|
||||
@ -183,10 +161,6 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) {
|
||||
|
||||
void MarkCompactCollector::Finish() {
|
||||
#ifdef DEBUG
|
||||
SymbolTable* symbol_table = SymbolTable::cast(Heap::symbol_table());
|
||||
SymbolTableVerifier v;
|
||||
symbol_table->IterateElements(&v);
|
||||
|
||||
ASSERT(state_ == SWEEP_SPACES || state_ == REBUILD_RSETS);
|
||||
state_ = IDLE;
|
||||
#endif
|
||||
@ -246,13 +220,7 @@ static inline HeapObject* ShortCircuitConsString(Object** p) {
|
||||
MapWord map_word = object->map_word();
|
||||
map_word.ClearMark();
|
||||
InstanceType type = map_word.ToMap()->instance_type();
|
||||
if (type >= FIRST_NONSTRING_TYPE || (type & kIsSymbolMask) != 0) {
|
||||
return object;
|
||||
}
|
||||
|
||||
StringRepresentationTag rep =
|
||||
static_cast<StringRepresentationTag>(type & kStringRepresentationMask);
|
||||
if (rep != kConsStringTag) return object;
|
||||
if ((type & kShortcutTypeMask) != kShortcutTypeTag) return object;
|
||||
|
||||
Object* second = reinterpret_cast<ConsString*>(object)->unchecked_second();
|
||||
if (reinterpret_cast<String*>(second) != Heap::empty_string()) return object;
|
||||
|
@ -679,7 +679,7 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
|
||||
SmartPointer<uc16> smart_chars = this->ToWideCString();
|
||||
ASSERT(memcmp(*smart_chars,
|
||||
resource->data(),
|
||||
resource->length()*sizeof(**smart_chars)) == 0);
|
||||
resource->length() * sizeof(**smart_chars)) == 0);
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
@ -6304,7 +6304,7 @@ class SymbolKey : public HashTableKey {
|
||||
if (StringShape(string_).IsCons()) {
|
||||
ConsString* cons_string = ConsString::cast(string_);
|
||||
cons_string->TryFlatten();
|
||||
if (cons_string->second() == Heap::empty_string()) {
|
||||
if (cons_string->second()->length() == 0) {
|
||||
string_ = cons_string->first();
|
||||
}
|
||||
}
|
||||
@ -6312,6 +6312,7 @@ class SymbolKey : public HashTableKey {
|
||||
Map* map = Heap::SymbolMapForString(string_);
|
||||
if (map != NULL) {
|
||||
string_->set_map(map);
|
||||
ASSERT(string_->IsSymbol());
|
||||
return string_;
|
||||
}
|
||||
// Otherwise allocate a new symbol.
|
||||
|
@ -441,6 +441,20 @@ enum StringRepresentationTag {
|
||||
kExternalStringTag = 0x3
|
||||
};
|
||||
|
||||
|
||||
// A ConsString with an empty string as the right side is a candidate
|
||||
// for being shortcut by the garbage collector unless it is a
|
||||
// symbol. It's not common to have non-flat symbols, so we do not
|
||||
// shortcut them thereby avoiding turning symbols into strings. See
|
||||
// heap.cc and mark-compact.cc.
|
||||
STATIC_ASSERT(kNotStringTag != 0 && kSymbolTag != 0);
|
||||
const uint32_t kShortcutTypeMask =
|
||||
kIsNotStringMask |
|
||||
kIsSymbolMask |
|
||||
kStringRepresentationMask;
|
||||
const uint32_t kShortcutTypeTag = kConsStringTag;
|
||||
|
||||
|
||||
enum InstanceType {
|
||||
SHORT_SYMBOL_TYPE = kShortStringTag | kSymbolTag | kSeqStringTag,
|
||||
MEDIUM_SYMBOL_TYPE = kMediumStringTag | kSymbolTag | kSeqStringTag,
|
||||
|
Loading…
Reference in New Issue
Block a user