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:
kasperl@chromium.org 2009-04-14 12:00:56 +00:00
parent 850d5ed380
commit bca37da6af
4 changed files with 45 additions and 45 deletions

View File

@ -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();
}

View File

@ -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;

View File

@ -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.

View File

@ -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,