Commit 8e86f221 authored by Frank Emrich's avatar Frank Emrich Committed by Commit Bot

[dict-proto] CSA/Torque implementation of SwissNameDictionary, pt. 2

This CL adds:
a) Helper macros that access the meta table, used in follow-up CLs

b) Infrastructure for building efficient accesses to the meta table

Bug: v8:11330
Change-Id: I5494c3048a4f82f21871437dfe367d6a456c8257
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2773004
Commit-Queue: Frank Emrich <emrich@google.com>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarSantiago Aboy Solanes <solanes@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73602}
parent 07d7fd32
......@@ -4,6 +4,8 @@
#include "src/codegen/code-stub-assembler.h"
#include <functional>
#include "include/v8-internal.h"
#include "src/base/macros.h"
#include "src/codegen/code-factory.h"
......@@ -14306,6 +14308,227 @@ void PrototypeCheckAssembler::CheckAndBranch(TNode<HeapObject> prototype,
}
}
//
// Begin of SwissNameDictionary macros
//
namespace {
// Provides load and store functions that abstract over the details of accessing
// the meta table in memory. Instead they allow using logical indices that are
// independent from the underlying entry size in the meta table of a
// SwissNameDictionary.
class MetaTableAccessor {
public:
MetaTableAccessor(CodeStubAssembler& csa, MachineType mt)
: csa{csa}, mt{mt} {}
TNode<Uint32T> Load(TNode<ByteArray> meta_table, TNode<IntPtrT> index) {
TNode<IntPtrT> offset = OverallOffset(meta_table, index);
return csa.UncheckedCast<Uint32T>(
csa.LoadFromObject(mt, meta_table, offset));
}
TNode<Uint32T> Load(TNode<ByteArray> meta_table, int index) {
return Load(meta_table, csa.IntPtrConstant(index));
}
void Store(TNode<ByteArray> meta_table, TNode<IntPtrT> index,
TNode<Uint32T> data) {
TNode<IntPtrT> offset = OverallOffset(meta_table, index);
#ifdef DEBUG
int bits = mt.MemSize() * 8;
TNode<IntPtrT> max_value = csa.IntPtrConstant(1ULL << bits);
CSA_ASSERT(&csa, csa.IntPtrLessThan(
csa.ChangeInt32ToIntPtr(csa.Signed(data)), max_value));
#endif
csa.StoreToObject(mt.representation(), meta_table, offset, data,
StoreToObjectWriteBarrier::kNone);
}
void Store(TNode<ByteArray> meta_table, int index, TNode<Uint32T> data) {
Store(meta_table, csa.IntPtrConstant(index), data);
}
private:
TNode<IntPtrT> OverallOffset(TNode<ByteArray> meta_table,
TNode<IntPtrT> index) {
// TODO(v8:11330): consider using ElementOffsetFromIndex().
int offset_to_data_minus_tag = ByteArray::kHeaderSize - kHeapObjectTag;
TNode<IntPtrT> overall_offset;
int size = mt.MemSize();
intptr_t constant;
if (csa.TryToIntPtrConstant(index, &constant)) {
intptr_t index_offset = constant * size;
overall_offset =
csa.IntPtrConstant(offset_to_data_minus_tag + index_offset);
} else {
TNode<IntPtrT> index_offset =
csa.IntPtrMul(index, csa.IntPtrConstant(size));
overall_offset = csa.IntPtrAdd(
csa.IntPtrConstant(offset_to_data_minus_tag), index_offset);
}
#ifdef DEBUG
TNode<IntPtrT> byte_array_data_bytes =
csa.SmiToIntPtr(csa.LoadFixedArrayBaseLength(meta_table));
TNode<IntPtrT> max_allowed_offset = csa.IntPtrAdd(
byte_array_data_bytes, csa.IntPtrConstant(offset_to_data_minus_tag));
CSA_ASSERT(&csa, csa.UintPtrLessThan(overall_offset, max_allowed_offset));
#endif
return overall_offset;
}
CodeStubAssembler& csa;
MachineType mt;
};
// Type of functions that given a MetaTableAccessor, use its load and store
// functions to generate code for operating on the meta table.
using MetaTableAccessFunction = std::function<void(MetaTableAccessor&)>;
// Helper function for macros operating on the meta table of a
// SwissNameDictionary. Given a MetaTableAccessFunction, generates branching
// code and uses the builder to generate code for each of the three possible
// sizes per entry a meta table can have.
void GenerateMetaTableAccess(CodeStubAssembler* csa, TNode<IntPtrT> capacity,
MetaTableAccessFunction builder) {
MetaTableAccessor mta8 = MetaTableAccessor(*csa, MachineType::Uint8());
MetaTableAccessor mta16 = MetaTableAccessor(*csa, MachineType::Uint16());
MetaTableAccessor mta32 = MetaTableAccessor(*csa, MachineType::Uint32());
using Label = compiler::CodeAssemblerLabel;
Label small(csa), medium(csa), done(csa);
csa->GotoIf(
csa->IntPtrLessThanOrEqual(
capacity,
csa->IntPtrConstant(SwissNameDictionary::kMax1ByteMetaTableCapacity)),
&small);
csa->GotoIf(
csa->IntPtrLessThanOrEqual(
capacity,
csa->IntPtrConstant(SwissNameDictionary::kMax2ByteMetaTableCapacity)),
&medium);
builder(mta32);
csa->Goto(&done);
csa->Bind(&medium);
builder(mta16);
csa->Goto(&done);
csa->Bind(&small);
builder(mta8);
csa->Goto(&done);
csa->Bind(&done);
}
} // namespace
TNode<IntPtrT> CodeStubAssembler::LoadSwissNameDictionaryNumberOfElements(
TNode<SwissNameDictionary> table, TNode<IntPtrT> capacity) {
TNode<ByteArray> meta_table = LoadSwissNameDictionaryMetaTable(table);
TVARIABLE(Uint32T, nof, Uint32Constant(0));
MetaTableAccessFunction builder = [&](MetaTableAccessor& mta) {
nof = mta.Load(meta_table,
SwissNameDictionary::kMetaTableElementCountFieldIndex);
};
GenerateMetaTableAccess(this, capacity, builder);
return ChangeInt32ToIntPtr(nof.value());
}
TNode<IntPtrT>
CodeStubAssembler::LoadSwissNameDictionaryNumberOfDeletedElements(
TNode<SwissNameDictionary> table, TNode<IntPtrT> capacity) {
TNode<ByteArray> meta_table = LoadSwissNameDictionaryMetaTable(table);
TVARIABLE(Uint32T, nod, Uint32Constant(0));
MetaTableAccessFunction builder = [&](MetaTableAccessor& mta) {
nod =
mta.Load(meta_table,
SwissNameDictionary::kMetaTableDeletedElementCountFieldIndex);
};
GenerateMetaTableAccess(this, capacity, builder);
return ChangeInt32ToIntPtr(nod.value());
}
void CodeStubAssembler::StoreSwissNameDictionaryEnumToEntryMapping(
TNode<SwissNameDictionary> table, TNode<IntPtrT> capacity,
TNode<IntPtrT> enum_index, TNode<Int32T> entry) {
TNode<ByteArray> meta_table = LoadSwissNameDictionaryMetaTable(table);
TNode<IntPtrT> meta_table_index = IntPtrAdd(
IntPtrConstant(SwissNameDictionary::kMetaTableEnumerationDataStartIndex),
enum_index);
MetaTableAccessFunction builder = [&](MetaTableAccessor& mta) {
mta.Store(meta_table, meta_table_index, Unsigned(entry));
};
GenerateMetaTableAccess(this, capacity, builder);
}
TNode<Uint32T>
CodeStubAssembler::SwissNameDictionaryIncreaseElementCountOrBailout(
TNode<ByteArray> meta_table, TNode<IntPtrT> capacity,
TNode<Uint32T> max_usable_capacity, Label* bailout) {
TVARIABLE(Uint32T, used_var, Uint32Constant(0));
MetaTableAccessFunction builder = [&](MetaTableAccessor& mta) {
TNode<Uint32T> nof = mta.Load(
meta_table, SwissNameDictionary::kMetaTableElementCountFieldIndex);
TNode<Uint32T> nod =
mta.Load(meta_table,
SwissNameDictionary::kMetaTableDeletedElementCountFieldIndex);
TNode<Uint32T> used = Uint32Add(nof, nod);
GotoIf(Uint32GreaterThanOrEqual(used, max_usable_capacity), bailout);
TNode<Uint32T> inc_nof = Uint32Add(nof, Uint32Constant(1));
mta.Store(meta_table, SwissNameDictionary::kMetaTableElementCountFieldIndex,
inc_nof);
used_var = used;
};
GenerateMetaTableAccess(this, capacity, builder);
return used_var.value();
}
TNode<Uint32T> CodeStubAssembler::SwissNameDictionaryUpdateCountsForDeletion(
TNode<ByteArray> meta_table, TNode<IntPtrT> capacity) {
TVARIABLE(Uint32T, new_nof_var, Uint32Constant(0));
MetaTableAccessFunction builder = [&](MetaTableAccessor& mta) {
TNode<Uint32T> nof = mta.Load(
meta_table, SwissNameDictionary::kMetaTableElementCountFieldIndex);
TNode<Uint32T> nod =
mta.Load(meta_table,
SwissNameDictionary::kMetaTableDeletedElementCountFieldIndex);
TNode<Uint32T> new_nof = Uint32Sub(nof, Uint32Constant(1));
TNode<Uint32T> new_nod = Uint32Add(nod, Uint32Constant(1));
mta.Store(meta_table, SwissNameDictionary::kMetaTableElementCountFieldIndex,
new_nof);
mta.Store(meta_table,
SwissNameDictionary::kMetaTableDeletedElementCountFieldIndex,
new_nod);
new_nof_var = new_nof;
};
GenerateMetaTableAccess(this, capacity, builder);
return new_nof_var.value();
}
TNode<SwissNameDictionary> CodeStubAssembler::AllocateSwissNameDictionary(
TNode<IntPtrT> at_least_space_for) {
// TOOD(v8:11330) Dummy implementation until real version exists.
......
......@@ -3720,6 +3720,30 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<SwissNameDictionary> AllocateSwissNameDictionary(
int at_least_space_for);
TNode<IntPtrT> LoadSwissNameDictionaryNumberOfElements(
TNode<SwissNameDictionary> table, TNode<IntPtrT> capacity);
TNode<IntPtrT> LoadSwissNameDictionaryNumberOfDeletedElements(
TNode<SwissNameDictionary> table, TNode<IntPtrT> capacity);
// Specialized operation to be used when adding entries:
// If used capacity (= number of present + deleted elements) is less than
// |max_usable|, increment the number of present entries and return the used
// capacity value (prior to the incrementation). Otherwise, goto |bailout|.
TNode<Uint32T> SwissNameDictionaryIncreaseElementCountOrBailout(
TNode<ByteArray> meta_table, TNode<IntPtrT> capacity,
TNode<Uint32T> max_usable_capacity, Label* bailout);
// Specialized operation to be used when deleting entries: Decreases the
// number of present entries and increases the number of deleted ones. Returns
// new (= decremented) number of present entries.
TNode<Uint32T> SwissNameDictionaryUpdateCountsForDeletion(
TNode<ByteArray> meta_table, TNode<IntPtrT> capacity);
void StoreSwissNameDictionaryEnumToEntryMapping(
TNode<SwissNameDictionary> table, TNode<IntPtrT> capacity,
TNode<IntPtrT> enum_index, TNode<Int32T> entry);
TNode<Uint64T> LoadSwissNameDictionaryCtrlTableGroup(TNode<IntPtrT> address);
private:
......
......@@ -1011,6 +1011,11 @@ class V8_EXPORT_PRIVATE CodeAssembler {
static_cast<TNode<Word32T>>(right)));
}
TNode<Uint32T> Uint32Sub(TNode<Uint32T> left, TNode<Uint32T> right) {
return Unsigned(Int32Sub(static_cast<TNode<Word32T>>(left),
static_cast<TNode<Word32T>>(right)));
}
TNode<Int32T> Int32Sub(TNode<Int32T> left, TNode<Int32T> right) {
return Signed(Int32Sub(static_cast<TNode<Word32T>>(left),
static_cast<TNode<Word32T>>(right)));
......
......@@ -573,7 +573,7 @@ Handle<SwissNameDictionary> Factory::CreateCanonicalEmptySwissNameDictionary() {
ReadOnlyRoots roots(isolate());
Handle<ByteArray> empty_meta_table =
NewByteArray(SwissNameDictionary::kMetaTableEnumerationTableStartOffset,
NewByteArray(SwissNameDictionary::kMetaTableEnumerationDataStartIndex,
AllocationType::kReadOnly);
Map map = roots.swiss_name_dictionary_map();
......
......@@ -49,19 +49,19 @@ void SwissNameDictionary::SetCapacity(int capacity) {
}
int SwissNameDictionary::NumberOfElements() {
return GetMetaTableField(kMetaTableElementCountOffset);
return GetMetaTableField(kMetaTableElementCountFieldIndex);
}
int SwissNameDictionary::NumberOfDeletedElements() {
return GetMetaTableField(kMetaTableDeletedElementCountOffset);
return GetMetaTableField(kMetaTableDeletedElementCountFieldIndex);
}
void SwissNameDictionary::SetNumberOfElements(int elements) {
SetMetaTableField(kMetaTableElementCountOffset, elements);
SetMetaTableField(kMetaTableElementCountFieldIndex, elements);
}
void SwissNameDictionary::SetNumberOfDeletedElements(int deleted_elements) {
SetMetaTableField(kMetaTableDeletedElementCountOffset, deleted_elements);
SetMetaTableField(kMetaTableDeletedElementCountFieldIndex, deleted_elements);
}
int SwissNameDictionary::UsedCapacity() {
......@@ -132,7 +132,7 @@ int SwissNameDictionary::CapacityFor(int at_least_space_for) {
int SwissNameDictionary::EntryForEnumerationIndex(int enumeration_index) {
DCHECK_LT(enumeration_index, UsedCapacity());
return GetMetaTableField(kMetaTableEnumerationTableStartOffset +
return GetMetaTableField(kMetaTableEnumerationDataStartIndex +
enumeration_index);
}
......@@ -142,7 +142,7 @@ void SwissNameDictionary::SetEntryForEnumerationIndex(int enumeration_index,
DCHECK_LT(static_cast<unsigned>(entry), static_cast<unsigned>(Capacity()));
DCHECK(IsFull(GetCtrl(entry)));
SetMetaTableField(kMetaTableEnumerationTableStartOffset + enumeration_index,
SetMetaTableField(kMetaTableEnumerationDataStartIndex + enumeration_index,
entry);
}
......@@ -736,7 +736,7 @@ SwissNameDictionary::probe(uint32_t hash, int capacity) {
ACCESSORS_CHECKED2(SwissNameDictionary, meta_table, ByteArray,
MetaTablePointerOffset(), true,
value.length() >= kMetaTableEnumerationTableStartOffset)
value.length() >= kMetaTableEnumerationDataStartIndex)
} // namespace internal
} // namespace v8
......
......@@ -217,9 +217,17 @@ class V8_EXPORT_PRIVATE SwissNameDictionary : public HeapObject {
static constexpr int kDataTableKeyEntryIndex = 0;
static constexpr int kDataTableValueEntryIndex = kDataTableKeyEntryIndex + 1;
static constexpr int kMetaTableElementCountOffset = 0;
static constexpr int kMetaTableDeletedElementCountOffset = 1;
static constexpr int kMetaTableEnumerationTableStartOffset = 2;
// Field indices describing the layout of the meta table: A field index of i
// means that the corresponding meta table entry resides at an offset of {i *
// sizeof(uintX_t)} bytes from the beginning of the meta table. Here, the X in
// uintX_t can be 8, 16, or 32, and depends on the capacity of the overall
// SwissNameDictionary. See the section "Meta table" in the comment at the
// beginning of the SwissNameDictionary class in this file.
static constexpr int kMetaTableElementCountFieldIndex = 0;
static constexpr int kMetaTableDeletedElementCountFieldIndex = 1;
// Field index of the first entry of the enumeration table (which is part of
// the meta table).
static constexpr int kMetaTableEnumerationDataStartIndex = 2;
// The maximum capacity of any SwissNameDictionary whose meta table can use 1
// byte per entry.
......
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