Commit 5d27e647 authored by Frank Emrich's avatar Frank Emrich Committed by Commit Bot

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

This CL enables proper testing for the CSA/Torque implementation of
SwissNameDictionary. This is done by changing the implementation of
test_swiss_hash_table::CSATestRunner.

This is the last CL of this series and concludes the CSA/Torque
implementation of SwissNameDictionary.

Bug: v8:11330
Change-Id: Ib46ef3a2c9ec9746591c2af94346be7d0382122b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2786843
Commit-Queue: Frank Emrich <emrich@google.com>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73685}
parent c71fe282
......@@ -8043,7 +8043,7 @@ TNode<Object> CodeStubAssembler::LoadValueByKeyIndex(
}
template <>
TNode<Object> CodeStubAssembler::LoadValueByKeyIndex(
V8_EXPORT_PRIVATE TNode<Object> CodeStubAssembler::LoadValueByKeyIndex(
TNode<SwissNameDictionary> container, TNode<IntPtrT> key_index) {
TNode<IntPtrT> offset_minus_tag = SwissNameDictionaryOffsetIntoDataTableMT(
container, key_index, SwissNameDictionary::kDataTableValueEntryIndex);
......@@ -8064,7 +8064,7 @@ TNode<Uint32T> CodeStubAssembler::LoadDetailsByKeyIndex(
}
template <>
TNode<Uint32T> CodeStubAssembler::LoadDetailsByKeyIndex(
V8_EXPORT_PRIVATE TNode<Uint32T> CodeStubAssembler::LoadDetailsByKeyIndex(
TNode<SwissNameDictionary> container, TNode<IntPtrT> key_index) {
TNode<IntPtrT> capacity =
ChangeInt32ToIntPtr(LoadSwissNameDictionaryCapacity(container));
......@@ -8084,7 +8084,7 @@ void CodeStubAssembler::StoreDetailsByKeyIndex(TNode<ContainerType> container,
}
template <>
void CodeStubAssembler::StoreDetailsByKeyIndex(
V8_EXPORT_PRIVATE void CodeStubAssembler::StoreDetailsByKeyIndex(
TNode<SwissNameDictionary> container, TNode<IntPtrT> key_index,
TNode<Smi> details) {
TNode<IntPtrT> capacity =
......@@ -8108,7 +8108,7 @@ void CodeStubAssembler::StoreValueByKeyIndex(TNode<ContainerType> container,
}
template <>
void CodeStubAssembler::StoreValueByKeyIndex(
V8_EXPORT_PRIVATE void CodeStubAssembler::StoreValueByKeyIndex(
TNode<SwissNameDictionary> container, TNode<IntPtrT> key_index,
TNode<Object> value, WriteBarrierMode write_barrier) {
TNode<IntPtrT> offset_minus_tag = SwissNameDictionaryOffsetIntoDataTableMT(
......@@ -14480,10 +14480,10 @@ class MetaTableAccessor {
#ifdef DEBUG
int bits = mt.MemSize() * 8;
TNode<IntPtrT> max_value = csa.IntPtrConstant(1ULL << bits);
TNode<UintPtrT> max_value = csa.UintPtrConstant((1ULL << bits) - 1);
CSA_ASSERT(&csa, csa.IntPtrLessThan(
csa.ChangeInt32ToIntPtr(csa.Signed(data)), max_value));
CSA_ASSERT(&csa, csa.UintPtrLessThanOrEqual(csa.ChangeUint32ToWord(data),
max_value));
#endif
csa.StoreToObject(mt.representation(), meta_table, offset, data,
......@@ -15146,5 +15146,31 @@ void CodeStubAssembler::SwissNameDictionarySetCtrl(
StoreToObjectWriteBarrier::kNone);
}
void CodeStubAssembler::SwissNameDictionaryFindEntry(
TNode<SwissNameDictionary> table, TNode<Name> key, Label* found,
TVariable<IntPtrT>* var_found_entry, Label* not_found) {
if (SwissNameDictionary::kUseSIMD) {
SwissNameDictionaryFindEntrySIMD(table, key, found, var_found_entry,
not_found);
} else {
SwissNameDictionaryFindEntryPortable(table, key, found, var_found_entry,
not_found);
}
}
void CodeStubAssembler::SwissNameDictionaryAdd(TNode<SwissNameDictionary> table,
TNode<Name> key,
TNode<Object> value,
TNode<Uint8T> property_details,
Label* needs_resize) {
if (SwissNameDictionary::kUseSIMD) {
SwissNameDictionaryAddSIMD(table, key, value, property_details,
needs_resize);
} else {
SwissNameDictionaryAddPortable(table, key, value, property_details,
needs_resize);
}
}
} // namespace internal
} // namespace v8
......@@ -3768,6 +3768,16 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<SwissNameDictionary> CopySwissNameDictionary(
TNode<SwissNameDictionary> original);
void SwissNameDictionaryFindEntry(TNode<SwissNameDictionary> table,
TNode<Name> key, Label* found,
TVariable<IntPtrT>* var_found_entry,
Label* not_found);
void SwissNameDictionaryAdd(TNode<SwissNameDictionary> table, TNode<Name> key,
TNode<Object> value,
TNode<Uint8T> property_details,
Label* needs_resize);
private:
friend class CodeStubArguments;
......
......@@ -102,27 +102,4 @@ struct GroupPortableLoader {
};
}
}
// TODO(v8:11330) Temporary nonsense code that supresses warnings about unused
// macros.
@export
macro SwissTableWarningSuppresser(): never {
const group = GroupPortableLoader{}.LoadGroup(0);
let mask = group.Match(0);
let seq = ProbeSequence{mask: 0, offset: 0, index: 0};
const _bla2 = group.MatchEmpty();
const _bla3 = H1(0);
const _bla4 = H2(0);
const _bla5 = seq.Next();
const _bla6 = seq.Offset(0);
const _bla7 = mask.HasBitsSet();
const _bla8 = mask.LowestBitSet();
const _bla9 = mask.ClearLowestSetBit();
unreachable;
}
}
......@@ -204,6 +204,7 @@ class V8_EXPORT_PRIVATE SwissNameDictionary : public HeapObject {
static constexpr int kNotFoundSentinel = -1;
static const int kGroupWidth = Group::kWidth;
static const bool kUseSIMD = kGroupWidth == 16;
class BodyDescriptor;
......
......@@ -277,64 +277,73 @@ macro SwissNameDictionaryDelete(table: SwissNameDictionary, entry: intptr)
}
}
// TODO(v8:11330) Ideally, we would like to implement
// CodeStubAssembler::SwissNameDictionaryFindEntry in Torque and do the
// necessary switching between the two implementations with if(kUseSimd) {...}
// else {...}. However, Torque currently generates a call to
// CodeAssembler::Branch which cannot guarantee that code for the "bad" path is
// not generated, even if the branch can be resolved at compile time. This means
// that we end up trying to generate unused code using unsupported instructions.
@export
macro SwissNameDictionaryFindEntry(table: SwissNameDictionary, key: Name):
macro SwissNameDictionaryFindEntrySIMD(table: SwissNameDictionary, key: Name):
never labels Found(intptr), NotFound {
try {
if (kUseSIMD) {
// TODO(v8:11330) Not implemented in Torque, yet, doing runtime call
// instead.
const res = runtime::SwissTableFindEntry(kNoContext, table, key);
if (res == kNotFoundSentinel) {
goto NotFound;
} else {
goto Found(Convert<intptr>(res));
}
} else {
FindEntry<GroupPortableLoader>(table, key)
otherwise Found, NotFound;
}
} label Found(index: intptr) {
goto Found(index);
} label NotFound {
// TODO(v8:11330) Not implemented in Torque, yet, doing runtime call
// instead.
const res = runtime::SwissTableFindEntry(kNoContext, table, key);
if (res == kNotFoundSentinel) {
goto NotFound;
} else {
goto Found(Convert<intptr>(res));
}
}
@export
macro SwissNameDictionaryAdd(
macro SwissNameDictionaryFindEntryPortable(
table: SwissNameDictionary, key: Name): never labels
Found(intptr),
NotFound {
FindEntry<GroupPortableLoader>(table, key)
otherwise Found, NotFound;
}
// TODO(v8:11330) Ideally, we would like to implement
// CodeStubAssembler::SwissNameDictionaryAdd in Torque and do the necessary
// switching between the two implementations with if(kUseSimd) {...} else {...}.
// However, Torque currently generates a call to CodeAssembler::Branch which
// cannot guarantee that code for the "bad" path is not generated, even if the
// branch can be resolved at compile time. This means that we end up trying to
// generate unused code using unsupported instructions.
@export
macro SwissNameDictionaryAddSIMD(
table: SwissNameDictionary, key: Name, value: Object,
propertyDetails: uint8) labels Bailout {
try {
if (kUseSIMD) {
// TODO(v8:11330) Not implemented in Torque, yet, doing runtime call
// instead. However, must bailout if the runtime call would allocate a new
// dictionary.
// Determine if bailout needed:
const capacity = Convert<intptr>(table.capacity);
const maxUsable = SwissNameDictionaryMaxUsableCapacity(capacity);
// Doing two independent accesses to the meta table here (repeating the
// branching), rather than combining the accesses. Accepting that due to
// the fact that this is a slow placeholder until the SIMD version
// replaces it.
const nof = LoadSwissNameDictionaryNumberOfElements(table, capacity);
const nod =
LoadSwissNameDictionaryNumberOfDeletedElements(table, capacity);
const used = nof + nod;
if (used >= maxUsable) {
goto Bailout;
}
runtime::SwissTableAdd(
kNoContext, table, key, value,
Convert<Smi>(Convert<int32>(propertyDetails)));
// TODO(v8:11330) Not implemented in Torque, yet, doing runtime call
// instead. However, must bailout if the runtime call would allocate a new
// dictionary.
} else {
Add<GroupPortableLoader>(table, key, value, propertyDetails)
otherwise Bailout;
}
} label Bailout {
// Determine if bailout needed:
const capacity = Convert<intptr>(table.capacity);
const maxUsable = SwissNameDictionaryMaxUsableCapacity(capacity);
// Doing two independent accesses to the meta table here (repeating the
// branching), rather than combining the accesses. Accepting that due to
// the fact that this is a slow placeholder until the SIMD version
// replaces it.
const nof = LoadSwissNameDictionaryNumberOfElements(table, capacity);
const nod = LoadSwissNameDictionaryNumberOfDeletedElements(table, capacity);
const used = nof + nod;
if (used >= maxUsable) {
goto Bailout;
}
runtime::SwissTableAdd(
kNoContext, table, key, value,
Convert<Smi>(Convert<int32>(propertyDetails)));
}
@export
macro SwissNameDictionaryAddPortable(
table: SwissNameDictionary, key: Name, value: Object,
propertyDetails: uint8) labels Bailout {
Add<GroupPortableLoader>(table, key, value, propertyDetails)
otherwise Bailout;
}
}
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