Commit e72f7f53 authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by Commit Bot

[hashtable] Port SmallOrderedHashTableAllocate to CSA

Bug: v8:6443, v8:7569
Change-Id: Ia7e1ed9ab7e85ac366349688278ba59507d38b7e
Reviewed-on: https://chromium-review.googlesource.com/1098474
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54068}
parent a617bf52
......@@ -2433,6 +2433,13 @@ Node* CodeStubAssembler::LoadSharedFunctionInfoBytecodeArray(Node* shared) {
return var_result.value();
}
void CodeStubAssembler::StoreObjectByteNoWriteBarrier(TNode<HeapObject> object,
int offset,
TNode<Word32T> value) {
StoreNoWriteBarrier(MachineRepresentation::kWord8, object,
IntPtrConstant(offset - kHeapObjectTag), value);
}
void CodeStubAssembler::StoreHeapNumberValue(SloppyTNode<HeapNumber> object,
SloppyTNode<Float64T> value) {
StoreObjectFieldNoWriteBarrier(object, HeapNumber::kValueOffset, value,
......@@ -3256,6 +3263,87 @@ Node* CodeStubAssembler::AllocateOrderedHashTable() {
template Node* CodeStubAssembler::AllocateOrderedHashTable<OrderedHashMap>();
template Node* CodeStubAssembler::AllocateOrderedHashTable<OrderedHashSet>();
template <typename CollectionType>
TNode<CollectionType> CodeStubAssembler::AllocateSmallOrderedHashTable(
TNode<IntPtrT> capacity) {
CSA_ASSERT(this, WordIsPowerOfTwo(capacity));
CSA_ASSERT(this, IntPtrLessThan(
capacity, IntPtrConstant(CollectionType::kMaxCapacity)));
TNode<IntPtrT> data_table_start_offset =
IntPtrConstant(CollectionType::kDataTableStartOffset);
TNode<IntPtrT> data_table_size = IntPtrMul(
capacity, IntPtrConstant(CollectionType::kEntrySize * kPointerSize));
TNode<Int32T> hash_table_size =
Int32Div(TruncateIntPtrToInt32(capacity),
Int32Constant(CollectionType::kLoadFactor));
TNode<IntPtrT> hash_table_start_offset =
IntPtrAdd(data_table_start_offset, data_table_size);
TNode<IntPtrT> hash_table_and_chain_table_size =
IntPtrAdd(ChangeInt32ToIntPtr(hash_table_size), capacity);
TNode<IntPtrT> total_size =
IntPtrAdd(hash_table_start_offset, hash_table_and_chain_table_size);
TNode<IntPtrT> total_size_word_aligned =
IntPtrAdd(total_size, IntPtrConstant(kPointerSize - 1));
total_size_word_aligned = ChangeInt32ToIntPtr(
Int32Div(TruncateIntPtrToInt32(total_size_word_aligned),
Int32Constant(kPointerSize)));
total_size_word_aligned =
UncheckedCast<IntPtrT>(TimesPointerSize(total_size_word_aligned));
// Allocate the table and add the proper map.
TNode<Map> small_ordered_hash_map = CAST(LoadRoot(
static_cast<Heap::RootListIndex>(CollectionType::GetMapRootIndex())));
TNode<Object> table_obj = CAST(AllocateInNewSpace(total_size_word_aligned));
StoreMapNoWriteBarrier(table_obj, small_ordered_hash_map);
TNode<CollectionType> table = UncheckedCast<CollectionType>(table_obj);
// Initialize the SmallOrderedHashTable fields.
StoreObjectByteNoWriteBarrier(
table, CollectionType::kNumberOfBucketsOffset,
Word32And(Int32Constant(0xFF), hash_table_size));
StoreObjectByteNoWriteBarrier(table, CollectionType::kNumberOfElementsOffset,
Int32Constant(0));
StoreObjectByteNoWriteBarrier(
table, CollectionType::kNumberOfDeletedElementsOffset, Int32Constant(0));
TNode<IntPtrT> table_address =
IntPtrSub(BitcastTaggedToWord(table), IntPtrConstant(kHeapObjectTag));
TNode<IntPtrT> hash_table_start_address =
IntPtrAdd(table_address, hash_table_start_offset);
// Initialize the HashTable part.
Node* memset = ExternalConstant(ExternalReference::libc_memset_function());
CallCFunction3(MachineType::AnyTagged(), MachineType::Pointer(),
MachineType::IntPtr(), MachineType::UintPtr(), memset,
hash_table_start_address, IntPtrConstant(0xFF),
hash_table_and_chain_table_size);
// Initialize the DataTable part.
TNode<HeapObject> filler = TheHoleConstant();
TNode<WordT> data_table_start_address =
IntPtrAdd(table_address, data_table_start_offset);
TNode<WordT> data_table_end_address =
IntPtrAdd(data_table_start_address, data_table_size);
StoreFieldsNoWriteBarrier(data_table_start_address, data_table_end_address,
filler);
return table;
}
template TNode<SmallOrderedHashMap>
CodeStubAssembler::AllocateSmallOrderedHashTable<SmallOrderedHashMap>(
TNode<IntPtrT> capacity);
template TNode<SmallOrderedHashSet>
CodeStubAssembler::AllocateSmallOrderedHashTable<SmallOrderedHashSet>(
TNode<IntPtrT> capacity);
template <typename CollectionType>
void CodeStubAssembler::FindOrderedHashTableEntry(
Node* table, Node* hash,
......@@ -4700,7 +4788,7 @@ TNode<UintPtrT> CodeStubAssembler::ChangeNonnegativeNumberToUintPtr(
return result.value();
}
Node* CodeStubAssembler::TimesPointerSize(Node* value) {
SloppyTNode<WordT> CodeStubAssembler::TimesPointerSize(Node* value) {
return WordShl(value, IntPtrConstant(kPointerSizeLog2));
}
......
......@@ -1072,6 +1072,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* LoadSharedFunctionInfoBytecodeArray(Node* shared);
void StoreObjectByteNoWriteBarrier(TNode<HeapObject> object, int offset,
TNode<Word32T> value);
// Store the floating point value of a HeapNumber.
void StoreHeapNumberValue(SloppyTNode<HeapNumber> object,
SloppyTNode<Float64T> value);
......@@ -1254,6 +1257,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
std::function<void(Node*, Label*, Label*)> key_compare,
Variable* entry_start_position, Label* entry_found, Label* not_found);
template <typename CollectionType>
TNode<CollectionType> AllocateSmallOrderedHashTable(TNode<IntPtrT> capacity);
Node* AllocateStruct(Node* map, AllocationFlags flags = kNone);
void InitializeStructBody(Node* object, Node* map, Node* size,
int start_offset = Struct::kHeaderSize);
......@@ -1554,7 +1560,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Variable* var_numeric,
Variable* var_feedback);
Node* TimesPointerSize(Node* value);
SloppyTNode<WordT> TimesPointerSize(Node* value);
// Type conversions.
// Throws a TypeError for {method_name} if {value} is not coercible to Object,
......
......@@ -725,9 +725,9 @@ ExternalReference ExternalReference::libc_memmove_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(libc_memmove)));
}
void* libc_memset(void* dest, int byte, size_t n) {
DCHECK_EQ(static_cast<char>(byte), byte);
return memset(dest, byte, n);
void* libc_memset(void* dest, int value, size_t n) {
DCHECK_EQ(static_cast<byte>(value), value);
return memset(dest, value, n);
}
ExternalReference ExternalReference::libc_memset_function() {
......
......@@ -235,7 +235,7 @@ class SmallOrderedHashTable<Derived>::BodyDescriptor final
ObjectVisitor* v) {
Derived* table = reinterpret_cast<Derived*>(obj);
int offset = kHeaderSize + kDataTableStartOffset;
int offset = kDataTableStartOffset;
int entry = 0;
for (int i = 0; i < table->Capacity(); i++) {
for (int j = 0; j < Derived::kEntrySize; j++) {
......
......@@ -2705,8 +2705,7 @@ void Foreign::set_foreign_address(Address value) {
template <class Derived>
void SmallOrderedHashTable<Derived>::SetDataEntry(int entry, int relative_index,
Object* value) {
Address entry_offset =
kHeaderSize + GetDataEntryOffset(entry, relative_index);
Address entry_offset = GetDataEntryOffset(entry, relative_index);
RELAXED_WRITE_FIELD(this, entry_offset, value);
WRITE_BARRIER(Heap::FromWritableHeapObject(this), this,
static_cast<int>(entry_offset), value);
......
......@@ -19,6 +19,14 @@ int OrderedHashMap::GetMapRootIndex() {
return Heap::kOrderedHashMapMapRootIndex;
}
int SmallOrderedHashMap::GetMapRootIndex() {
return Heap::kSmallOrderedHashMapMapRootIndex;
}
int SmallOrderedHashSet::GetMapRootIndex() {
return Heap::kSmallOrderedHashSetMapRootIndex;
}
inline Object* OrderedHashMap::ValueAt(int entry) {
DCHECK_LT(entry, this->UsedCapacity());
return get(EntryToIndex(entry) + kValueOffset);
......
......@@ -337,7 +337,7 @@ void SmallOrderedHashTable<Derived>::Initialize(Isolate* isolate,
num_buckets + num_chains);
if (isolate->heap()->InNewSpace(this)) {
MemsetPointer(RawField(this, kHeaderSize + kDataTableStartOffset),
MemsetPointer(RawField(this, kDataTableStartOffset),
isolate->heap()->the_hole_value(),
capacity * Derived::kEntrySize);
} else {
......
......@@ -338,10 +338,10 @@ class SmallOrderedHashTable : public HeapObject {
int data_table_size = DataTableSizeFor(capacity);
int hash_table_size = capacity / kLoadFactor;
int chain_table_size = capacity;
int total_size = kHeaderSize + kDataTableStartOffset + data_table_size +
hash_table_size + chain_table_size;
int total_size = kDataTableStartOffset + data_table_size + hash_table_size +
chain_table_size;
return ((total_size + kPointerSize - 1) / kPointerSize) * kPointerSize;
return RoundUp(total_size, kPointerSize);
}
// Returns the number elements that can fit into the allocated table.
......@@ -355,20 +355,20 @@ class SmallOrderedHashTable : public HeapObject {
// Returns the number elements that are present in the table.
int NumberOfElements() const {
int nof_elements = getByte(0, kNumberOfElementsByteIndex);
int nof_elements = getByte(kNumberOfElementsOffset, 0);
DCHECK_LE(nof_elements, Capacity());
return nof_elements;
}
int NumberOfDeletedElements() const {
int nof_deleted_elements = getByte(0, kNumberOfDeletedElementsByteIndex);
int nof_deleted_elements = getByte(kNumberOfDeletedElementsOffset, 0);
DCHECK_LE(nof_deleted_elements, Capacity());
return nof_deleted_elements;
}
int NumberOfBuckets() const { return getByte(0, kNumberOfBucketsByteIndex); }
int NumberOfBuckets() const { return getByte(kNumberOfBucketsOffset, 0); }
DECL_VERIFIER(SmallOrderedHashTable)
......@@ -407,8 +407,7 @@ class SmallOrderedHashTable : public HeapObject {
}
Address GetHashTableStartAddress(int capacity) const {
return FIELD_ADDR(
this, kHeaderSize + kDataTableStartOffset + DataTableSizeFor(capacity));
return FIELD_ADDR(this, kDataTableStartOffset + DataTableSizeFor(capacity));
}
void SetFirstEntry(int bucket, byte value) {
......@@ -449,13 +448,13 @@ class SmallOrderedHashTable : public HeapObject {
DCHECK_LT(entry, Capacity());
DCHECK_LE(static_cast<unsigned>(relative_index), Derived::kEntrySize);
Offset entry_offset = GetDataEntryOffset(entry, relative_index);
return READ_FIELD(this, kHeaderSize + entry_offset);
return READ_FIELD(this, entry_offset);
}
Object* KeyAt(int entry) const {
DCHECK_LT(entry, Capacity());
Offset entry_offset = GetDataEntryOffset(entry, Derived::kKeyIndex);
return READ_FIELD(this, kHeaderSize + entry_offset);
return READ_FIELD(this, entry_offset);
}
int HashToBucket(int hash) const { return hash & (NumberOfBuckets() - 1); }
......@@ -467,18 +466,16 @@ class SmallOrderedHashTable : public HeapObject {
return entry;
}
void SetNumberOfBuckets(int num) {
setByte(0, kNumberOfBucketsByteIndex, num);
}
void SetNumberOfBuckets(int num) { setByte(kNumberOfBucketsOffset, 0, num); }
void SetNumberOfElements(int num) {
DCHECK_LE(static_cast<unsigned>(num), Capacity());
setByte(0, kNumberOfElementsByteIndex, num);
setByte(kNumberOfElementsOffset, 0, num);
}
void SetNumberOfDeletedElements(int num) {
DCHECK_LE(static_cast<unsigned>(num), Capacity());
setByte(0, kNumberOfDeletedElementsByteIndex, num);
setByte(kNumberOfDeletedElementsOffset, 0, num);
}
int FindEntry(Isolate* isolate, Object* key) {
......@@ -497,11 +494,14 @@ class SmallOrderedHashTable : public HeapObject {
return kNotFound;
}
static const int kNumberOfElementsByteIndex = 0;
static const int kNumberOfDeletedElementsByteIndex = 1;
static const int kNumberOfBucketsByteIndex = 2;
static const Offset kNumberOfElementsOffset = kHeaderSize;
static const Offset kNumberOfDeletedElementsOffset =
kNumberOfElementsOffset + kOneByteSize;
static const Offset kNumberOfBucketsOffset =
kNumberOfDeletedElementsOffset + kOneByteSize;
static const constexpr Offset kDataTableStartOffset =
RoundUp<kPointerSize>(kNumberOfBucketsOffset);
static const Offset kDataTableStartOffset = kPointerSize;
static constexpr int DataTableSizeFor(int capacity) {
return capacity * Derived::kEntrySize * kPointerSize;
}
......@@ -510,13 +510,12 @@ class SmallOrderedHashTable : public HeapObject {
// structure.
byte getByte(Offset offset, ByteIndex index) const {
DCHECK(offset < kDataTableStartOffset || offset >= GetBucketsStartOffset());
return READ_BYTE_FIELD(this, kHeaderSize + offset + (index * kOneByteSize));
return READ_BYTE_FIELD(this, offset + (index * kOneByteSize));
}
void setByte(Offset offset, ByteIndex index, byte value) {
DCHECK(offset < kDataTableStartOffset || offset >= GetBucketsStartOffset());
WRITE_BYTE_FIELD(this, kHeaderSize + offset + (index * kOneByteSize),
value);
WRITE_BYTE_FIELD(this, offset + (index * kOneByteSize), value);
}
Offset GetDataEntryOffset(int entry, int relative_index) const {
......@@ -536,6 +535,7 @@ class SmallOrderedHashTable : public HeapObject {
private:
friend class OrderedHashMapHandler;
friend class OrderedHashSetHandler;
friend class CodeStubAssembler;
};
class SmallOrderedHashSet : public SmallOrderedHashTable<SmallOrderedHashSet> {
......@@ -554,6 +554,7 @@ class SmallOrderedHashSet : public SmallOrderedHashTable<SmallOrderedHashSet> {
Handle<SmallOrderedHashSet> table,
Handle<Object> key);
static inline bool Is(Handle<HeapObject> table);
static inline int GetMapRootIndex();
};
class SmallOrderedHashMap : public SmallOrderedHashTable<SmallOrderedHashMap> {
......@@ -574,6 +575,7 @@ class SmallOrderedHashMap : public SmallOrderedHashTable<SmallOrderedHashMap> {
Handle<Object> key,
Handle<Object> value);
static inline bool Is(Handle<HeapObject> table);
static inline int GetMapRootIndex();
};
// TODO(gsathya): Rename this to OrderedHashTable, after we rename
......
......@@ -3314,6 +3314,80 @@ TEST(SingleInputPhiElimination) {
// single-input phi is properly eliminated.
}
TEST(SmallOrderedHashMapAllocate) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1;
CodeAssemblerTester asm_tester(isolate, kNumParams);
{
CodeStubAssembler m(asm_tester.state());
TNode<Smi> capacity = m.CAST(m.Parameter(0));
m.Return(m.AllocateSmallOrderedHashTable<SmallOrderedHashMap>(
m.SmiToIntPtr(capacity)));
}
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
Factory* factory = isolate->factory();
int capacity = SmallOrderedHashMap::kMinCapacity;
while (capacity <= SmallOrderedHashMap::kMaxCapacity) {
Handle<SmallOrderedHashMap> expected =
factory->NewSmallOrderedHashMap(capacity);
Handle<Object> result_raw =
ft.Call(Handle<Smi>(Smi::FromInt(capacity), isolate)).ToHandleChecked();
Handle<SmallOrderedHashMap> actual = Handle<SmallOrderedHashMap>(
SmallOrderedHashMap::cast(*result_raw), isolate);
CHECK_EQ(capacity, actual->Capacity());
CHECK_EQ(0, actual->NumberOfElements());
CHECK_EQ(0, actual->NumberOfDeletedElements());
CHECK_EQ(capacity / SmallOrderedHashMap::kLoadFactor,
actual->NumberOfBuckets());
CHECK(memcmp(*expected, *actual, SmallOrderedHashMap::SizeFor(capacity)));
#ifdef VERIFY_HEAP
actual->SmallOrderedHashTableVerify(isolate);
#endif
capacity = capacity << 1;
}
#ifdef VERIFY_HEAP
isolate->heap()->Verify();
#endif
}
TEST(SmallOrderedHashSetAllocate) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1;
CodeAssemblerTester asm_tester(isolate, kNumParams);
{
CodeStubAssembler m(asm_tester.state());
TNode<Smi> capacity = m.CAST(m.Parameter(0));
m.Return(m.AllocateSmallOrderedHashTable<SmallOrderedHashSet>(
m.SmiToIntPtr(capacity)));
}
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
int capacity = SmallOrderedHashSet::kMinCapacity;
Factory* factory = isolate->factory();
while (capacity <= SmallOrderedHashSet::kMaxCapacity) {
Handle<SmallOrderedHashSet> expected =
factory->NewSmallOrderedHashSet(capacity);
Handle<Object> result_raw =
ft.Call(Handle<Smi>(Smi::FromInt(capacity), isolate)).ToHandleChecked();
Handle<SmallOrderedHashSet> actual = Handle<SmallOrderedHashSet>(
SmallOrderedHashSet::cast(*result_raw), isolate);
CHECK_EQ(capacity, actual->Capacity());
CHECK_EQ(0, actual->NumberOfElements());
CHECK_EQ(0, actual->NumberOfDeletedElements());
CHECK_EQ(capacity / SmallOrderedHashSet::kLoadFactor,
actual->NumberOfBuckets());
CHECK(memcmp(*expected, *actual, SmallOrderedHashSet::SizeFor(capacity)));
#ifdef VERIFY_HEAP
actual->SmallOrderedHashTableVerify(isolate);
#endif
capacity = capacity << 1;
}
#ifdef VERIFY_HEAP
isolate->heap()->Verify();
#endif
}
TEST(IsDoubleElementsKind) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 2;
......
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