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( ...@@ -8043,7 +8043,7 @@ TNode<Object> CodeStubAssembler::LoadValueByKeyIndex(
} }
template <> template <>
TNode<Object> CodeStubAssembler::LoadValueByKeyIndex( V8_EXPORT_PRIVATE TNode<Object> CodeStubAssembler::LoadValueByKeyIndex(
TNode<SwissNameDictionary> container, TNode<IntPtrT> key_index) { TNode<SwissNameDictionary> container, TNode<IntPtrT> key_index) {
TNode<IntPtrT> offset_minus_tag = SwissNameDictionaryOffsetIntoDataTableMT( TNode<IntPtrT> offset_minus_tag = SwissNameDictionaryOffsetIntoDataTableMT(
container, key_index, SwissNameDictionary::kDataTableValueEntryIndex); container, key_index, SwissNameDictionary::kDataTableValueEntryIndex);
...@@ -8064,7 +8064,7 @@ TNode<Uint32T> CodeStubAssembler::LoadDetailsByKeyIndex( ...@@ -8064,7 +8064,7 @@ TNode<Uint32T> CodeStubAssembler::LoadDetailsByKeyIndex(
} }
template <> template <>
TNode<Uint32T> CodeStubAssembler::LoadDetailsByKeyIndex( V8_EXPORT_PRIVATE TNode<Uint32T> CodeStubAssembler::LoadDetailsByKeyIndex(
TNode<SwissNameDictionary> container, TNode<IntPtrT> key_index) { TNode<SwissNameDictionary> container, TNode<IntPtrT> key_index) {
TNode<IntPtrT> capacity = TNode<IntPtrT> capacity =
ChangeInt32ToIntPtr(LoadSwissNameDictionaryCapacity(container)); ChangeInt32ToIntPtr(LoadSwissNameDictionaryCapacity(container));
...@@ -8084,7 +8084,7 @@ void CodeStubAssembler::StoreDetailsByKeyIndex(TNode<ContainerType> container, ...@@ -8084,7 +8084,7 @@ void CodeStubAssembler::StoreDetailsByKeyIndex(TNode<ContainerType> container,
} }
template <> template <>
void CodeStubAssembler::StoreDetailsByKeyIndex( V8_EXPORT_PRIVATE void CodeStubAssembler::StoreDetailsByKeyIndex(
TNode<SwissNameDictionary> container, TNode<IntPtrT> key_index, TNode<SwissNameDictionary> container, TNode<IntPtrT> key_index,
TNode<Smi> details) { TNode<Smi> details) {
TNode<IntPtrT> capacity = TNode<IntPtrT> capacity =
...@@ -8108,7 +8108,7 @@ void CodeStubAssembler::StoreValueByKeyIndex(TNode<ContainerType> container, ...@@ -8108,7 +8108,7 @@ void CodeStubAssembler::StoreValueByKeyIndex(TNode<ContainerType> container,
} }
template <> template <>
void CodeStubAssembler::StoreValueByKeyIndex( V8_EXPORT_PRIVATE void CodeStubAssembler::StoreValueByKeyIndex(
TNode<SwissNameDictionary> container, TNode<IntPtrT> key_index, TNode<SwissNameDictionary> container, TNode<IntPtrT> key_index,
TNode<Object> value, WriteBarrierMode write_barrier) { TNode<Object> value, WriteBarrierMode write_barrier) {
TNode<IntPtrT> offset_minus_tag = SwissNameDictionaryOffsetIntoDataTableMT( TNode<IntPtrT> offset_minus_tag = SwissNameDictionaryOffsetIntoDataTableMT(
...@@ -14480,10 +14480,10 @@ class MetaTableAccessor { ...@@ -14480,10 +14480,10 @@ class MetaTableAccessor {
#ifdef DEBUG #ifdef DEBUG
int bits = mt.MemSize() * 8; 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_ASSERT(&csa, csa.UintPtrLessThanOrEqual(csa.ChangeUint32ToWord(data),
csa.ChangeInt32ToIntPtr(csa.Signed(data)), max_value)); max_value));
#endif #endif
csa.StoreToObject(mt.representation(), meta_table, offset, data, csa.StoreToObject(mt.representation(), meta_table, offset, data,
...@@ -15146,5 +15146,31 @@ void CodeStubAssembler::SwissNameDictionarySetCtrl( ...@@ -15146,5 +15146,31 @@ void CodeStubAssembler::SwissNameDictionarySetCtrl(
StoreToObjectWriteBarrier::kNone); 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 internal
} // namespace v8 } // namespace v8
...@@ -3768,6 +3768,16 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -3768,6 +3768,16 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<SwissNameDictionary> CopySwissNameDictionary( TNode<SwissNameDictionary> CopySwissNameDictionary(
TNode<SwissNameDictionary> original); 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: private:
friend class CodeStubArguments; friend class CodeStubArguments;
......
...@@ -102,27 +102,4 @@ struct GroupPortableLoader { ...@@ -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 { ...@@ -204,6 +204,7 @@ class V8_EXPORT_PRIVATE SwissNameDictionary : public HeapObject {
static constexpr int kNotFoundSentinel = -1; static constexpr int kNotFoundSentinel = -1;
static const int kGroupWidth = Group::kWidth; static const int kGroupWidth = Group::kWidth;
static const bool kUseSIMD = kGroupWidth == 16;
class BodyDescriptor; class BodyDescriptor;
......
...@@ -277,64 +277,73 @@ macro SwissNameDictionaryDelete(table: SwissNameDictionary, entry: intptr) ...@@ -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 @export
macro SwissNameDictionaryFindEntry(table: SwissNameDictionary, key: Name): macro SwissNameDictionaryFindEntrySIMD(table: SwissNameDictionary, key: Name):
never labels Found(intptr), NotFound { never labels Found(intptr), NotFound {
try { // TODO(v8:11330) Not implemented in Torque, yet, doing runtime call
if (kUseSIMD) { // instead.
// TODO(v8:11330) Not implemented in Torque, yet, doing runtime call const res = runtime::SwissTableFindEntry(kNoContext, table, key);
// instead. if (res == kNotFoundSentinel) {
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 {
goto NotFound; goto NotFound;
} else {
goto Found(Convert<intptr>(res));
} }
} }
@export @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, table: SwissNameDictionary, key: Name, value: Object,
propertyDetails: uint8) labels Bailout { propertyDetails: uint8) labels Bailout {
try { // TODO(v8:11330) Not implemented in Torque, yet, doing runtime call
if (kUseSIMD) { // instead. However, must bailout if the runtime call would allocate a new
// TODO(v8:11330) Not implemented in Torque, yet, doing runtime call // dictionary.
// 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)));
} else { // Determine if bailout needed:
Add<GroupPortableLoader>(table, key, value, propertyDetails) const capacity = Convert<intptr>(table.capacity);
otherwise Bailout; const maxUsable = SwissNameDictionaryMaxUsableCapacity(capacity);
} // Doing two independent accesses to the meta table here (repeating the
} label Bailout { // 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; 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