Commit 144be2c4 authored by ishell's avatar ishell Committed by Commit bot

Starting using GlobalDictionary for global objects instead of NameDictionary.

Review URL: https://codereview.chromium.org/1165603002

Cr-Commit-Position: refs/heads/master@{#28737}
parent db18b778
......@@ -2874,6 +2874,30 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
}
}
}
} else if (from->IsGlobalObject()) {
Handle<GlobalDictionary> properties =
Handle<GlobalDictionary>(from->global_dictionary());
int capacity = properties->Capacity();
for (int i = 0; i < capacity; i++) {
Object* raw_key(properties->KeyAt(i));
if (properties->IsKey(raw_key)) {
DCHECK(raw_key->IsName());
// If the property is already there we skip it.
Handle<Name> key(Name::cast(raw_key));
LookupIterator it(to, key, LookupIterator::OWN_SKIP_INTERCEPTOR);
CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
if (it.IsFound()) continue;
// Set the property.
Handle<Object> value =
Handle<Object>(properties->ValueAt(i), isolate());
DCHECK(value->IsPropertyCell());
value = handle(PropertyCell::cast(*value)->value(), isolate());
if (value->IsTheHole()) continue;
PropertyDetails details = properties->DetailsAt(i);
DCHECK_EQ(kData, details.kind());
JSObject::AddProperty(to, key, value, details.attributes());
}
}
} else {
Handle<NameDictionary> properties =
Handle<NameDictionary>(from->property_dictionary());
......@@ -2891,10 +2915,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
Handle<Object> value = Handle<Object>(properties->ValueAt(i),
isolate());
DCHECK(!value->IsCell());
if (value->IsPropertyCell()) {
value = handle(PropertyCell::cast(*value)->value(), isolate());
}
if (value->IsTheHole()) continue;
DCHECK(!value->IsTheHole());
PropertyDetails details = properties->DetailsAt(i);
DCHECK_EQ(kData, details.kind());
JSObject::AddProperty(to, key, value, details.attributes());
......
......@@ -1583,8 +1583,8 @@ Handle<GlobalObject> Factory::NewGlobalObject(Handle<JSFunction> constructor) {
// Allocate a dictionary object for backing storage.
int at_least_space_for = map->NumberOfOwnDescriptors() * 2 + initial_size;
Handle<NameDictionary> dictionary =
NameDictionary::New(isolate(), at_least_space_for);
Handle<GlobalDictionary> dictionary =
GlobalDictionary::New(isolate(), at_least_space_for);
// The global object might be created from an object template with accessors.
// Fill these accessors into the dictionary.
......@@ -1599,7 +1599,7 @@ Handle<GlobalObject> Factory::NewGlobalObject(Handle<JSFunction> constructor) {
Handle<PropertyCell> cell = NewPropertyCell();
cell->set_value(descs->GetCallbacksObject(i));
// |dictionary| already contains enough space for all properties.
USE(NameDictionary::Add(dictionary, name, cell, d));
USE(GlobalDictionary::Add(dictionary, name, cell, d));
}
// Allocate the global object and initialize it with the backing store.
......
......@@ -1648,17 +1648,33 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
break;
}
}
} else if (js_obj->IsGlobalObject()) {
// We assume that global objects can only have slow properties.
GlobalDictionary* dictionary = js_obj->global_dictionary();
int length = dictionary->Capacity();
for (int i = 0; i < length; ++i) {
Object* k = dictionary->KeyAt(i);
if (dictionary->IsKey(k)) {
Object* target = dictionary->ValueAt(i);
DCHECK(target->IsPropertyCell());
Object* value = PropertyCell::cast(target)->value();
if (k == heap_->hidden_string()) {
TagObject(value, "(hidden properties)");
SetInternalReference(js_obj, entry, "hidden_properties", value);
continue;
}
PropertyDetails details = dictionary->DetailsAt(i);
SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry,
Name::cast(k), value);
}
}
} else {
NameDictionary* dictionary = js_obj->property_dictionary();
int length = dictionary->Capacity();
for (int i = 0; i < length; ++i) {
Object* k = dictionary->KeyAt(i);
if (dictionary->IsKey(k)) {
Object* target = dictionary->ValueAt(i);
// We assume that global objects can only have slow properties.
Object* value = target->IsPropertyCell()
? PropertyCell::cast(target)->value()
: target;
Object* value = dictionary->ValueAt(i);
if (k == heap_->hidden_string()) {
TagObject(value, "(hidden properties)");
SetInternalReference(js_obj, entry, "hidden_properties", value);
......
......@@ -64,16 +64,20 @@ LookupIterator::State LookupIterator::LookupInHolder(Map* const map,
number_ = accessor->GetIndexForKey(backing_store, index_);
if (number_ == kMaxUInt32) return NOT_FOUND;
property_details_ = accessor->GetDetails(backing_store, number_);
} else if (holder->IsGlobalObject()) {
GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary();
int number = dict->FindEntry(name_);
if (number == GlobalDictionary::kNotFound) return NOT_FOUND;
number_ = static_cast<uint32_t>(number);
DCHECK(dict->ValueAt(number_)->IsPropertyCell());
PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_));
if (cell->value()->IsTheHole()) return NOT_FOUND;
property_details_ = dict->DetailsAt(number_);
} else if (map->is_dictionary_map()) {
NameDictionary* dict = JSObject::cast(holder)->property_dictionary();
int number = dict->FindEntry(name_);
if (number == NameDictionary::kNotFound) return NOT_FOUND;
number_ = static_cast<uint32_t>(number);
if (holder->IsGlobalObject()) {
DCHECK(dict->ValueAt(number_)->IsPropertyCell());
PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_));
if (cell->value()->IsTheHole()) return NOT_FOUND;
}
property_details_ = dict->DetailsAt(number_);
} else {
DescriptorArray* descriptors = map->instance_descriptors();
......
......@@ -258,12 +258,12 @@ bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const {
Handle<Object> LookupIterator::FetchValue() const {
Object* result = NULL;
Handle<JSObject> holder = GetHolder<JSObject>();
if (holder_map_->is_dictionary_map()) {
if (holder_map_->IsGlobalObjectMap()) {
result = holder->global_dictionary()->ValueAt(number_);
DCHECK(result->IsPropertyCell());
result = PropertyCell::cast(result)->value();
} else if (holder_map_->is_dictionary_map()) {
result = holder->property_dictionary()->ValueAt(number_);
if (holder_map_->IsGlobalObjectMap()) {
DCHECK(result->IsPropertyCell());
result = PropertyCell::cast(result)->value();
}
} else if (property_details_.type() == v8::internal::DATA) {
FieldIndex field_index = FieldIndex::ForDescriptor(*holder_map_, number_);
return JSObject::FastPropertyAt(holder, property_details_.representation(),
......@@ -315,7 +315,7 @@ Handle<HeapType> LookupIterator::GetFieldType() const {
Handle<PropertyCell> LookupIterator::GetPropertyCell() const {
Handle<JSObject> holder = GetHolder<JSObject>();
Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
Object* value = global->property_dictionary()->ValueAt(dictionary_entry());
Object* value = global->global_dictionary()->ValueAt(dictionary_entry());
DCHECK(value->IsPropertyCell());
return handle(PropertyCell::cast(value));
}
......@@ -337,15 +337,15 @@ Handle<Object> LookupIterator::GetDataValue() const {
void LookupIterator::WriteDataValue(Handle<Object> value) {
DCHECK_EQ(DATA, state_);
Handle<JSObject> holder = GetHolder<JSObject>();
if (holder_map_->is_dictionary_map()) {
if (holder->IsGlobalObject()) {
Handle<GlobalDictionary> property_dictionary =
handle(holder->global_dictionary());
PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value,
property_details_);
} else if (holder_map_->is_dictionary_map()) {
Handle<NameDictionary> property_dictionary =
handle(holder->property_dictionary());
if (holder->IsGlobalObject()) {
PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value,
property_details_);
} else {
property_dictionary->ValueAtPut(dictionary_entry(), *value);
}
property_dictionary->ValueAtPut(dictionary_entry(), *value);
} else if (property_details_.type() == v8::internal::DATA) {
holder->WriteToField(descriptor_number(), *value);
} else {
......
......@@ -1064,6 +1064,11 @@ void JSObject::IncrementSpillStatistics(SpillInformation* info) {
info->number_of_objects_with_fast_properties_++;
info->number_of_fast_used_fields_ += map()->NextFreePropertyIndex();
info->number_of_fast_unused_fields_ += map()->unused_property_fields();
} else if (IsGlobalObject()) {
GlobalDictionary* dict = global_dictionary();
info->number_of_slow_used_properties_ += dict->NumberOfElements();
info->number_of_slow_unused_properties_ +=
dict->Capacity() - dict->NumberOfElements();
} else {
NameDictionary* dict = property_dictionary();
info->number_of_slow_used_properties_ += dict->NumberOfElements();
......
......@@ -6737,9 +6737,7 @@ bool JSObject::HasIndexedInterceptor() {
NameDictionary* JSObject::property_dictionary() {
DCHECK(!HasFastProperties());
// TODO(ishell): Uncomment, once all property_dictionary() usages for global
// objects are replaced with global_dictionary().
// DCHECK(!IsGlobalObject());
DCHECK(!IsGlobalObject());
return NameDictionary::cast(properties());
}
......
......@@ -255,6 +255,8 @@ void JSObject::PrintProperties(std::ostream& os) { // NOLINT
break;
}
}
} else if (IsGlobalObject()) {
global_dictionary()->Print(os);
} else {
property_dictionary()->Print(os);
}
......
This diff is collapsed.
......@@ -9945,11 +9945,11 @@ class PropertyCell : public HeapObject {
static PropertyCellType UpdatedType(Handle<PropertyCell> cell,
Handle<Object> value,
PropertyDetails details);
static void UpdateCell(Handle<NameDictionary> dictionary, int entry,
static void UpdateCell(Handle<GlobalDictionary> dictionary, int entry,
Handle<Object> value, PropertyDetails details);
static Handle<PropertyCell> InvalidateEntry(Handle<NameDictionary> dictionary,
int entry);
static Handle<PropertyCell> InvalidateEntry(
Handle<GlobalDictionary> dictionary, int entry);
static void SetValueWithInvalidation(Handle<PropertyCell> cell,
Handle<Object> new_value);
......
......@@ -592,19 +592,27 @@ RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
DisallowHeapAllocation no_allocation;
Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
Handle<Name> key = Handle<Name>::cast(key_obj);
if (!receiver->HasFastProperties()) {
if (receiver->IsGlobalObject()) {
// Attempt dictionary lookup.
NameDictionary* dictionary = receiver->property_dictionary();
GlobalDictionary* dictionary = receiver->global_dictionary();
int entry = dictionary->FindEntry(key);
if ((entry != NameDictionary::kNotFound) &&
if ((entry != GlobalDictionary::kNotFound) &&
(dictionary->DetailsAt(entry).type() == DATA)) {
Object* value = dictionary->ValueAt(entry);
if (!receiver->IsGlobalObject()) return value;
DCHECK(value->IsPropertyCell());
value = PropertyCell::cast(value)->value();
if (!value->IsTheHole()) return value;
// If value is the hole (meaning, absent) do the general lookup.
}
} else if (!receiver->HasFastProperties()) {
// Attempt dictionary lookup.
NameDictionary* dictionary = receiver->property_dictionary();
int entry = dictionary->FindEntry(key);
if ((entry != NameDictionary::kNotFound) &&
(dictionary->DetailsAt(entry).type() == DATA)) {
Object* value = dictionary->ValueAt(entry);
return value;
}
}
} else if (key_obj->IsSmi()) {
// JSObject without a name key. If the key is a Smi, check for a
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment