tint/castable: Add Maybe() MaybeAnyOf()
Moves hashcode bloom-filter type logic to helpers instead of inlining this stuff. Minor code cleanup. Change-Id: Id6816dd18445d1d1200a9d49f05cb803095b3d89 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/114341 Reviewed-by: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Kokoro: Ben Clayton <bclayton@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
55ceebec1e
commit
ea1cc79cb8
|
@ -86,11 +86,36 @@ enum CastFlags {
|
||||||
kDontErrorOnImpossibleCast = 1,
|
kDontErrorOnImpossibleCast = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The type of a hash code
|
||||||
|
using HashCode = uint64_t;
|
||||||
|
|
||||||
|
/// Maybe checks to see if an object with the full hashcode @p object_full_hashcode could
|
||||||
|
/// potentially be of, or derive from the type with the hashcode @p query_hashcode.
|
||||||
|
/// @param type_hashcode the hashcode of the type
|
||||||
|
/// @param object_full_hashcode the full hashcode of the object being queried
|
||||||
|
/// @returns true if the object with the given full hashcode could be one of the template types.
|
||||||
|
inline bool Maybe(HashCode type_hashcode, HashCode object_full_hashcode) {
|
||||||
|
return (object_full_hashcode & type_hashcode) == type_hashcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// MaybeAnyOf checks to see if an object with the full hashcode @p object_full_hashcode could
|
||||||
|
/// potentially be of, or derive from the types with the combined hashcode @p combined_hashcode.
|
||||||
|
/// @param combined_hashcode the bitwise OR'd hashcodes of the types
|
||||||
|
/// @param object_full_hashcode the full hashcode of the object being queried
|
||||||
|
/// @returns true if the object with the given full hashcode could be one of the template types.
|
||||||
|
inline bool MaybeAnyOf(HashCode combined_hashcode, HashCode object_full_hashcode) {
|
||||||
|
// Compare the object's hashcode to the bitwise-or of all the tested type's hashcodes. If
|
||||||
|
// there's no intersection of bits in the two masks, then we can guarantee that the type is not
|
||||||
|
// in `TO`.
|
||||||
|
HashCode mask = object_full_hashcode & combined_hashcode;
|
||||||
|
// HashCodeOf() ensures that two bits are always set for every hash, so we can quickly
|
||||||
|
// eliminate the bitmask where only one bit is set.
|
||||||
|
HashCode two_bits = mask & (mask - 1);
|
||||||
|
return two_bits != 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// TypeInfo holds type information for a Castable type.
|
/// TypeInfo holds type information for a Castable type.
|
||||||
struct TypeInfo {
|
struct TypeInfo {
|
||||||
/// The type of a hash code
|
|
||||||
using HashCode = uint64_t;
|
|
||||||
|
|
||||||
/// The base class of this type
|
/// The base class of this type
|
||||||
const TypeInfo* base;
|
const TypeInfo* base;
|
||||||
/// The type name
|
/// The type name
|
||||||
|
@ -133,10 +158,7 @@ struct TypeInfo {
|
||||||
/// @returns true if the class with this TypeInfo is of, or derives from the
|
/// @returns true if the class with this TypeInfo is of, or derives from the
|
||||||
/// class with the given TypeInfo.
|
/// class with the given TypeInfo.
|
||||||
inline bool Is(const tint::TypeInfo* type) const {
|
inline bool Is(const tint::TypeInfo* type) const {
|
||||||
// Optimization: Check whether the all the bits of the type's hashcode can be found in the
|
if (!Maybe(type->hashcode, full_hashcode)) {
|
||||||
// full_hashcode. If a single bit is missing, then we can quickly tell that that this
|
|
||||||
// TypeInfo does not derive from `type`.
|
|
||||||
if ((full_hashcode & type->hashcode) != type->hashcode) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,14 +243,7 @@ struct TypeInfo {
|
||||||
} else if constexpr (kCount == 1) {
|
} else if constexpr (kCount == 1) {
|
||||||
return Is(&Of<std::tuple_element_t<0, TUPLE>>());
|
return Is(&Of<std::tuple_element_t<0, TUPLE>>());
|
||||||
} else {
|
} else {
|
||||||
// Optimization: Compare the object's hashcode to the bitwise-or of all the tested
|
if (MaybeAnyOf(TypeInfo::CombinedHashCodeOfTuple<TUPLE>(), full_hashcode)) {
|
||||||
// type's hashcodes. If there's no intersection of bits in the two masks, then we can
|
|
||||||
// guarantee that the type is not in `TO`.
|
|
||||||
HashCode mask = full_hashcode & TypeInfo::CombinedHashCodeOfTuple<TUPLE>();
|
|
||||||
// HashCodeOf() ensures that two bits are always set for every hash, so we can quickly
|
|
||||||
// eliminate the bitmask where only one bit is set.
|
|
||||||
HashCode two_bits = mask & (mask - 1);
|
|
||||||
if (two_bits) {
|
|
||||||
// Possibly one of the types in `TUPLE`.
|
// Possibly one of the types in `TUPLE`.
|
||||||
// Split the search in two, and scan each block.
|
// Split the search in two, and scan each block.
|
||||||
static constexpr auto kMid = kCount / 2;
|
static constexpr auto kMid = kCount / 2;
|
||||||
|
@ -597,13 +612,8 @@ inline bool NonDefaultCases([[maybe_unused]] T* object,
|
||||||
// Multiple cases.
|
// Multiple cases.
|
||||||
// Check the hashcode bits to see if there's any possibility of a case matching in these
|
// Check the hashcode bits to see if there's any possibility of a case matching in these
|
||||||
// cases. If there isn't, we can skip all these cases.
|
// cases. If there isn't, we can skip all these cases.
|
||||||
TypeInfo::HashCode mask =
|
if (MaybeAnyOf(TypeInfo::CombinedHashCodeOf<SwitchCaseType<CASES>...>(),
|
||||||
type->full_hashcode & TypeInfo::CombinedHashCodeOf<SwitchCaseType<CASES>...>();
|
type->full_hashcode)) {
|
||||||
// HashCodeOf() ensures that two bits are always set for every hash, so we can quickly
|
|
||||||
// eliminate the bitmask where only one bit is set.
|
|
||||||
TypeInfo::HashCode two_bits = mask & (mask - 1);
|
|
||||||
if (two_bits) {
|
|
||||||
// There's a possibility. We need to scan further.
|
|
||||||
// Split the cases into two, and recurse.
|
// Split the cases into two, and recurse.
|
||||||
constexpr size_t kMid = kNumCases / 2;
|
constexpr size_t kMid = kNumCases / 2;
|
||||||
return NonDefaultCases(object, type, result, traits::Slice<0, kMid>(cases)) ||
|
return NonDefaultCases(object, type, result, traits::Slice<0, kMid>(cases)) ||
|
||||||
|
|
Loading…
Reference in New Issue