Do not shortcut cons string symbols during garbage collection.
Attempt to flatten cons strings when converting them to symbols so that symbols will most often be flat strings. Review URL: http://codereview.chromium.org/1700 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@253 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
195a57b59b
commit
255b63ef50
@ -221,15 +221,15 @@ static MarkingStack marking_stack;
|
|||||||
|
|
||||||
|
|
||||||
inline HeapObject* ShortCircuitConsString(Object** p) {
|
inline HeapObject* ShortCircuitConsString(Object** p) {
|
||||||
// Optimization: If the heap object pointed to by p is a cons string whose
|
// Optimization: If the heap object pointed to by p is a non-symbol
|
||||||
// right substring is Heap::empty_string, update it in place to its left
|
// cons string whose right substring is Heap::empty_string, update
|
||||||
// substring. Return the updated value.
|
// it in place to its left substring. Return the updated value.
|
||||||
//
|
//
|
||||||
// Here we assume that if we change *p, we replace it with a heap object
|
// Here we assume that if we change *p, we replace it with a heap object
|
||||||
// (ie, the left substring of a cons string is always a heap object).
|
// (ie, the left substring of a cons string is always a heap object).
|
||||||
//
|
//
|
||||||
// The check performed is:
|
// The check performed is:
|
||||||
// object->IsConsString() &&
|
// object->IsConsString() && !object->IsSymbol() &&
|
||||||
// (ConsString::cast(object)->second() == Heap::empty_string())
|
// (ConsString::cast(object)->second() == Heap::empty_string())
|
||||||
// except the maps for the object and its possible substrings might be
|
// except the maps for the object and its possible substrings might be
|
||||||
// marked.
|
// marked.
|
||||||
@ -237,7 +237,9 @@ inline HeapObject* ShortCircuitConsString(Object** p) {
|
|||||||
MapWord map_word = object->map_word();
|
MapWord map_word = object->map_word();
|
||||||
map_word.ClearMark();
|
map_word.ClearMark();
|
||||||
InstanceType type = map_word.ToMap()->instance_type();
|
InstanceType type = map_word.ToMap()->instance_type();
|
||||||
if (type >= FIRST_NONSTRING_TYPE) return object;
|
if (type >= FIRST_NONSTRING_TYPE || (type & kIsSymbolMask) != 0) {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
StringRepresentationTag rep =
|
StringRepresentationTag rep =
|
||||||
static_cast<StringRepresentationTag>(type & kStringRepresentationMask);
|
static_cast<StringRepresentationTag>(type & kStringRepresentationMask);
|
||||||
|
@ -1124,8 +1124,7 @@ Object* JSObject::ReplaceConstantFunctionProperty(String* name,
|
|||||||
if (value->IsJSFunction()) {
|
if (value->IsJSFunction()) {
|
||||||
JSFunction* function = JSFunction::cast(value);
|
JSFunction* function = JSFunction::cast(value);
|
||||||
|
|
||||||
Object* new_map =
|
Object* new_map = map()->CopyDropTransitions();
|
||||||
map()->CopyDropTransitions();
|
|
||||||
if (new_map->IsFailure()) return new_map;
|
if (new_map->IsFailure()) return new_map;
|
||||||
set_map(Map::cast(new_map));
|
set_map(Map::cast(new_map));
|
||||||
|
|
||||||
@ -2646,7 +2645,7 @@ Object* DescriptorArray::CopyInsert(Descriptor* descriptor,
|
|||||||
int new_size = number_of_descriptors() - transitions - null_descriptors;
|
int new_size = number_of_descriptors() - transitions - null_descriptors;
|
||||||
|
|
||||||
// If key is in descriptor, we replace it in-place when filtering.
|
// If key is in descriptor, we replace it in-place when filtering.
|
||||||
int index = Search(descriptor->key());
|
int index = Search(descriptor->GetKey());
|
||||||
const bool inserting = (index == kNotFound);
|
const bool inserting = (index == kNotFound);
|
||||||
const bool replacing = !inserting;
|
const bool replacing = !inserting;
|
||||||
bool keep_enumeration_index = false;
|
bool keep_enumeration_index = false;
|
||||||
@ -2689,7 +2688,7 @@ Object* DescriptorArray::CopyInsert(Descriptor* descriptor,
|
|||||||
// and inserting or replacing a descriptor.
|
// and inserting or replacing a descriptor.
|
||||||
DescriptorWriter w(new_descriptors);
|
DescriptorWriter w(new_descriptors);
|
||||||
DescriptorReader r(this);
|
DescriptorReader r(this);
|
||||||
uint32_t descriptor_hash = descriptor->key()->Hash();
|
uint32_t descriptor_hash = descriptor->GetKey()->Hash();
|
||||||
|
|
||||||
for (; !r.eos(); r.advance()) {
|
for (; !r.eos(); r.advance()) {
|
||||||
if (r.GetKey()->Hash() > descriptor_hash ||
|
if (r.GetKey()->Hash() > descriptor_hash ||
|
||||||
@ -5385,6 +5384,15 @@ class SymbolKey : public HashTableKey {
|
|||||||
uint32_t Hash() { return string_->Hash(); }
|
uint32_t Hash() { return string_->Hash(); }
|
||||||
|
|
||||||
Object* GetObject() {
|
Object* GetObject() {
|
||||||
|
// If the string is a cons string, attempt to flatten it so that
|
||||||
|
// symbols will most often be flat strings.
|
||||||
|
if (string_->IsConsString()) {
|
||||||
|
ConsString* cons_string = ConsString::cast(string_);
|
||||||
|
cons_string->TryFlatten();
|
||||||
|
if (cons_string->second() == Heap::empty_string()) {
|
||||||
|
string_ = String::cast(cons_string->first());
|
||||||
|
}
|
||||||
|
}
|
||||||
// Transform string to symbol if possible.
|
// Transform string to symbol if possible.
|
||||||
Map* map = Heap::SymbolMapForString(string_);
|
Map* map = Heap::SymbolMapForString(string_);
|
||||||
if (map != NULL) {
|
if (map != NULL) {
|
||||||
|
@ -2556,7 +2556,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
|
|||||||
Consume(Token::STRING);
|
Consume(Token::STRING);
|
||||||
Handle<String> symbol =
|
Handle<String> symbol =
|
||||||
factory()->LookupSymbol(scanner_.literal_string(),
|
factory()->LookupSymbol(scanner_.literal_string(),
|
||||||
scanner_.literal_length());
|
scanner_.literal_length());
|
||||||
result = NEW(Literal(symbol));
|
result = NEW(Literal(symbol));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2708,8 +2708,8 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
|||||||
case Token::STRING: {
|
case Token::STRING: {
|
||||||
Consume(Token::STRING);
|
Consume(Token::STRING);
|
||||||
Handle<String> string =
|
Handle<String> string =
|
||||||
factory()->LookupSymbol(scanner_.literal_string(),
|
factory()->LookupSymbol(scanner_.literal_string(),
|
||||||
scanner_.literal_length());
|
scanner_.literal_length());
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
if (!string.is_null() && string->AsArrayIndex(&index)) {
|
if (!string.is_null() && string->AsArrayIndex(&index)) {
|
||||||
key = NewNumberLiteral(index);
|
key = NewNumberLiteral(index);
|
||||||
@ -3032,7 +3032,7 @@ Handle<String> Parser::ParseIdentifier(bool* ok) {
|
|||||||
Expect(Token::IDENTIFIER, ok);
|
Expect(Token::IDENTIFIER, ok);
|
||||||
if (!*ok) return Handle<String>();
|
if (!*ok) return Handle<String>();
|
||||||
return factory()->LookupSymbol(scanner_.literal_string(),
|
return factory()->LookupSymbol(scanner_.literal_string(),
|
||||||
scanner_.literal_length());
|
scanner_.literal_length());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function reads an identifier and determines whether or not it
|
// This function reads an identifier and determines whether or not it
|
||||||
|
@ -44,8 +44,6 @@ class Descriptor BASE_EMBEDDED {
|
|||||||
return Smi::cast(value)->value();
|
return Smi::cast(value)->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
String* key() { return key_; }
|
|
||||||
|
|
||||||
Object* KeyToSymbol() {
|
Object* KeyToSymbol() {
|
||||||
if (!key_->IsSymbol()) {
|
if (!key_->IsSymbol()) {
|
||||||
Object* result = Heap::LookupSymbol(key_);
|
Object* result = Heap::LookupSymbol(key_);
|
||||||
|
Loading…
Reference in New Issue
Block a user