Commit 5c46c24d authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[ubsan] Use Address type inside of IdentityMap and HandleBase

This refactors the innards of HandleBase and IdentityMap
to use Address instead of Object*, as part of the quest
to get rid of Object* entirely.

Bug: v8:3770
Change-Id: I82bd9547ef0d208b1e42636792e21c9064af4cea
Reviewed-on: https://chromium-review.googlesource.com/c/1285396
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56797}
parent aa302310
...@@ -65,6 +65,9 @@ class RootIndexMap { ...@@ -65,6 +65,9 @@ class RootIndexMap {
} }
return false; return false;
} }
bool Lookup(Address obj, RootIndex* out_root_list) {
return Lookup(reinterpret_cast<HeapObject*>(obj), out_root_list);
}
private: private:
HeapObjectToIndexHashMap* map_; HeapObjectToIndexHashMap* map_;
......
...@@ -12,22 +12,21 @@ ...@@ -12,22 +12,21 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
HandleBase::HandleBase(Object* object, Isolate* isolate) HandleBase::HandleBase(Address object, Isolate* isolate)
: location_(HandleScope::GetHandle(isolate, object)) {} : location_(HandleScope::GetHandle(isolate, object)) {}
template <typename T>
// Allocate a new handle for the object, do not canonicalize. // Allocate a new handle for the object, do not canonicalize.
template <typename T>
Handle<T> Handle<T>::New(T* object, Isolate* isolate) { Handle<T> Handle<T>::New(T* object, Isolate* isolate) {
return Handle( return Handle(reinterpret_cast<T**>(
reinterpret_cast<T**>(HandleScope::CreateHandle(isolate, object))); HandleScope::CreateHandle(isolate, reinterpret_cast<Address>(object))));
} }
template <typename T> template <typename T>
template <typename S> template <typename S>
const Handle<T> Handle<T>::cast(Handle<S> that) { const Handle<T> Handle<T>::cast(Handle<S> that) {
T::cast(*reinterpret_cast<T**>(that.location())); T::cast(*reinterpret_cast<T**>(that.location()));
return Handle<T>(reinterpret_cast<T**>(that.location_)); return Handle<T>(that.location_);
} }
HandleScope::HandleScope(Isolate* isolate) { HandleScope::HandleScope(Isolate* isolate) {
...@@ -39,7 +38,8 @@ HandleScope::HandleScope(Isolate* isolate) { ...@@ -39,7 +38,8 @@ HandleScope::HandleScope(Isolate* isolate) {
} }
template <typename T> template <typename T>
Handle<T>::Handle(T* object, Isolate* isolate) : HandleBase(object, isolate) {} Handle<T>::Handle(T* object, Isolate* isolate)
: HandleBase(reinterpret_cast<Address>(object), isolate) {}
template <typename T> template <typename T>
V8_INLINE Handle<T> handle(T* object, Isolate* isolate) { V8_INLINE Handle<T> handle(T* object, Isolate* isolate) {
...@@ -107,22 +107,7 @@ Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) { ...@@ -107,22 +107,7 @@ Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) {
return result; return result;
} }
Object** HandleScope::CreateHandle(Isolate* isolate, Object* value) { Address* HandleScope::CreateHandle(Isolate* isolate, Address value) {
DCHECK(AllowHandleAllocation::IsAllowed());
HandleScopeData* data = isolate->handle_scope_data();
Object** result = data->next;
if (result == data->limit) result = Extend(isolate);
// Update the current next field, set the value in the created
// handle, and return the result.
DCHECK(result < data->limit);
data->next = result + 1;
*result = value;
return result;
}
Address* HandleScope::CreateHandle(Isolate* isolate, Address value_address) {
DCHECK(AllowHandleAllocation::IsAllowed()); DCHECK(AllowHandleAllocation::IsAllowed());
HandleScopeData* data = isolate->handle_scope_data(); HandleScopeData* data = isolate->handle_scope_data();
Address* result = reinterpret_cast<Address*>(data->next); Address* result = reinterpret_cast<Address*>(data->next);
...@@ -135,11 +120,11 @@ Address* HandleScope::CreateHandle(Isolate* isolate, Address value_address) { ...@@ -135,11 +120,11 @@ Address* HandleScope::CreateHandle(Isolate* isolate, Address value_address) {
reinterpret_cast<Address>(data->limit)); reinterpret_cast<Address>(data->limit));
data->next = reinterpret_cast<Object**>(reinterpret_cast<Address>(result) + data->next = reinterpret_cast<Object**>(reinterpret_cast<Address>(result) +
sizeof(Address)); sizeof(Address));
*result = value_address; *result = value;
return result; return result;
} }
Object** HandleScope::GetHandle(Isolate* isolate, Object* value) { Address* HandleScope::GetHandle(Isolate* isolate, Address value) {
DCHECK(AllowHandleAllocation::IsAllowed()); DCHECK(AllowHandleAllocation::IsAllowed());
HandleScopeData* data = isolate->handle_scope_data(); HandleScopeData* data = isolate->handle_scope_data();
CanonicalHandleScope* canonical = data->canonical_scope; CanonicalHandleScope* canonical = data->canonical_scope;
......
...@@ -24,13 +24,14 @@ ASSERT_TRIVIALLY_COPYABLE(MaybeHandle<Object>); ...@@ -24,13 +24,14 @@ ASSERT_TRIVIALLY_COPYABLE(MaybeHandle<Object>);
#ifdef DEBUG #ifdef DEBUG
bool HandleBase::IsDereferenceAllowed(DereferenceCheckMode mode) const { bool HandleBase::IsDereferenceAllowed(DereferenceCheckMode mode) const {
DCHECK_NOT_NULL(location_); DCHECK_NOT_NULL(location_);
Object* object = *location_; Object* object = reinterpret_cast<Object*>(*location_);
if (object->IsSmi()) return true; if (object->IsSmi()) return true;
HeapObject* heap_object = HeapObject::cast(object); HeapObject* heap_object = HeapObject::cast(object);
Isolate* isolate; Isolate* isolate;
if (!Isolate::FromWritableHeapObject(heap_object, &isolate)) return true; if (!Isolate::FromWritableHeapObject(heap_object, &isolate)) return true;
RootIndex root_index; RootIndex root_index;
if (isolate->roots_table().IsRootHandleLocation(location_, &root_index) && if (isolate->roots_table().IsRootHandleLocation(
reinterpret_cast<Object**>(location_), &root_index) &&
RootsTable::IsImmortalImmovable(root_index)) { RootsTable::IsImmortalImmovable(root_index)) {
return true; return true;
} }
...@@ -41,7 +42,7 @@ bool HandleBase::IsDereferenceAllowed(DereferenceCheckMode mode) const { ...@@ -41,7 +42,7 @@ bool HandleBase::IsDereferenceAllowed(DereferenceCheckMode mode) const {
if (heap_object->IsCell()) return true; if (heap_object->IsCell()) return true;
if (heap_object->IsMap()) return true; if (heap_object->IsMap()) return true;
if (heap_object->IsInternalizedString()) return true; if (heap_object->IsInternalizedString()) return true;
return !isolate->IsDeferredHandle(location_); return !isolate->IsDeferredHandle(reinterpret_cast<Object**>(location_));
} }
return true; return true;
} }
...@@ -133,7 +134,7 @@ CanonicalHandleScope::CanonicalHandleScope(Isolate* isolate) ...@@ -133,7 +134,7 @@ CanonicalHandleScope::CanonicalHandleScope(Isolate* isolate)
prev_canonical_scope_ = handle_scope_data->canonical_scope; prev_canonical_scope_ = handle_scope_data->canonical_scope;
handle_scope_data->canonical_scope = this; handle_scope_data->canonical_scope = this;
root_index_map_ = new RootIndexMap(isolate); root_index_map_ = new RootIndexMap(isolate);
identity_map_ = new IdentityMap<Object**, ZoneAllocationPolicy>( identity_map_ = new IdentityMap<Address*, ZoneAllocationPolicy>(
isolate->heap(), ZoneAllocationPolicy(&zone_)); isolate->heap(), ZoneAllocationPolicy(&zone_));
canonical_level_ = handle_scope_data->level; canonical_level_ = handle_scope_data->level;
} }
...@@ -145,26 +146,25 @@ CanonicalHandleScope::~CanonicalHandleScope() { ...@@ -145,26 +146,25 @@ CanonicalHandleScope::~CanonicalHandleScope() {
isolate_->handle_scope_data()->canonical_scope = prev_canonical_scope_; isolate_->handle_scope_data()->canonical_scope = prev_canonical_scope_;
} }
Address* CanonicalHandleScope::Lookup(Address object) {
Object** CanonicalHandleScope::Lookup(Object* object) {
DCHECK_LE(canonical_level_, isolate_->handle_scope_data()->level); DCHECK_LE(canonical_level_, isolate_->handle_scope_data()->level);
if (isolate_->handle_scope_data()->level != canonical_level_) { if (isolate_->handle_scope_data()->level != canonical_level_) {
// We are in an inner handle scope. Do not canonicalize since we will leave // We are in an inner handle scope. Do not canonicalize since we will leave
// this handle scope while still being in the canonical scope. // this handle scope while still being in the canonical scope.
return HandleScope::CreateHandle(isolate_, object); return HandleScope::CreateHandle(isolate_, object);
} }
if (object->IsHeapObject()) { if (Internals::HasHeapObjectTag(object)) {
RootIndex root_index; RootIndex root_index;
if (root_index_map_->Lookup(HeapObject::cast(object), &root_index)) { if (root_index_map_->Lookup(object, &root_index)) {
return isolate_->root_handle(root_index).location(); return isolate_->root_handle(root_index).location_as_address_ptr();
} }
} }
Object*** entry = identity_map_->Get(object); Address** entry = identity_map_->Get(reinterpret_cast<Object*>(object));
if (*entry == nullptr) { if (*entry == nullptr) {
// Allocate new handle location. // Allocate new handle location.
*entry = HandleScope::CreateHandle(isolate_, object); *entry = HandleScope::CreateHandle(isolate_, object);
} }
return reinterpret_cast<Object**>(*entry); return *entry;
} }
......
...@@ -29,8 +29,10 @@ class Object; ...@@ -29,8 +29,10 @@ class Object;
// Base class for Handle instantiations. Don't use directly. // Base class for Handle instantiations. Don't use directly.
class HandleBase { class HandleBase {
public: public:
V8_INLINE explicit HandleBase(Object** location) : location_(location) {} V8_INLINE explicit HandleBase(Object** location)
V8_INLINE explicit HandleBase(Object* object, Isolate* isolate); : location_(reinterpret_cast<Address*>(location)) {}
V8_INLINE explicit HandleBase(Address* location) : location_(location) {}
V8_INLINE explicit HandleBase(Address object, Isolate* isolate);
// Check if this handle refers to the exact same object as the other handle. // Check if this handle refers to the exact same object as the other handle.
V8_INLINE bool is_identical_to(const HandleBase that) const { V8_INLINE bool is_identical_to(const HandleBase that) const {
...@@ -52,13 +54,13 @@ class HandleBase { ...@@ -52,13 +54,13 @@ class HandleBase {
protected: protected:
// Provides the C++ dereference operator. // Provides the C++ dereference operator.
V8_INLINE Object* operator*() const { V8_INLINE Address operator*() const {
SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK)); SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
return *location_; return *location_;
} }
// Returns the address to where the raw pointer is stored. // Returns the address to where the raw pointer is stored.
V8_INLINE Object** location() const { V8_INLINE Address* location() const {
SLOW_DCHECK(location_ == nullptr || SLOW_DCHECK(location_ == nullptr ||
IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK)); IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
return location_; return location_;
...@@ -74,7 +76,10 @@ class HandleBase { ...@@ -74,7 +76,10 @@ class HandleBase {
} }
#endif // DEBUG #endif // DEBUG
Object** location_; // This uses type Address* as opposed to a pointer type to a typed
// wrapper class, because it doesn't point to instances of such a
// wrapper class. Design overview: https://goo.gl/Ph4CGz
Address* location_;
}; };
...@@ -98,6 +103,11 @@ class Handle final : public HandleBase { ...@@ -98,6 +103,11 @@ class Handle final : public HandleBase {
static_assert(std::is_convertible<T*, Object*>::value, static_assert(std::is_convertible<T*, Object*>::value,
"static type violation"); "static type violation");
} }
V8_INLINE explicit Handle(Address* location) : HandleBase(location) {
// Type check:
static_assert(std::is_convertible<T*, Object*>::value,
"static type violation");
}
V8_INLINE Handle(T* object, Isolate* isolate); V8_INLINE Handle(T* object, Isolate* isolate);
...@@ -124,7 +134,7 @@ class Handle final : public HandleBase { ...@@ -124,7 +134,7 @@ class Handle final : public HandleBase {
// TODO(jkummerow): This is temporary; eventually location() should // TODO(jkummerow): This is temporary; eventually location() should
// return an Address*. // return an Address*.
V8_INLINE Address* location_as_address_ptr() const { V8_INLINE Address* location_as_address_ptr() const {
return reinterpret_cast<Address*>(HandleBase::location()); return HandleBase::location();
} }
template <typename S> template <typename S>
...@@ -186,12 +196,10 @@ class HandleScope { ...@@ -186,12 +196,10 @@ class HandleScope {
V8_EXPORT_PRIVATE static int NumberOfHandles(Isolate* isolate); V8_EXPORT_PRIVATE static int NumberOfHandles(Isolate* isolate);
// Create a new handle or lookup a canonical handle. // Create a new handle or lookup a canonical handle.
V8_INLINE static Object** GetHandle(Isolate* isolate, Object* value); V8_INLINE static Address* GetHandle(Isolate* isolate, Address value);
// Creates a new handle with the given value. // Creates a new handle with the given value.
V8_INLINE static Object** CreateHandle(Isolate* isolate, Object* value); V8_INLINE static Address* CreateHandle(Isolate* isolate, Address value);
V8_INLINE static Address* CreateHandle(Isolate* isolate,
Address value_address);
// Deallocates any extensions used by the current scope. // Deallocates any extensions used by the current scope.
V8_EXPORT_PRIVATE static void DeleteExtensions(Isolate* isolate); V8_EXPORT_PRIVATE static void DeleteExtensions(Isolate* isolate);
...@@ -263,12 +271,12 @@ class V8_EXPORT_PRIVATE CanonicalHandleScope final { ...@@ -263,12 +271,12 @@ class V8_EXPORT_PRIVATE CanonicalHandleScope final {
~CanonicalHandleScope(); ~CanonicalHandleScope();
private: private:
Object** Lookup(Object* object); Address* Lookup(Address object);
Isolate* isolate_; Isolate* isolate_;
Zone zone_; Zone zone_;
RootIndexMap* root_index_map_; RootIndexMap* root_index_map_;
IdentityMap<Object**, ZoneAllocationPolicy>* identity_map_; IdentityMap<Address*, ZoneAllocationPolicy>* identity_map_;
// Ordinary nested handle scopes within the current one are not canonical. // Ordinary nested handle scopes within the current one are not canonical.
int canonical_level_; int canonical_level_;
// We may have nested canonical scopes. Handles are canonical within each one. // We may have nested canonical scopes. Handles are canonical within each one.
......
...@@ -22,7 +22,7 @@ IdentityMapBase::~IdentityMapBase() { ...@@ -22,7 +22,7 @@ IdentityMapBase::~IdentityMapBase() {
void IdentityMapBase::Clear() { void IdentityMapBase::Clear() {
if (keys_) { if (keys_) {
DCHECK(!is_iterable()); DCHECK(!is_iterable());
heap_->UnregisterStrongRoots(keys_); heap_->UnregisterStrongRoots(reinterpret_cast<Object**>(keys_));
DeleteArray(keys_); DeleteArray(keys_);
DeleteArray(values_); DeleteArray(values_);
keys_ = nullptr; keys_ = nullptr;
...@@ -43,9 +43,10 @@ void IdentityMapBase::DisableIteration() { ...@@ -43,9 +43,10 @@ void IdentityMapBase::DisableIteration() {
is_iterable_ = false; is_iterable_ = false;
} }
int IdentityMapBase::ScanKeysFor(Object* address) const { int IdentityMapBase::ScanKeysFor(Address address) const {
int start = Hash(address) & mask_; int start = Hash(address) & mask_;
Object* not_mapped = ReadOnlyRoots(heap_).not_mapped_symbol(); Address not_mapped =
reinterpret_cast<Address>(ReadOnlyRoots(heap_).not_mapped_symbol());
for (int index = start; index < capacity_; index++) { for (int index = start; index < capacity_; index++) {
if (keys_[index] == address) return index; // Found. if (keys_[index] == address) return index; // Found.
if (keys_[index] == not_mapped) return -1; // Not found. if (keys_[index] == not_mapped) return -1; // Not found.
...@@ -57,8 +58,9 @@ int IdentityMapBase::ScanKeysFor(Object* address) const { ...@@ -57,8 +58,9 @@ int IdentityMapBase::ScanKeysFor(Object* address) const {
return -1; return -1;
} }
int IdentityMapBase::InsertKey(Object* address) { int IdentityMapBase::InsertKey(Address address) {
Object* not_mapped = ReadOnlyRoots(heap_).not_mapped_symbol(); Address not_mapped =
reinterpret_cast<Address>(ReadOnlyRoots(heap_).not_mapped_symbol());
while (true) { while (true) {
int start = Hash(address) & mask_; int start = Hash(address) & mask_;
int limit = capacity_ / 2; int limit = capacity_ / 2;
...@@ -80,7 +82,8 @@ int IdentityMapBase::InsertKey(Object* address) { ...@@ -80,7 +82,8 @@ int IdentityMapBase::InsertKey(Object* address) {
bool IdentityMapBase::DeleteIndex(int index, void** deleted_value) { bool IdentityMapBase::DeleteIndex(int index, void** deleted_value) {
if (deleted_value != nullptr) *deleted_value = values_[index]; if (deleted_value != nullptr) *deleted_value = values_[index];
Object* not_mapped = ReadOnlyRoots(heap_).not_mapped_symbol(); Address not_mapped =
reinterpret_cast<Address>(ReadOnlyRoots(heap_).not_mapped_symbol());
DCHECK_NE(keys_[index], not_mapped); DCHECK_NE(keys_[index], not_mapped);
keys_[index] = not_mapped; keys_[index] = not_mapped;
values_[index] = nullptr; values_[index] = nullptr;
...@@ -97,7 +100,7 @@ bool IdentityMapBase::DeleteIndex(int index, void** deleted_value) { ...@@ -97,7 +100,7 @@ bool IdentityMapBase::DeleteIndex(int index, void** deleted_value) {
int next_index = index; int next_index = index;
for (;;) { for (;;) {
next_index = (next_index + 1) & mask_; next_index = (next_index + 1) & mask_;
Object* key = keys_[next_index]; Address key = keys_[next_index];
if (key == not_mapped) break; if (key == not_mapped) break;
int expected_index = Hash(key) & mask_; int expected_index = Hash(key) & mask_;
...@@ -118,7 +121,7 @@ bool IdentityMapBase::DeleteIndex(int index, void** deleted_value) { ...@@ -118,7 +121,7 @@ bool IdentityMapBase::DeleteIndex(int index, void** deleted_value) {
return true; return true;
} }
int IdentityMapBase::Lookup(Object* key) const { int IdentityMapBase::Lookup(Address key) const {
int index = ScanKeysFor(key); int index = ScanKeysFor(key);
if (index < 0 && gc_counter_ != heap_->gc_count()) { if (index < 0 && gc_counter_ != heap_->gc_count()) {
// Miss; rehash if there was a GC, then lookup again. // Miss; rehash if there was a GC, then lookup again.
...@@ -128,7 +131,7 @@ int IdentityMapBase::Lookup(Object* key) const { ...@@ -128,7 +131,7 @@ int IdentityMapBase::Lookup(Object* key) const {
return index; return index;
} }
int IdentityMapBase::LookupOrInsert(Object* key) { int IdentityMapBase::LookupOrInsert(Address key) {
// Perform an optimistic lookup. // Perform an optimistic lookup.
int index = ScanKeysFor(key); int index = ScanKeysFor(key);
if (index < 0) { if (index < 0) {
...@@ -140,17 +143,17 @@ int IdentityMapBase::LookupOrInsert(Object* key) { ...@@ -140,17 +143,17 @@ int IdentityMapBase::LookupOrInsert(Object* key) {
return index; return index;
} }
int IdentityMapBase::Hash(Object* address) const { int IdentityMapBase::Hash(Address address) const {
CHECK_NE(address, ReadOnlyRoots(heap_).not_mapped_symbol()); CHECK_NE(address,
uintptr_t raw_address = reinterpret_cast<uintptr_t>(address); reinterpret_cast<Address>(ReadOnlyRoots(heap_).not_mapped_symbol()));
return static_cast<int>(hasher_(raw_address)); return static_cast<int>(hasher_(address));
} }
// Searches this map for the given key using the object's address // Searches this map for the given key using the object's address
// as the identity, returning: // as the identity, returning:
// found => a pointer to the storage location for the value // found => a pointer to the storage location for the value
// not found => a pointer to a new storage location for the value // not found => a pointer to a new storage location for the value
IdentityMapBase::RawEntry IdentityMapBase::GetEntry(Object* key) { IdentityMapBase::RawEntry IdentityMapBase::GetEntry(Address key) {
CHECK(!is_iterable()); // Don't allow insertion while iterable. CHECK(!is_iterable()); // Don't allow insertion while iterable.
if (capacity_ == 0) { if (capacity_ == 0) {
// Allocate the initial storage for keys and values. // Allocate the initial storage for keys and values.
...@@ -158,13 +161,15 @@ IdentityMapBase::RawEntry IdentityMapBase::GetEntry(Object* key) { ...@@ -158,13 +161,15 @@ IdentityMapBase::RawEntry IdentityMapBase::GetEntry(Object* key) {
mask_ = kInitialIdentityMapSize - 1; mask_ = kInitialIdentityMapSize - 1;
gc_counter_ = heap_->gc_count(); gc_counter_ = heap_->gc_count();
keys_ = reinterpret_cast<Object**>(NewPointerArray(capacity_)); keys_ = reinterpret_cast<Address*>(NewPointerArray(capacity_));
Object* not_mapped = ReadOnlyRoots(heap_).not_mapped_symbol(); Address not_mapped =
reinterpret_cast<Address>(ReadOnlyRoots(heap_).not_mapped_symbol());
for (int i = 0; i < capacity_; i++) keys_[i] = not_mapped; for (int i = 0; i < capacity_; i++) keys_[i] = not_mapped;
values_ = NewPointerArray(capacity_); values_ = NewPointerArray(capacity_);
memset(values_, 0, sizeof(void*) * capacity_); memset(values_, 0, sizeof(void*) * capacity_);
heap_->RegisterStrongRoots(keys_, keys_ + capacity_); heap_->RegisterStrongRoots(reinterpret_cast<Object**>(keys_),
reinterpret_cast<Object**>(keys_ + capacity_));
} }
int index = LookupOrInsert(key); int index = LookupOrInsert(key);
return &values_[index]; return &values_[index];
...@@ -174,7 +179,7 @@ IdentityMapBase::RawEntry IdentityMapBase::GetEntry(Object* key) { ...@@ -174,7 +179,7 @@ IdentityMapBase::RawEntry IdentityMapBase::GetEntry(Object* key) {
// as the identity, returning: // as the identity, returning:
// found => a pointer to the storage location for the value // found => a pointer to the storage location for the value
// not found => {nullptr} // not found => {nullptr}
IdentityMapBase::RawEntry IdentityMapBase::FindEntry(Object* key) const { IdentityMapBase::RawEntry IdentityMapBase::FindEntry(Address key) const {
// Don't allow find by key while iterable (might rehash). // Don't allow find by key while iterable (might rehash).
CHECK(!is_iterable()); CHECK(!is_iterable());
if (size_ == 0) return nullptr; if (size_ == 0) return nullptr;
...@@ -186,7 +191,7 @@ IdentityMapBase::RawEntry IdentityMapBase::FindEntry(Object* key) const { ...@@ -186,7 +191,7 @@ IdentityMapBase::RawEntry IdentityMapBase::FindEntry(Object* key) const {
// Deletes the given key from the map using the object's address as the // Deletes the given key from the map using the object's address as the
// identity, returning true iff the key was found (in which case, the value // identity, returning true iff the key was found (in which case, the value
// argument will be set to the deleted entry's value). // argument will be set to the deleted entry's value).
bool IdentityMapBase::DeleteEntry(Object* key, void** deleted_value) { bool IdentityMapBase::DeleteEntry(Address key, void** deleted_value) {
CHECK(!is_iterable()); // Don't allow deletion by key while iterable. CHECK(!is_iterable()); // Don't allow deletion by key while iterable.
if (size_ == 0) return false; if (size_ == 0) return false;
int index = Lookup(key); int index = Lookup(key);
...@@ -194,10 +199,11 @@ bool IdentityMapBase::DeleteEntry(Object* key, void** deleted_value) { ...@@ -194,10 +199,11 @@ bool IdentityMapBase::DeleteEntry(Object* key, void** deleted_value) {
return DeleteIndex(index, deleted_value); return DeleteIndex(index, deleted_value);
} }
Object* IdentityMapBase::KeyAtIndex(int index) const { Address IdentityMapBase::KeyAtIndex(int index) const {
DCHECK_LE(0, index); DCHECK_LE(0, index);
DCHECK_LT(index, capacity_); DCHECK_LT(index, capacity_);
DCHECK_NE(keys_[index], ReadOnlyRoots(heap_).not_mapped_symbol()); DCHECK_NE(keys_[index], reinterpret_cast<Address>(
ReadOnlyRoots(heap_).not_mapped_symbol()));
CHECK(is_iterable()); // Must be iterable to access by index; CHECK(is_iterable()); // Must be iterable to access by index;
return keys_[index]; return keys_[index];
} }
...@@ -205,7 +211,8 @@ Object* IdentityMapBase::KeyAtIndex(int index) const { ...@@ -205,7 +211,8 @@ Object* IdentityMapBase::KeyAtIndex(int index) const {
IdentityMapBase::RawEntry IdentityMapBase::EntryAtIndex(int index) const { IdentityMapBase::RawEntry IdentityMapBase::EntryAtIndex(int index) const {
DCHECK_LE(0, index); DCHECK_LE(0, index);
DCHECK_LT(index, capacity_); DCHECK_LT(index, capacity_);
DCHECK_NE(keys_[index], ReadOnlyRoots(heap_).not_mapped_symbol()); DCHECK_NE(keys_[index], reinterpret_cast<Address>(
ReadOnlyRoots(heap_).not_mapped_symbol()));
CHECK(is_iterable()); // Must be iterable to access by index; CHECK(is_iterable()); // Must be iterable to access by index;
return &values_[index]; return &values_[index];
} }
...@@ -214,7 +221,8 @@ int IdentityMapBase::NextIndex(int index) const { ...@@ -214,7 +221,8 @@ int IdentityMapBase::NextIndex(int index) const {
DCHECK_LE(-1, index); DCHECK_LE(-1, index);
DCHECK_LE(index, capacity_); DCHECK_LE(index, capacity_);
CHECK(is_iterable()); // Must be iterable to access by index; CHECK(is_iterable()); // Must be iterable to access by index;
Object* not_mapped = ReadOnlyRoots(heap_).not_mapped_symbol(); Address not_mapped =
reinterpret_cast<Address>(ReadOnlyRoots(heap_).not_mapped_symbol());
for (++index; index < capacity_; ++index) { for (++index; index < capacity_; ++index) {
if (keys_[index] != not_mapped) { if (keys_[index] != not_mapped) {
return index; return index;
...@@ -228,11 +236,12 @@ void IdentityMapBase::Rehash() { ...@@ -228,11 +236,12 @@ void IdentityMapBase::Rehash() {
// Record the current GC counter. // Record the current GC counter.
gc_counter_ = heap_->gc_count(); gc_counter_ = heap_->gc_count();
// Assume that most objects won't be moved. // Assume that most objects won't be moved.
std::vector<std::pair<Object*, void*>> reinsert; std::vector<std::pair<Address, void*>> reinsert;
// Search the table looking for keys that wouldn't be found with their // Search the table looking for keys that wouldn't be found with their
// current hashcode and evacuate them. // current hashcode and evacuate them.
int last_empty = -1; int last_empty = -1;
Object* not_mapped = ReadOnlyRoots(heap_).not_mapped_symbol(); Address not_mapped =
reinterpret_cast<Address>(ReadOnlyRoots(heap_).not_mapped_symbol());
for (int i = 0; i < capacity_; i++) { for (int i = 0; i < capacity_; i++) {
if (keys_[i] == not_mapped) { if (keys_[i] == not_mapped) {
last_empty = i; last_empty = i;
...@@ -240,7 +249,7 @@ void IdentityMapBase::Rehash() { ...@@ -240,7 +249,7 @@ void IdentityMapBase::Rehash() {
int pos = Hash(keys_[i]) & mask_; int pos = Hash(keys_[i]) & mask_;
if (pos <= last_empty || pos > i) { if (pos <= last_empty || pos > i) {
// Evacuate an entry that is in the wrong place. // Evacuate an entry that is in the wrong place.
reinsert.push_back(std::pair<Object*, void*>(keys_[i], values_[i])); reinsert.push_back(std::pair<Address, void*>(keys_[i], values_[i]));
keys_[i] = not_mapped; keys_[i] = not_mapped;
values_[i] = nullptr; values_[i] = nullptr;
last_empty = i; last_empty = i;
...@@ -261,7 +270,7 @@ void IdentityMapBase::Resize(int new_capacity) { ...@@ -261,7 +270,7 @@ void IdentityMapBase::Resize(int new_capacity) {
// Resize the internal storage and reinsert all the key/value pairs. // Resize the internal storage and reinsert all the key/value pairs.
DCHECK_GT(new_capacity, size_); DCHECK_GT(new_capacity, size_);
int old_capacity = capacity_; int old_capacity = capacity_;
Object** old_keys = keys_; Address* old_keys = keys_;
void** old_values = values_; void** old_values = values_;
capacity_ = new_capacity; capacity_ = new_capacity;
...@@ -269,8 +278,9 @@ void IdentityMapBase::Resize(int new_capacity) { ...@@ -269,8 +278,9 @@ void IdentityMapBase::Resize(int new_capacity) {
gc_counter_ = heap_->gc_count(); gc_counter_ = heap_->gc_count();
size_ = 0; size_ = 0;
keys_ = reinterpret_cast<Object**>(NewPointerArray(capacity_)); keys_ = reinterpret_cast<Address*>(NewPointerArray(capacity_));
Object* not_mapped = ReadOnlyRoots(heap_).not_mapped_symbol(); Address not_mapped =
reinterpret_cast<Address>(ReadOnlyRoots(heap_).not_mapped_symbol());
for (int i = 0; i < capacity_; i++) keys_[i] = not_mapped; for (int i = 0; i < capacity_; i++) keys_[i] = not_mapped;
values_ = NewPointerArray(capacity_); values_ = NewPointerArray(capacity_);
memset(values_, 0, sizeof(void*) * capacity_); memset(values_, 0, sizeof(void*) * capacity_);
...@@ -283,8 +293,9 @@ void IdentityMapBase::Resize(int new_capacity) { ...@@ -283,8 +293,9 @@ void IdentityMapBase::Resize(int new_capacity) {
} }
// Unregister old keys and register new keys. // Unregister old keys and register new keys.
heap_->UnregisterStrongRoots(old_keys); heap_->UnregisterStrongRoots(reinterpret_cast<Object**>(old_keys));
heap_->RegisterStrongRoots(keys_, keys_ + capacity_); heap_->RegisterStrongRoots(reinterpret_cast<Object**>(keys_),
reinterpret_cast<Object**>(keys_ + capacity_));
// Delete old storage; // Delete old storage;
DeleteArray(old_keys); DeleteArray(old_keys);
......
...@@ -41,12 +41,12 @@ class IdentityMapBase { ...@@ -41,12 +41,12 @@ class IdentityMapBase {
is_iterable_(false) {} is_iterable_(false) {}
virtual ~IdentityMapBase(); virtual ~IdentityMapBase();
RawEntry GetEntry(Object* key); RawEntry GetEntry(Address key);
RawEntry FindEntry(Object* key) const; RawEntry FindEntry(Address key) const;
bool DeleteEntry(Object* key, void** deleted_value); bool DeleteEntry(Address key, void** deleted_value);
void Clear(); void Clear();
Object* KeyAtIndex(int index) const; Address KeyAtIndex(int index) const;
V8_EXPORT_PRIVATE RawEntry EntryAtIndex(int index) const; V8_EXPORT_PRIVATE RawEntry EntryAtIndex(int index) const;
V8_EXPORT_PRIVATE int NextIndex(int index) const; V8_EXPORT_PRIVATE int NextIndex(int index) const;
...@@ -59,14 +59,14 @@ class IdentityMapBase { ...@@ -59,14 +59,14 @@ class IdentityMapBase {
private: private:
// Internal implementation should not be called directly by subclasses. // Internal implementation should not be called directly by subclasses.
int ScanKeysFor(Object* address) const; int ScanKeysFor(Address address) const;
int InsertKey(Object* address); int InsertKey(Address address);
int Lookup(Object* key) const; int Lookup(Address key) const;
int LookupOrInsert(Object* key); int LookupOrInsert(Address key);
bool DeleteIndex(int index, void** deleted_value); bool DeleteIndex(int index, void** deleted_value);
void Rehash(); void Rehash();
void Resize(int new_capacity); void Resize(int new_capacity);
int Hash(Object* address) const; int Hash(Address address) const;
base::hash<uintptr_t> hasher_; base::hash<uintptr_t> hasher_;
Heap* heap_; Heap* heap_;
...@@ -74,7 +74,7 @@ class IdentityMapBase { ...@@ -74,7 +74,7 @@ class IdentityMapBase {
int size_; int size_;
int capacity_; int capacity_;
int mask_; int mask_;
Object** keys_; Address* keys_;
void** values_; void** values_;
bool is_iterable_; bool is_iterable_;
...@@ -100,25 +100,31 @@ class IdentityMap : public IdentityMapBase { ...@@ -100,25 +100,31 @@ class IdentityMap : public IdentityMapBase {
// found => a pointer to the storage location for the value // found => a pointer to the storage location for the value
// not found => a pointer to a new storage location for the value // not found => a pointer to a new storage location for the value
V* Get(Handle<Object> key) { return Get(*key); } V* Get(Handle<Object> key) { return Get(*key); }
V* Get(Object* key) { return reinterpret_cast<V*>(GetEntry(key)); } V* Get(Object* key) {
return reinterpret_cast<V*>(GetEntry(reinterpret_cast<Address>(key)));
}
// Searches this map for the given key using the object's address // Searches this map for the given key using the object's address
// as the identity, returning: // as the identity, returning:
// found => a pointer to the storage location for the value // found => a pointer to the storage location for the value
// not found => {nullptr} // not found => {nullptr}
V* Find(Handle<Object> key) const { return Find(*key); } V* Find(Handle<Object> key) const { return Find(*key); }
V* Find(Object* key) const { return reinterpret_cast<V*>(FindEntry(key)); } V* Find(Object* key) const {
return reinterpret_cast<V*>(FindEntry(reinterpret_cast<Address>(key)));
}
// Set the value for the given key. // Set the value for the given key.
void Set(Handle<Object> key, V v) { Set(*key, v); } void Set(Handle<Object> key, V v) { Set(*key, v); }
void Set(Object* key, V v) { *(reinterpret_cast<V*>(GetEntry(key))) = v; } void Set(Object* key, V v) {
*(reinterpret_cast<V*>(GetEntry(reinterpret_cast<Address>(key)))) = v;
}
bool Delete(Handle<Object> key, V* deleted_value) { bool Delete(Handle<Object> key, V* deleted_value) {
return Delete(*key, deleted_value); return Delete(*key, deleted_value);
} }
bool Delete(Object* key, V* deleted_value) { bool Delete(Object* key, V* deleted_value) {
void* v = nullptr; void* v = nullptr;
bool deleted_something = DeleteEntry(key, &v); bool deleted_something = DeleteEntry(reinterpret_cast<Address>(key), &v);
if (deleted_value != nullptr && deleted_something) { if (deleted_value != nullptr && deleted_something) {
*deleted_value = *reinterpret_cast<V*>(&v); *deleted_value = *reinterpret_cast<V*>(&v);
} }
...@@ -137,7 +143,9 @@ class IdentityMap : public IdentityMapBase { ...@@ -137,7 +143,9 @@ class IdentityMap : public IdentityMapBase {
return *this; return *this;
} }
Object* key() const { return map_->KeyAtIndex(index_); } Object* key() const {
return reinterpret_cast<Object*>(map_->KeyAtIndex(index_));
}
V* entry() const { V* entry() const {
return reinterpret_cast<V*>(map_->EntryAtIndex(index_)); return reinterpret_cast<V*>(map_->EntryAtIndex(index_));
} }
......
...@@ -142,8 +142,9 @@ class IdentityMapTester : public HandleAndZoneScope { ...@@ -142,8 +142,9 @@ class IdentityMapTester : public HandleAndZoneScope {
void SimulateGCByIncrementingSmisBy(int shift) { void SimulateGCByIncrementingSmisBy(int shift) {
for (int i = 0; i < map.capacity_; i++) { for (int i = 0; i < map.capacity_; i++) {
if (map.keys_[i]->IsSmi()) { Address key = map.keys_[i];
map.keys_[i] = Smi::FromInt(Smi::ToInt(map.keys_[i]) + shift); if (!Internals::HasHeapObjectTag(key)) {
map.keys_[i] = Internals::IntToSmi(Internals::SmiValue(key) + shift);
} }
} }
map.gc_counter_ = -1; map.gc_counter_ = -1;
......
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