Commit 0a8f8a95 authored by yangguo's avatar yangguo Committed by Commit bot

Change hash table capacity heuristics when serializing.

Also extract non-templated parts of HashTable class into HashTableBase.

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

Cr-Commit-Position: refs/heads/master@{#27959}
parent 4d3044e1
......@@ -3095,7 +3095,7 @@ void Heap::CreateInitialObjects() {
TENURED));
Handle<SeededNumberDictionary> slow_element_dictionary =
SeededNumberDictionary::New(isolate(), 0, TENURED);
SeededNumberDictionary::New(isolate(), 1, TENURED);
slow_element_dictionary->set_requires_slow_elements();
set_empty_slow_element_dictionary(*slow_element_dictionary);
......
......@@ -3245,8 +3245,7 @@ DescriptorArray::WhitenessWitness::~WhitenessWitness() {
}
template<typename Derived, typename Shape, typename Key>
int HashTable<Derived, Shape, Key>::ComputeCapacity(int at_least_space_for) {
int HashTableBase::ComputeCapacity(int at_least_space_for) {
const int kMinCapacity = 32;
int capacity = base::bits::RoundUpToPowerOfTwo32(at_least_space_for * 2);
if (capacity < kMinCapacity) {
......@@ -3256,7 +3255,12 @@ int HashTable<Derived, Shape, Key>::ComputeCapacity(int at_least_space_for) {
}
template<typename Derived, typename Shape, typename Key>
int HashTableBase::ComputeCapacityForSerialization(int at_least_space_for) {
return base::bits::RoundUpToPowerOfTwo32(at_least_space_for);
}
template <typename Derived, typename Shape, typename Key>
int HashTable<Derived, Shape, Key>::FindEntry(Key key) {
return FindEntry(GetIsolate(), key);
}
......
......@@ -14555,7 +14555,9 @@ Handle<Derived> HashTable<Derived, Shape, Key>::New(
DCHECK(!capacity_option || base::bits::IsPowerOfTwo32(at_least_space_for));
int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
? at_least_space_for
: ComputeCapacity(at_least_space_for);
: isolate->serializer_enabled()
? ComputeCapacityForSerialization(at_least_space_for)
: ComputeCapacity(at_least_space_for);
if (capacity > HashTable::kMaxCapacity) {
v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
}
......
......@@ -3301,26 +3301,9 @@ class BaseShape {
}
};
template<typename Derived, typename Shape, typename Key>
class HashTable: public FixedArray {
public:
// Wrapper methods
inline uint32_t Hash(Key key) {
if (Shape::UsesSeed) {
return Shape::SeededHash(key, GetHeap()->HashSeed());
} else {
return Shape::Hash(key);
}
}
inline uint32_t HashForObject(Key key, Object* object) {
if (Shape::UsesSeed) {
return Shape::SeededHashForObject(key, GetHeap()->HashSeed(), object);
} else {
return Shape::HashForObject(key, object);
}
}
class HashTableBase : public FixedArray {
public:
// Returns the number of elements in the hash table.
int NumberOfElements() {
return Smi::cast(get(kNumberOfElementsIndex))->value();
......@@ -3351,19 +3334,12 @@ class HashTable: public FixedArray {
SetNumberOfDeletedElements(NumberOfDeletedElements() + n);
}
// Returns a new HashTable object.
MUST_USE_RESULT static Handle<Derived> New(
Isolate* isolate,
int at_least_space_for,
MinimumCapacity capacity_option = USE_DEFAULT_MINIMUM_CAPACITY,
PretenureFlag pretenure = NOT_TENURED);
// Computes the required capacity for a table holding the given
// number of elements. May be more than HashTable::kMaxCapacity.
static int ComputeCapacity(int at_least_space_for);
static inline int ComputeCapacity(int at_least_space_for);
// Returns the key at entry.
Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
// Use a different heuristic to compute capacity when serializing.
static inline int ComputeCapacityForSerialization(int at_least_space_for);
// 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.
......@@ -3371,12 +3347,6 @@ class HashTable: public FixedArray {
return !k->IsTheHole() && !k->IsUndefined();
}
// Garbage collection support.
void IteratePrefix(ObjectVisitor* visitor);
void IterateElements(ObjectVisitor* visitor);
DECLARE_CAST(HashTable)
// Compute the probe offset (quadratic probing).
INLINE(static uint32_t GetProbeOffset(uint32_t n)) {
return (n + n * n) >> 1;
......@@ -3386,42 +3356,11 @@ class HashTable: public FixedArray {
static const int kNumberOfDeletedElementsIndex = 1;
static const int kCapacityIndex = 2;
static const int kPrefixStartIndex = 3;
static const int kElementsStartIndex =
kPrefixStartIndex + Shape::kPrefixSize;
static const int kEntrySize = Shape::kEntrySize;
static const int kElementsStartOffset =
kHeaderSize + kElementsStartIndex * kPointerSize;
static const int kCapacityOffset =
kHeaderSize + kCapacityIndex * kPointerSize;
// Constant used for denoting a absent entry.
static const int kNotFound = -1;
// Maximal capacity of HashTable. Based on maximal length of underlying
// FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
// cannot overflow.
static const int kMaxCapacity =
(FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize;
// Find entry for key otherwise return kNotFound.
inline int FindEntry(Key key);
int FindEntry(Isolate* isolate, Key key);
// Rehashes the table in-place.
void Rehash(Key key);
protected:
friend class ObjectHashTable;
// Find the entry at which to insert element with the given key that
// has the given hash value.
uint32_t FindInsertionEntry(uint32_t hash);
// Returns the index for an entry (of the key)
static inline int EntryToIndex(int entry) {
return (entry * kEntrySize) + kElementsStartIndex;
}
// Update the number of elements in the hash table.
void SetNumberOfElements(int nof) {
set(kNumberOfElementsIndex, Smi::FromInt(nof));
......@@ -3432,17 +3371,6 @@ class HashTable: public FixedArray {
set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
}
// Sets the capacity of the hash table.
void SetCapacity(int capacity) {
// To scale a computed hash code to fit within the hash table, we
// use bit-wise AND with a mask, so the capacity must be positive
// and non-zero.
DCHECK(capacity > 0);
DCHECK(capacity <= kMaxCapacity);
set(kCapacityIndex, Smi::FromInt(capacity));
}
// Returns probe entry.
static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) {
DCHECK(base::bits::IsPowerOfTwo32(size));
......@@ -3457,6 +3385,64 @@ class HashTable: public FixedArray {
uint32_t last, uint32_t number, uint32_t size) {
return (last + number) & (size - 1);
}
};
template <typename Derived, typename Shape, typename Key>
class HashTable : public HashTableBase {
public:
// Wrapper methods
inline uint32_t Hash(Key key) {
if (Shape::UsesSeed) {
return Shape::SeededHash(key, GetHeap()->HashSeed());
} else {
return Shape::Hash(key);
}
}
inline uint32_t HashForObject(Key key, Object* object) {
if (Shape::UsesSeed) {
return Shape::SeededHashForObject(key, GetHeap()->HashSeed(), object);
} else {
return Shape::HashForObject(key, object);
}
}
// Returns a new HashTable object.
MUST_USE_RESULT static Handle<Derived> New(
Isolate* isolate, int at_least_space_for,
MinimumCapacity capacity_option = USE_DEFAULT_MINIMUM_CAPACITY,
PretenureFlag pretenure = NOT_TENURED);
DECLARE_CAST(HashTable)
// Garbage collection support.
void IteratePrefix(ObjectVisitor* visitor);
void IterateElements(ObjectVisitor* visitor);
// Find entry for key otherwise return kNotFound.
inline int FindEntry(Key key);
int FindEntry(Isolate* isolate, Key key);
// Rehashes the table in-place.
void Rehash(Key key);
// Returns the key at entry.
Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
static const int kElementsStartIndex = kPrefixStartIndex + Shape::kPrefixSize;
static const int kEntrySize = Shape::kEntrySize;
static const int kElementsStartOffset =
kHeaderSize + kElementsStartIndex * kPointerSize;
static const int kCapacityOffset =
kHeaderSize + kCapacityIndex * kPointerSize;
protected:
friend class ObjectHashTable;
// Find the entry at which to insert element with the given key that
// has the given hash value.
uint32_t FindInsertionEntry(uint32_t hash);
// Attempt to shrink hash table after removal of key.
MUST_USE_RESULT static Handle<Derived> Shrink(Handle<Derived> table, Key key);
......@@ -3468,6 +3454,27 @@ class HashTable: public FixedArray {
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
// use bit-wise AND with a mask, so the capacity must be positive
// and non-zero.
DCHECK(capacity > 0);
DCHECK(capacity <= kMaxCapacity);
set(kCapacityIndex, Smi::FromInt(capacity));
}
// Maximal capacity of HashTable. Based on maximal length of underlying
// FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
// cannot overflow.
static const int kMaxCapacity =
(FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize;
private:
// Returns _expected_ if one of entries given by the first _probe_ probes is
// equal to _expected_. Otherwise, returns the entry given by the probe
......
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