Commit 1f24c38b authored by ishell's avatar ishell Committed by Commit bot

GlobalDictionary now stores PropertyDetails in PropertyCells.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#28752}
parent 85ff7a04
......@@ -2892,12 +2892,11 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
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());
DCHECK(properties->ValueAt(i)->IsPropertyCell());
Handle<PropertyCell> cell(PropertyCell::cast(properties->ValueAt(i)));
Handle<Object> value(cell->value(), isolate());
if (value->IsTheHole()) continue;
PropertyDetails details = properties->DetailsAt(i);
PropertyDetails details = cell->property_details();
DCHECK_EQ(kData, details.kind());
JSObject::AddProperty(to, key, value, details.attributes());
}
......
......@@ -1655,15 +1655,15 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
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();
DCHECK(dictionary->ValueAt(i)->IsPropertyCell());
PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(i));
Object* value = cell->value();
if (k == heap_->hidden_string()) {
TagObject(value, "(hidden properties)");
SetInternalReference(js_obj, entry, "hidden_properties", value);
continue;
}
PropertyDetails details = dictionary->DetailsAt(i);
PropertyDetails details = cell->property_details();
SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry,
Name::cast(k), value);
}
......
......@@ -2914,6 +2914,7 @@ AllocationResult Heap::AllocatePropertyCell() {
PropertyCell* cell = PropertyCell::cast(result);
cell->set_dependent_code(DependentCode::cast(empty_fixed_array()),
SKIP_WRITE_BARRIER);
cell->set_property_details(PropertyDetails(Smi::FromInt(0)));
cell->set_value(the_hole_value());
return result;
}
......
......@@ -72,7 +72,7 @@ LookupIterator::State LookupIterator::LookupInHolder(Map* const map,
DCHECK(dict->ValueAt(number_)->IsPropertyCell());
PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_));
if (cell->value()->IsTheHole()) return NOT_FOUND;
property_details_ = dict->DetailsAt(number_);
property_details_ = cell->property_details();
} else if (map->is_dictionary_map()) {
NameDictionary* dict = JSObject::cast(holder)->property_dictionary();
int number = dict->FindEntry(name_);
......
......@@ -1930,6 +1930,7 @@ void Oddball::set_kind(byte value) {
ACCESSORS(Cell, value, Object, kValueOffset)
ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset)
ACCESSORS(PropertyCell, property_details_raw, Object, kDetailsOffset)
ACCESSORS(PropertyCell, value, Object, kValueOffset)
Object* WeakCell::value() const { return READ_FIELD(this, kValueOffset); }
......@@ -7124,7 +7125,7 @@ template<typename Derived, typename Shape, typename Key>
void Dictionary<Derived, Shape, Key>::SetEntry(int entry,
Handle<Object> key,
Handle<Object> value) {
SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
this->SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
}
......@@ -7133,13 +7134,40 @@ void Dictionary<Derived, Shape, Key>::SetEntry(int entry,
Handle<Object> key,
Handle<Object> value,
PropertyDetails details) {
Shape::SetEntry(static_cast<Derived*>(this), entry, key, value, details);
}
template <typename Key>
template <typename Dictionary>
void BaseDictionaryShape<Key>::SetEntry(Dictionary* dict, int entry,
Handle<Object> key,
Handle<Object> value,
PropertyDetails details) {
STATIC_ASSERT(Dictionary::kEntrySize == 3);
DCHECK(!key->IsName() || details.dictionary_index() > 0);
int index = dict->EntryToIndex(entry);
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = dict->GetWriteBarrierMode(no_gc);
dict->set(index, *key, mode);
dict->set(index + 1, *value, mode);
dict->set(index + 2, details.AsSmi());
}
template <typename Dictionary>
void GlobalDictionaryShape::SetEntry(Dictionary* dict, int entry,
Handle<Object> key, Handle<Object> value,
PropertyDetails details) {
STATIC_ASSERT(Dictionary::kEntrySize == 2);
DCHECK(!key->IsName() || details.dictionary_index() > 0);
int index = DerivedHashTable::EntryToIndex(entry);
DCHECK(value->IsPropertyCell());
int index = dict->EntryToIndex(entry);
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
FixedArray::set(index, *key, mode);
FixedArray::set(index+1, *value, mode);
FixedArray::set(index+2, details.AsSmi());
WriteBarrierMode mode = dict->GetWriteBarrierMode(no_gc);
dict->set(index, *key, mode);
dict->set(index + 1, *value, mode);
PropertyCell::cast(*value)->set_property_details(details);
}
......@@ -7210,6 +7238,27 @@ Handle<FixedArray> NameDictionary::DoGenerateNewEnumerationIndices(
}
template <typename Dictionary>
PropertyDetails GlobalDictionaryShape::DetailsAt(Dictionary* dict, int entry) {
DCHECK(entry >= 0); // Not found is -1, which is not caught by get().
Object* raw_value = dict->ValueAt(entry);
DCHECK(raw_value->IsPropertyCell());
PropertyCell* cell = PropertyCell::cast(raw_value);
return cell->property_details();
}
template <typename Dictionary>
void GlobalDictionaryShape::DetailsAtPut(Dictionary* dict, int entry,
PropertyDetails value) {
DCHECK(entry >= 0); // Not found is -1, which is not caught by get().
Object* raw_value = dict->ValueAt(entry);
DCHECK(raw_value->IsPropertyCell());
PropertyCell* cell = PropertyCell::cast(raw_value);
cell->set_property_details(value);
}
template <typename Dictionary>
bool GlobalDictionaryShape::IsDeleted(Dictionary* dict, int entry) {
DCHECK(dict->ValueAt(entry)->IsPropertyCell());
......
......@@ -1531,8 +1531,9 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
os << "PropertyCell for ";
HeapStringAllocator allocator;
StringStream accumulator(&allocator);
PropertyCell::cast(this)->value()->ShortPrint(&accumulator);
os << accumulator.ToCString().get();
PropertyCell* cell = PropertyCell::cast(this);
cell->value()->ShortPrint(&accumulator);
os << accumulator.ToCString().get() << " " << cell->property_details();
break;
}
case WEAK_CELL_TYPE: {
......@@ -1816,12 +1817,13 @@ void JSObject::AddSlowProperty(Handle<JSObject> object,
// If there's a cell there, just invalidate and set the property.
if (entry != GlobalDictionary::kNotFound) {
PropertyCell::UpdateCell(dict, entry, value, details);
// TODO(dcarney): move this to UpdateCell.
// TODO(ishell): move this to UpdateCell.
// Need to adjust the details.
int index = dict->NextEnumerationIndex();
dict->SetNextEnumerationIndex(index + 1);
details = dict->DetailsAt(entry).set_index(index);
dict->DetailsAtPut(entry, details);
PropertyCell* cell = PropertyCell::cast(dict->ValueAt(entry));
details = cell->property_details().set_index(index);
cell->set_property_details(details);
} else {
auto cell = isolate->factory()->NewPropertyCell();
......@@ -5422,9 +5424,9 @@ void JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
auto cell = PropertyCell::InvalidateEntry(dictionary, entry);
cell->set_value(isolate->heap()->the_hole_value());
// TODO(dcarney): InvalidateForDelete
dictionary->DetailsAtPut(entry, dictionary->DetailsAt(entry).set_cell_type(
PropertyCellType::kInvalidated));
// TODO(ishell): InvalidateForDelete
cell->set_property_details(
cell->property_details().set_cell_type(PropertyCellType::kInvalidated));
} else {
Handle<NameDictionary> dictionary(object->property_dictionary());
int entry = dictionary->FindEntry(name);
......@@ -15619,7 +15621,7 @@ void GlobalObject::InvalidatePropertyCell(Handle<GlobalObject> global,
}
// TODO(dcarney): rename to EnsureEmptyPropertyCell or something.
// TODO(ishell): rename to EnsureEmptyPropertyCell or something.
Handle<PropertyCell> GlobalObject::EnsurePropertyCell(
Handle<GlobalObject> global, Handle<Name> name) {
DCHECK(!global->HasFastProperties());
......@@ -15628,12 +15630,12 @@ Handle<PropertyCell> GlobalObject::EnsurePropertyCell(
Handle<PropertyCell> cell;
if (entry != GlobalDictionary::kNotFound) {
// This call should be idempotent.
DCHECK(dictionary->DetailsAt(entry).cell_type() ==
PropertyCellType::kUninitialized ||
dictionary->DetailsAt(entry).cell_type() ==
PropertyCellType::kInvalidated);
DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
cell = handle(PropertyCell::cast(dictionary->ValueAt(entry)));
DCHECK(cell->property_details().cell_type() ==
PropertyCellType::kUninitialized ||
cell->property_details().cell_type() ==
PropertyCellType::kInvalidated);
DCHECK(cell->value()->IsTheHole());
return cell;
}
......@@ -17305,10 +17307,10 @@ Handle<PropertyCell> PropertyCell::InvalidateEntry(
dictionary->ValueAtPut(entry, *new_cell);
bool is_the_hole = cell->value()->IsTheHole();
// Cell is officially mutable henceforth.
auto details = dictionary->DetailsAt(entry);
PropertyDetails details = cell->property_details();
details = details.set_cell_type(is_the_hole ? PropertyCellType::kInvalidated
: PropertyCellType::kMutable);
dictionary->DetailsAtPut(entry, details);
new_cell->set_property_details(details);
// Old cell is ready for invalidation.
if (is_the_hole) {
cell->set_value(isolate->heap()->undefined_value());
......@@ -17383,12 +17385,12 @@ void PropertyCell::UpdateCell(Handle<GlobalDictionary> dictionary, int entry,
DCHECK(!value->IsTheHole());
DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
const PropertyDetails original_details = dictionary->DetailsAt(entry);
const PropertyDetails original_details = cell->property_details();
// Data accesses could be cached in ics or optimized code.
bool invalidate =
original_details.kind() == kData && details.kind() == kAccessor;
int index = original_details.dictionary_index();
auto old_type = original_details.cell_type();
PropertyCellType old_type = original_details.cell_type();
// Preserve the enumeration index unless the property was deleted or never
// initialized.
if (cell->value()->IsTheHole()) {
......@@ -17400,12 +17402,12 @@ void PropertyCell::UpdateCell(Handle<GlobalDictionary> dictionary, int entry,
DCHECK(index > 0);
details = details.set_index(index);
auto new_type = UpdatedType(cell, value, original_details);
PropertyCellType new_type = UpdatedType(cell, value, original_details);
if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry);
// Install new property details and cell value.
details = details.set_cell_type(new_type);
dictionary->DetailsAtPut(entry, details);
cell->set_property_details(details);
cell->set_value(*value);
// Deopt when transitioning from a constant type.
......
......@@ -3468,6 +3468,11 @@ class HashTable : public HashTableBase {
static const int kCapacityOffset =
kHeaderSize + kCapacityIndex * kPointerSize;
// Returns the index for an entry (of the key)
static inline int EntryToIndex(int entry) {
return (entry * kEntrySize) + kElementsStartIndex;
}
protected:
friend class ObjectHashTable;
......@@ -3485,11 +3490,6 @@ class HashTable : public HashTableBase {
Key key,
PretenureFlag pretenure = NOT_TENURED);
// Returns the index for an entry (of the key)
static inline int EntryToIndex(int entry) {
return (entry * kEntrySize) + kElementsStartIndex;
}
// Sets the capacity of the hash table.
void SetCapacity(int capacity) {
// To scale a computed hash code to fit within the hash table, we
......@@ -3615,14 +3615,12 @@ class Dictionary: public HashTable<Derived, Shape, Key> {
// Returns the property details for the property at entry.
PropertyDetails DetailsAt(int entry) {
DCHECK(entry >= 0); // Not found is -1, which is not caught by get().
return PropertyDetails(
Smi::cast(this->get(Derived::EntryToIndex(entry) + 2)));
return Shape::DetailsAt(static_cast<Derived*>(this), entry);
}
// Set the details for entry.
void DetailsAtPut(int entry, PropertyDetails value) {
this->set(Derived::EntryToIndex(entry) + 2, value.AsSmi());
Shape::DetailsAtPut(static_cast<Derived*>(this), entry, value);
}
// Returns true if property at given entry is deleted.
......@@ -3754,10 +3752,29 @@ class NameDictionaryBase : public Dictionary<Derived, Shape, Handle<Name> > {
template <typename Key>
class BaseDictionaryShape : public BaseShape<Key> {
public:
template <typename Dictionary>
static inline PropertyDetails DetailsAt(Dictionary* dict, int entry) {
STATIC_ASSERT(Dictionary::kEntrySize == 3);
DCHECK(entry >= 0); // Not found is -1, which is not caught by get().
return PropertyDetails(
Smi::cast(dict->get(Dictionary::EntryToIndex(entry) + 2)));
}
template <typename Dictionary>
static inline void DetailsAtPut(Dictionary* dict, int entry,
PropertyDetails value) {
STATIC_ASSERT(Dictionary::kEntrySize == 3);
dict->set(Dictionary::EntryToIndex(entry) + 2, value.AsSmi());
}
template <typename Dictionary>
static bool IsDeleted(Dictionary* dict, int entry) {
return false;
}
template <typename Dictionary>
static inline void SetEntry(Dictionary* dict, int entry, Handle<Object> key,
Handle<Object> value, PropertyDetails details);
};
......@@ -3788,10 +3805,21 @@ class NameDictionary
class GlobalDictionaryShape : public NameDictionaryShape {
public:
static const int kEntrySize = 3; // Overrides NameDictionaryShape::kEntrySize
static const int kEntrySize = 2; // Overrides NameDictionaryShape::kEntrySize
template <typename Dictionary>
static inline PropertyDetails DetailsAt(Dictionary* dict, int entry);
template <typename Dictionary>
static inline void DetailsAtPut(Dictionary* dict, int entry,
PropertyDetails value);
template <typename Dictionary>
static bool IsDeleted(Dictionary* dict, int entry);
template <typename Dictionary>
static inline void SetEntry(Dictionary* dict, int entry, Handle<Object> key,
Handle<Object> value, PropertyDetails details);
};
......@@ -9890,12 +9918,22 @@ class Cell: public HeapObject {
class PropertyCell : public HeapObject {
public:
// [property_details]: details of the global property.
DECL_ACCESSORS(property_details_raw, Object)
// [value]: value of the global property.
DECL_ACCESSORS(value, Object)
// [dependent_code]: dependent code that depends on the type of the global
// property.
DECL_ACCESSORS(dependent_code, DependentCode)
PropertyDetails property_details() {
return PropertyDetails(Smi::cast(property_details_raw()));
}
void set_property_details(PropertyDetails details) {
set_property_details_raw(details.AsSmi());
}
PropertyCellConstantType GetConstantType();
// Computes the new type of the cell's contents for the given value, but
......@@ -9919,7 +9957,8 @@ class PropertyCell : public HeapObject {
DECLARE_VERIFIER(PropertyCell)
// Layout description.
static const int kValueOffset = HeapObject::kHeaderSize;
static const int kDetailsOffset = HeapObject::kHeaderSize;
static const int kValueOffset = kDetailsOffset + kPointerSize;
static const int kDependentCodeOffset = kValueOffset + kPointerSize;
static const int kSize = kDependentCodeOffset + kPointerSize;
......
......@@ -596,13 +596,14 @@ RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
// Attempt dictionary lookup.
GlobalDictionary* dictionary = receiver->global_dictionary();
int entry = dictionary->FindEntry(key);
if ((entry != GlobalDictionary::kNotFound) &&
(dictionary->DetailsAt(entry).type() == DATA)) {
Object* value = dictionary->ValueAt(entry);
DCHECK(value->IsPropertyCell());
value = PropertyCell::cast(value)->value();
if (!value->IsTheHole()) return value;
// If value is the hole (meaning, absent) do the general lookup.
if (entry != GlobalDictionary::kNotFound) {
DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
if (cell->property_details().type() == DATA) {
Object* value = cell->value();
if (!value->IsTheHole()) return value;
// If value is the hole (meaning, absent) do the general lookup.
}
}
} else if (!receiver->HasFastProperties()) {
// Attempt dictionary lookup.
......
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