MCPcopy Create free account
hub / github.com/apache/tvm-ffi / HashObject

Method HashObject

src/ffi/extra/structural_hash.cc:105–169  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

103 }
104
105 uint64_t HashObject(const ObjectRef& obj) {
106 // NOTE: invariant: lhs and rhs are already the same type
107 const TVMFFITypeInfo* type_info = TVMFFIGetTypeInfo(obj->type_index());
108 if (type_info->metadata == nullptr) {
109 TVM_FFI_THROW(TypeError) << "Type metadata is not set for type `"
110 << String(type_info->type_key)
111 << "`, so StructuralHash is not supported for this type";
112 }
113 if (type_info->metadata->structural_eq_hash_kind == kTVMFFISEqHashKindUnsupported) {
114 TVM_FFI_THROW(TypeError) << "_type_s_eq_hash_kind is not set for type `"
115 << String(type_info->type_key)
116 << "`, so StructuralHash is not supported for this type";
117 }
118
119 auto structural_eq_hash_kind = type_info->metadata->structural_eq_hash_kind;
120 if (structural_eq_hash_kind == kTVMFFISEqHashKindUnsupported) {
121 // Fallback to pointer hash
122 return std::hash<const Object*>()(obj.get());
123 }
124 // return recored hash value if it is already computed
125 auto it = hash_memo_.find(obj);
126 if (it != hash_memo_.end()) {
127 return it->second;
128 }
129
130 uint64_t hash_value;
131 if (structural_eq_hash_kind != kTVMFFISEqHashKindFreeVar) {
132 hash_value = HashFields(obj, type_info, obj->GetTypeKeyHash());
133 } else {
134 // FreeVar path. In a non-recursive def region the FreeVar's own
135 // sub-fields are walked outside the def region (nested free vars
136 // there hash by pointer, matching use semantics), so we clamp
137 // ``def_region_kind_`` to ``kNone`` around the HashFields call and
138 // restore before the FreeVar-level injection below.
139 //
140 // We always call HashFields, even in use mode where the returned
141 // ``hash_value`` is discarded by the pointer-hash fallback. The
142 // walk's side effect on ``free_var_counter_`` (incremented for
143 // every nested FreeVar reached via SEqHashDef-tagged sub-fields)
144 // is observable to FreeVars hashed later in the same traversal;
145 // skipping the walk would silently change those subsequent hashes.
146 TVMFFIDefRegionKind saved_def_region_kind = def_region_kind_;
147 if (def_region_kind_ == kTVMFFIDefRegionKindNonRecursive) {
148 def_region_kind_ = kTVMFFIDefRegionKindNone;
149 }
150 hash_value = HashFields(obj, type_info, obj->GetTypeKeyHash());
151 def_region_kind_ = saved_def_region_kind;
152 if (def_region_kind_ != kTVMFFIDefRegionKindNone) {
153 // use lexical order of free var and its type
154 hash_value = details::StableHashCombine(hash_value, free_var_counter_++);
155 } else {
156 // Fallback to pointer hash; we are not in a def region.
157 hash_value = std::hash<const Object*>()(obj.get());
158 }
159 }
160
161 // if it is a DAG node, also record the lexical order of graph counter
162 // this helps to distinguish DAG from trees.

Callers

nothing calls this directly

Calls 8

TVMFFIGetTypeInfoFunction · 0.85
StableHashCombineFunction · 0.85
GetTypeKeyHashMethod · 0.80
StringClass · 0.50
type_indexMethod · 0.45
getMethod · 0.45
findMethod · 0.45
endMethod · 0.45

Tested by

no test coverage detected