Commit 58ead42b authored by Dan Elphick's avatar Dan Elphick Committed by Commit Bot

[explicit isolates] Make IsKey and IsLive use ReadOnlyRoots

Converts the Shape functions IsKey and IsLive to take ReadOnlyRoots
rather Isolate. This allows HashTableBase::FindEntry and
ObjectHashTableBase::Lookup to also take ReadOnlyRoots rather than
Isolate.

Bug: v8:7786
Change-Id: I37efea1d20139f394d6365569438755cb8fc44c4
Reviewed-on: https://chromium-review.googlesource.com/1133391Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Dan Elphick <delphick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54390}
parent 770ace07
......@@ -5452,10 +5452,11 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
Handle<NameDictionary>(from->property_dictionary(), isolate());
Handle<FixedArray> key_indices =
NameDictionary::IterationIndices(properties);
ReadOnlyRoots roots(isolate());
for (int i = 0; i < key_indices->length(); i++) {
int key_index = Smi::ToInt(key_indices->get(i));
Object* raw_key = properties->KeyAt(key_index);
DCHECK(properties->IsKey(isolate(), raw_key));
DCHECK(properties->IsKey(roots, raw_key));
DCHECK(raw_key->IsName());
// If the property is already there we skip it.
Handle<Name> key(Name::cast(raw_key), isolate());
......
......@@ -651,9 +651,10 @@ uint32_t EstimateElementCount(Isolate* isolate, Handle<JSArray> array) {
case DICTIONARY_ELEMENTS: {
NumberDictionary* dictionary = NumberDictionary::cast(array->elements());
int capacity = dictionary->Capacity();
ReadOnlyRoots roots(isolate);
for (int i = 0; i < capacity; i++) {
Object* key = dictionary->KeyAt(i);
if (dictionary->IsKey(isolate, key)) {
if (dictionary->IsKey(roots, key)) {
element_count++;
}
}
......@@ -718,9 +719,10 @@ void CollectElementIndices(Isolate* isolate, Handle<JSObject> object,
DisallowHeapAllocation no_gc;
NumberDictionary* dict = NumberDictionary::cast(object->elements());
uint32_t capacity = dict->Capacity();
ReadOnlyRoots roots(isolate);
FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, j = 0, j, j < capacity, j++, {
Object* k = dict->KeyAt(j);
if (!dict->IsKey(isolate, k)) continue;
if (!dict->IsKey(roots, k)) continue;
DCHECK(k->IsNumber());
uint32_t index = static_cast<uint32_t>(k->Number());
if (index < range) {
......
......@@ -434,7 +434,8 @@ bool AccessInfoFactory::ComputePropertyAccessInfo(
isolate());
Handle<Cell> cell(
Cell::cast(module_namespace->module()->exports()->Lookup(
isolate(), name, Smi::ToInt(name->GetHash()))),
ReadOnlyRoots(isolate()), name,
Smi::ToInt(name->GetHash()))),
isolate());
if (cell->value()->IsTheHole(isolate())) {
// This module has not been fully initialized yet.
......
......@@ -1432,13 +1432,14 @@ class DictionaryElementsAccessor
CHECK(array->length()->ToArrayLength(&old_length));
{
DisallowHeapAllocation no_gc;
ReadOnlyRoots roots(isolate);
if (length < old_length) {
if (dict->requires_slow_elements()) {
// Find last non-deletable element in range of elements to be
// deleted and adjust range accordingly.
for (int entry = 0; entry < capacity; entry++) {
Object* index = dict->KeyAt(entry);
if (dict->IsKey(isolate, index)) {
if (dict->IsKey(roots, index)) {
uint32_t number = static_cast<uint32_t>(index->Number());
if (length <= number && number < old_length) {
PropertyDetails details = dict->DetailsAt(entry);
......@@ -1456,7 +1457,7 @@ class DictionaryElementsAccessor
int removed_entries = 0;
for (int entry = 0; entry < capacity; entry++) {
Object* index = dict->KeyAt(entry);
if (dict->IsKey(isolate, index)) {
if (dict->IsKey(roots, index)) {
uint32_t number = static_cast<uint32_t>(index->Number());
if (length <= number && number < old_length) {
dict->ClearEntry(entry);
......@@ -1497,9 +1498,10 @@ class DictionaryElementsAccessor
Handle<NumberDictionary> source_dict(
NumberDictionary::cast(receiver->elements()), isolate);
int entry_count = source_dict->Capacity();
ReadOnlyRoots roots(isolate);
for (int i = 0; i < entry_count; i++) {
Object* key = source_dict->KeyAt(i);
if (!source_dict->ToKey(isolate, i, &key)) continue;
if (!source_dict->ToKey(roots, i, &key)) continue;
uint64_t key_value = NumberToInt64(key);
if (key_value >= start && key_value < end) {
Handle<NumberDictionary> dest_dict(
......@@ -1528,10 +1530,10 @@ class DictionaryElementsAccessor
NumberDictionary* dict = NumberDictionary::cast(backing_store);
if (!dict->requires_slow_elements()) return false;
int capacity = dict->Capacity();
Isolate* isolate = holder->GetIsolate();
ReadOnlyRoots roots = holder->GetReadOnlyRoots();
for (int i = 0; i < capacity; i++) {
Object* key = dict->KeyAt(i);
if (!dict->IsKey(isolate, key)) continue;
if (!dict->IsKey(roots, key)) continue;
PropertyDetails details = dict->DetailsAt(i);
if (details.kind() == kAccessor) return true;
}
......@@ -1644,7 +1646,7 @@ class DictionaryElementsAccessor
int entry, PropertyFilter filter) {
DisallowHeapAllocation no_gc;
Object* raw_key = dictionary->KeyAt(entry);
if (!dictionary->IsKey(isolate, raw_key)) return kMaxUInt32;
if (!dictionary->IsKey(ReadOnlyRoots(isolate), raw_key)) return kMaxUInt32;
return FilterKey(dictionary, entry, raw_key, filter);
}
......@@ -1660,9 +1662,10 @@ class DictionaryElementsAccessor
GetMaxNumberOfEntries(*object, *backing_store));
int insertion_index = 0;
PropertyFilter filter = keys->filter();
ReadOnlyRoots roots(isolate);
for (int i = 0; i < capacity; i++) {
Object* raw_key = dictionary->KeyAt(i);
if (!dictionary->IsKey(isolate, raw_key)) continue;
if (!dictionary->IsKey(roots, raw_key)) continue;
uint32_t key = FilterKey(dictionary, i, raw_key, filter);
if (key == kMaxUInt32) {
keys->AddShadowingKey(raw_key);
......@@ -1706,9 +1709,10 @@ class DictionaryElementsAccessor
Handle<NumberDictionary> dictionary(
NumberDictionary::cast(receiver->elements()), isolate);
int capacity = dictionary->Capacity();
ReadOnlyRoots roots(isolate);
for (int i = 0; i < capacity; i++) {
Object* k = dictionary->KeyAt(i);
if (!dictionary->IsKey(isolate, k)) continue;
if (!dictionary->IsKey(roots, k)) continue;
Object* value = dictionary->ValueAt(i);
DCHECK(!value->IsTheHole(isolate));
DCHECK(!value->IsAccessorPair());
......@@ -1901,7 +1905,7 @@ class DictionaryElementsAccessor
#if DEBUG
DCHECK_EQ(holder->map()->elements_kind(), DICTIONARY_ELEMENTS);
if (!FLAG_enable_slow_asserts) return;
Isolate* isolate = holder->GetIsolate();
ReadOnlyRoots roots = holder->GetReadOnlyRoots();
NumberDictionary* dictionary = NumberDictionary::cast(holder->elements());
// Validate the requires_slow_elements and max_number_key values.
int capacity = dictionary->Capacity();
......@@ -1909,7 +1913,7 @@ class DictionaryElementsAccessor
int max_key = 0;
for (int i = 0; i < capacity; ++i) {
Object* k;
if (!dictionary->ToKey(isolate, i, &k)) continue;
if (!dictionary->ToKey(roots, i, &k)) continue;
DCHECK_LE(0.0, k->Number());
if (k->Number() > NumberDictionary::kRequiresSlowElementsLimit) {
requires_slow_elements = true;
......
......@@ -804,7 +804,7 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
Handle<ObjectHashTable> exports(
Handle<JSModuleNamespace>::cast(holder)->module()->exports(),
isolate());
int entry = exports->FindEntry(isolate(), lookup->name(),
int entry = exports->FindEntry(roots, lookup->name(),
Smi::ToInt(lookup->name()->GetHash()));
// We found the accessor, so the entry must exist.
DCHECK_NE(entry, ObjectHashTable::kNotFound);
......
......@@ -3186,15 +3186,13 @@ PropertyCell* GlobalDictionary::CellAt(int entry) {
return PropertyCell::cast(KeyAt(entry));
}
bool GlobalDictionaryShape::IsLive(Isolate* isolate, Object* k) {
ReadOnlyRoots roots(isolate);
bool GlobalDictionaryShape::IsLive(ReadOnlyRoots roots, Object* k) {
DCHECK_NE(roots.the_hole_value(), k);
return k != roots.undefined_value();
}
bool GlobalDictionaryShape::IsKey(Isolate* isolate, Object* k) {
return IsLive(isolate, k) &&
!PropertyCell::cast(k)->value()->IsTheHole(isolate);
bool GlobalDictionaryShape::IsKey(ReadOnlyRoots roots, Object* k) {
return IsLive(roots, k) && !PropertyCell::cast(k)->value()->IsTheHole(roots);
}
Name* GlobalDictionary::NameAt(int entry) { return CellAt(entry)->name(); }
......
This diff is collapsed.
......@@ -215,8 +215,8 @@ class GlobalDictionaryShape : public NameDictionaryShape {
PropertyDetails value);
static inline Object* Unwrap(Object* key);
static inline bool IsKey(Isolate* isolate, Object* k);
static inline bool IsLive(Isolate* isolate, Object* key);
static inline bool IsKey(ReadOnlyRoots roots, Object* k);
static inline bool IsLive(ReadOnlyRoots roots, Object* key);
static inline int GetMapRootIndex();
};
......
......@@ -69,18 +69,17 @@ int HashTable<Derived, Shape>::FindEntry(Key key) {
template <typename Derived, typename Shape>
int HashTable<Derived, Shape>::FindEntry(Isolate* isolate, Key key) {
return FindEntry(isolate, key, Shape::Hash(isolate, key));
return FindEntry(ReadOnlyRoots(isolate), key, Shape::Hash(isolate, key));
}
// Find entry for key otherwise return kNotFound.
template <typename Derived, typename Shape>
int HashTable<Derived, Shape>::FindEntry(Isolate* isolate, Key key,
int HashTable<Derived, Shape>::FindEntry(ReadOnlyRoots roots, Key key,
int32_t hash) {
uint32_t capacity = Capacity();
uint32_t entry = FirstProbe(hash, capacity);
uint32_t count = 1;
// EnsureCapacity will guarantee the hash table is never full.
ReadOnlyRoots roots(isolate);
Object* undefined = roots.undefined_value();
Object* the_hole = roots.the_hole_value();
USE(the_hole);
......@@ -98,27 +97,26 @@ int HashTable<Derived, Shape>::FindEntry(Isolate* isolate, Key key,
}
template <typename Derived, typename Shape>
bool HashTable<Derived, Shape>::IsKey(Isolate* isolate, Object* k) {
return Shape::IsKey(isolate, k);
bool HashTable<Derived, Shape>::IsKey(ReadOnlyRoots roots, Object* k) {
return Shape::IsKey(roots, k);
}
template <typename Derived, typename Shape>
bool HashTable<Derived, Shape>::ToKey(Isolate* isolate, int entry,
bool HashTable<Derived, Shape>::ToKey(ReadOnlyRoots roots, int entry,
Object** out_k) {
Object* k = KeyAt(entry);
if (!IsKey(isolate, k)) return false;
if (!IsKey(roots, k)) return false;
*out_k = Shape::Unwrap(k);
return true;
}
template <typename KeyT>
bool BaseShape<KeyT>::IsKey(Isolate* isolate, Object* key) {
return IsLive(isolate, key);
bool BaseShape<KeyT>::IsKey(ReadOnlyRoots roots, Object* key) {
return IsLive(roots, key);
}
template <typename KeyT>
bool BaseShape<KeyT>::IsLive(Isolate* isolate, Object* k) {
ReadOnlyRoots roots(isolate);
bool BaseShape<KeyT>::IsLive(ReadOnlyRoots roots, Object* k) {
return k != roots.the_hole_value() && k != roots.undefined_value();
}
......@@ -136,13 +134,13 @@ const HashTable<Derived, Shape>* HashTable<Derived, Shape>::cast(
}
bool ObjectHashSet::Has(Isolate* isolate, Handle<Object> key, int32_t hash) {
return FindEntry(isolate, key, hash) != kNotFound;
return FindEntry(ReadOnlyRoots(isolate), key, hash) != kNotFound;
}
bool ObjectHashSet::Has(Isolate* isolate, Handle<Object> key) {
Object* hash = key->GetHash();
if (!hash->IsSmi()) return false;
return FindEntry(isolate, key, Smi::ToInt(hash)) != kNotFound;
return FindEntry(ReadOnlyRoots(isolate), key, Smi::ToInt(hash)) != kNotFound;
}
} // namespace internal
......
......@@ -58,8 +58,8 @@ class BaseShape {
static inline int GetMapRootIndex();
static const bool kNeedsHoleCheck = true;
static Object* Unwrap(Object* key) { return key; }
static inline bool IsKey(Isolate* isolate, Object* key);
static inline bool IsLive(Isolate* isolate, Object* key);
static inline bool IsKey(ReadOnlyRoots roots, Object* key);
static inline bool IsLive(ReadOnlyRoots roots, Object* key);
};
class V8_EXPORT_PRIVATE HashTableBase : public NON_EXPORTED_BASE(FixedArray) {
......@@ -145,7 +145,7 @@ class HashTable : public HashTableBase {
// Find entry for key otherwise return kNotFound.
inline int FindEntry(Key key);
inline int FindEntry(Isolate* isolate, Key key, int32_t hash);
inline int FindEntry(ReadOnlyRoots roots, Key key, int32_t hash);
int FindEntry(Isolate* isolate, Key key);
// Rehashes the table in-place.
......@@ -153,9 +153,9 @@ class HashTable : public HashTableBase {
// Tells whether k is a real key. The hole and undefined are not allowed
// as keys and can be used to indicate missing or deleted elements.
static bool IsKey(Isolate* isolate, Object* k);
static bool IsKey(ReadOnlyRoots roots, Object* k);
inline bool ToKey(Isolate* isolate, int entry, Object** out_k);
inline bool ToKey(ReadOnlyRoots roots, int entry, Object** out_k);
// Returns the key at entry.
Object* KeyAt(int entry) { return get(EntryToIndex(entry) + kEntryKeyIndex); }
......@@ -276,7 +276,7 @@ class ObjectHashTableBase : public HashTable<Derived, Shape> {
// returned in case the key is not present.
Object* Lookup(Handle<Object> key);
Object* Lookup(Handle<Object> key, int32_t hash);
Object* Lookup(Isolate* isolate, Handle<Object> key, int32_t hash);
Object* Lookup(ReadOnlyRoots roots, Handle<Object> key, int32_t hash);
// Returns the value at entry.
Object* ValueAt(int entry);
......
......@@ -778,12 +778,13 @@ void FetchStarExports(Isolate* isolate, Handle<Module> module, Zone* zone,
// TODO(neis): Only allocate more_exports if there are star exports.
// Maybe split special_exports into indirect_exports and star_exports.
ReadOnlyRoots roots(isolate);
Handle<FixedArray> special_exports(module->info()->special_exports(),
isolate);
for (int i = 0, n = special_exports->length(); i < n; ++i) {
Handle<ModuleInfoEntry> entry(
ModuleInfoEntry::cast(special_exports->get(i)), isolate);
if (!entry->export_name()->IsUndefined(isolate)) {
if (!entry->export_name()->IsUndefined(roots)) {
continue; // Indirect export.
}
......@@ -802,24 +803,24 @@ void FetchStarExports(Isolate* isolate, Handle<Module> module, Zone* zone,
isolate);
for (int i = 0, n = requested_exports->Capacity(); i < n; ++i) {
Object* key;
if (!requested_exports->ToKey(isolate, i, &key)) continue;
if (!requested_exports->ToKey(roots, i, &key)) continue;
Handle<String> name(String::cast(key), isolate);
if (name->Equals(ReadOnlyRoots(isolate).default_string())) continue;
if (!exports->Lookup(name)->IsTheHole(isolate)) continue;
if (name->Equals(roots.default_string())) continue;
if (!exports->Lookup(name)->IsTheHole(roots)) continue;
Handle<Cell> cell(Cell::cast(requested_exports->ValueAt(i)), isolate);
auto insert_result = more_exports.insert(std::make_pair(name, cell));
if (!insert_result.second) {
auto it = insert_result.first;
if (*it->second == *cell || it->second->IsUndefined(isolate)) {
if (*it->second == *cell || it->second->IsUndefined(roots)) {
// We already recorded this mapping before, or the name is already
// known to be ambiguous. In either case, there's nothing to do.
} else {
DCHECK(it->second->IsCell());
// Different star exports provide different cells for this name, hence
// mark the name as ambiguous.
it->second = isolate->factory()->undefined_value();
it->second = roots.undefined_value_handle();
}
}
}
......@@ -848,7 +849,8 @@ Handle<JSModuleNamespace> Module::GetModuleNamespace(Isolate* isolate,
Handle<JSModuleNamespace> Module::GetModuleNamespace(Isolate* isolate,
Handle<Module> module) {
Handle<HeapObject> object(module->module_namespace(), isolate);
if (!object->IsUndefined(isolate)) {
ReadOnlyRoots roots(isolate);
if (!object->IsUndefined(roots)) {
// Namespace object already exists.
return Handle<JSModuleNamespace>::cast(object);
}
......@@ -862,7 +864,7 @@ Handle<JSModuleNamespace> Module::GetModuleNamespace(Isolate* isolate,
names.reserve(exports->NumberOfElements());
for (int i = 0, n = exports->Capacity(); i < n; ++i) {
Object* key;
if (!exports->ToKey(isolate, i, &key)) continue;
if (!exports->ToKey(roots, i, &key)) continue;
names.push_back(handle(String::cast(key), isolate));
}
DCHECK_EQ(static_cast<int>(names.size()), exports->NumberOfElements());
......
......@@ -1431,8 +1431,9 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
GlobalDictionary* dictionary =
JSGlobalObject::cast(js_obj)->global_dictionary();
int length = dictionary->Capacity();
ReadOnlyRoots roots(isolate);
for (int i = 0; i < length; ++i) {
if (dictionary->IsKey(isolate, dictionary->KeyAt(i))) {
if (dictionary->IsKey(roots, dictionary->KeyAt(i))) {
PropertyCell* cell = dictionary->CellAt(i);
Name* name = cell->name();
Object* value = cell->value();
......@@ -1444,9 +1445,10 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
} else {
NameDictionary* dictionary = js_obj->property_dictionary();
int length = dictionary->Capacity();
ReadOnlyRoots roots(isolate);
for (int i = 0; i < length; ++i) {
Object* k = dictionary->KeyAt(i);
if (dictionary->IsKey(isolate, k)) {
if (dictionary->IsKey(roots, k)) {
Object* value = dictionary->ValueAt(i);
PropertyDetails details = dictionary->DetailsAt(i);
SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry,
......@@ -1476,14 +1478,14 @@ void V8HeapExplorer::ExtractAccessorPairProperty(JSObject* js_obj, int entry,
void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, int entry) {
Isolate* isolate = js_obj->GetIsolate();
ReadOnlyRoots roots = js_obj->GetReadOnlyRoots();
if (js_obj->HasObjectElements()) {
FixedArray* elements = FixedArray::cast(js_obj->elements());
int length = js_obj->IsJSArray()
? Smi::ToInt(JSArray::cast(js_obj)->length())
: elements->length();
for (int i = 0; i < length; ++i) {
if (!elements->get(i)->IsTheHole(isolate)) {
if (!elements->get(i)->IsTheHole(roots)) {
SetElementReference(js_obj, entry, i, elements->get(i));
}
}
......@@ -1492,7 +1494,7 @@ void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, int entry) {
int length = dictionary->Capacity();
for (int i = 0; i < length; ++i) {
Object* k = dictionary->KeyAt(i);
if (dictionary->IsKey(isolate, k)) {
if (dictionary->IsKey(roots, k)) {
DCHECK(k->IsNumber());
uint32_t index = static_cast<uint32_t>(k->Number());
SetElementReference(js_obj, entry, index, dictionary->ValueAt(i));
......
......@@ -228,9 +228,10 @@ bool SubstituteValues(Isolate* isolate, Handle<Dictionary> dictionary,
// Replace all indices with proper methods.
int capacity = dictionary->Capacity();
ReadOnlyRoots roots(isolate);
for (int i = 0; i < capacity; i++) {
Object* maybe_key = dictionary->KeyAt(i);
if (!Dictionary::IsKey(isolate, maybe_key)) continue;
if (!Dictionary::IsKey(roots, maybe_key)) continue;
if (install_name_accessor && *install_name_accessor &&
(maybe_key == *name_string)) {
*install_name_accessor = false;
......
......@@ -98,7 +98,7 @@ RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) {
#ifdef DEBUG
DCHECK(key->IsJSReceiver());
DCHECK(EphemeronHashTableShape::IsLive(isolate, *key));
DCHECK(EphemeronHashTableShape::IsLive(ReadOnlyRoots(isolate), *key));
Handle<EphemeronHashTable> table(
EphemeronHashTable::cast(weak_collection->table()), isolate);
// Should only be called when shrinking the table is necessary. See
......@@ -130,7 +130,7 @@ RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
#ifdef DEBUG
DCHECK(key->IsJSReceiver());
DCHECK(EphemeronHashTableShape::IsLive(isolate, *key));
DCHECK(EphemeronHashTableShape::IsLive(ReadOnlyRoots(isolate), *key));
Handle<EphemeronHashTable> table(
EphemeronHashTable::cast(weak_collection->table()), isolate);
// Should only be called when rehashing or resizing the table is necessary.
......
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