static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v) { if (tv == (jl_value_t*)jl_sym_type) return ((jl_sym_t*)v)->hash; if (tv == (jl_value_t*)jl_simplevector_type) return hash_svec((jl_svec_t*)v); jl_datatype_t *dt = (jl_datatype_t*)tv; if (dt == jl_datatype_type) { jl_datatype_t *dtv = (jl_datatype_t*)v; // `name->wrapper` is cacheable even though it contains TypeVars // that don't have stable IDs. //if (jl_egal(dtv->name->wrapper, v)) // return bitmix(~dtv->name->hash, 0xaa5566aa); return bitmix(~dtv->name->hash, hash_svec(dtv->parameters)); } if (dt == jl_typename_type) return ((jl_typename_t*)v)->hash; #ifdef _P64 if (v == jl_ANY_flag) return 0x31c472f68ee30bddULL; #else if (v == jl_ANY_flag) return 0x8ee30bdd; #endif if (dt == jl_string_type) { #ifdef _P64 return memhash_seed(jl_string_data(v), jl_string_len(v), 0xedc3b677); #else return memhash32_seed(jl_string_data(v), jl_string_len(v), 0xedc3b677); #endif } if (dt->mutabl) return inthash((uintptr_t)v); size_t sz = jl_datatype_size(tv); uintptr_t h = jl_object_id(tv); if (sz == 0) return ~h; size_t nf = jl_datatype_nfields(dt); if (nf == 0) { return bits_hash(jl_data_ptr(v), sz) ^ h; } for (size_t f=0; f < nf; f++) { size_t offs = jl_field_offset(dt, f); char *vo = (char*)jl_data_ptr(v) + offs; uintptr_t u; if (jl_field_isptr(dt, f)) { jl_value_t *f = *(jl_value_t**)vo; u = f==NULL ? 0 : jl_object_id(f); } else { jl_datatype_t *fieldtype = (jl_datatype_t*)jl_field_type(dt, f); assert(jl_is_datatype(fieldtype) && !fieldtype->abstract && !fieldtype->mutabl); if (fieldtype->layout->haspadding) u = jl_object_id_((jl_value_t*)fieldtype, (jl_value_t*)vo); else u = bits_hash(vo, jl_field_size(dt, f)); } h = bitmix(h, u); } return h; }
static uintptr_t type_object_id_(jl_value_t *v, jl_varidx_t *env) { if (v == NULL) return 0; jl_datatype_t *tv = (jl_datatype_t*)jl_typeof(v); if (tv == jl_tvar_type) { jl_varidx_t *pe = env; int i = 0; while (pe != NULL) { if (pe->var == (jl_tvar_t*)v) return (i<<8) + 42; i++; pe = pe->prev; } return inthash((uintptr_t)v); } if (tv == jl_uniontype_type) { return bitmix(bitmix(jl_object_id((jl_value_t*)tv), type_object_id_(((jl_uniontype_t*)v)->a, env)), type_object_id_(((jl_uniontype_t*)v)->b, env)); } if (tv == jl_unionall_type) { jl_unionall_t *u = (jl_unionall_t*)v; uintptr_t h = u->var->name->hash; h = bitmix(h, type_object_id_(u->var->lb, env)); h = bitmix(h, type_object_id_(u->var->ub, env)); jl_varidx_t e = { u->var, env }; return bitmix(h, type_object_id_(u->body, &e)); } if (tv == jl_datatype_type) { uintptr_t h = ~((jl_datatype_t*)v)->name->hash; size_t i, l = jl_nparams(v); for (i = 0; i < l; i++) { h = bitmix(h, type_object_id_(jl_tparam(v, i), env)); } return h; } return jl_object_id_((jl_value_t*)tv, v); }
JL_DLLEXPORT uintptr_t jl_object_id(jl_value_t *v) { return jl_object_id_(jl_typeof(v), v); }