static jl_typemap_entry_t *jl_typemap_node_assoc_exact(jl_typemap_entry_t *ml, jl_value_t **args, size_t n) { while (ml != (void*)jl_nothing) { size_t lensig = jl_datatype_nfields(ml->sig); if (lensig == n || (ml->va && lensig <= n+1)) { int ismatch; if (ml->simplesig != (void*)jl_nothing && !sig_match_simple(args, n, jl_svec_data(ml->simplesig->parameters), 0, jl_datatype_nfields(ml->simplesig))) ismatch = 0; else if (ml->isleafsig) ismatch = sig_match_leaf(args, jl_svec_data(ml->sig->parameters), n); else if (ml->issimplesig) ismatch = sig_match_simple(args, n, jl_svec_data(ml->sig->parameters), ml->va, lensig); else ismatch = jl_tuple_subtype(args, n, ml->sig, 1); if (ismatch) { size_t i, l; for (i = 0, l = jl_svec_len(ml->guardsigs); i < l; i++) { // checking guard entries require a more // expensive subtype check, since guard entries added for ANY might be // abstract. this fixed issue #12967. if (jl_tuple_subtype(args, n, (jl_tupletype_t*)jl_svecref(ml->guardsigs, i), 1)) { break; } } if (i == l) return ml; } } ml = ml->next; } return NULL; }
jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *ml, jl_value_t **args, size_t n) { // some manually-unrolled common special cases while (ml->simplesig == (void*)jl_nothing && ml->guardsigs == jl_emptysvec && ml->isleafsig) { // use a tight loop for a long as possible if (n == jl_field_count(ml->sig) && jl_typeof(args[0]) == jl_tparam(ml->sig, 0)) { if (n == 1) return ml; if (n == 2) { if (jl_typeof(args[1]) == jl_tparam(ml->sig, 1)) return ml; } else if (n == 3) { if (jl_typeof(args[1]) == jl_tparam(ml->sig, 1) && jl_typeof(args[2]) == jl_tparam(ml->sig, 2)) return ml; } else { if (sig_match_leaf(args, jl_svec_data(ml->sig->parameters), n)) return ml; } } ml = ml->next; if (ml == (void*)jl_nothing) return NULL; } while (ml != (void*)jl_nothing) { size_t lensig = jl_field_count(ml->sig); if (lensig == n || (ml->va && lensig <= n+1)) { if (ml->simplesig != (void*)jl_nothing) { size_t lensimplesig = jl_field_count(ml->simplesig); int isva = lensimplesig > 0 && jl_is_vararg_type(jl_tparam(ml->simplesig, lensimplesig - 1)); if (lensig == n || (isva && lensimplesig <= n + 1)) { if (!sig_match_simple(args, n, jl_svec_data(ml->simplesig->parameters), isva, lensimplesig)) goto nomatch; } else { goto nomatch; } } if (ml->isleafsig) { if (!sig_match_leaf(args, jl_svec_data(ml->sig->parameters), n)) goto nomatch; } else if (ml->issimplesig) { if (!sig_match_simple(args, n, jl_svec_data(ml->sig->parameters), ml->va, lensig)) goto nomatch; } else { if (!jl_tuple_subtype(args, n, ml->sig, 1)) goto nomatch; } size_t i, l; if (ml->guardsigs != jl_emptysvec) { for (i = 0, l = jl_svec_len(ml->guardsigs); i < l; i++) { // checking guard entries require a more // expensive subtype check, since guard entries added for ANY might be // abstract. this fixed issue #12967. if (jl_tuple_subtype(args, n, (jl_tupletype_t*)jl_svecref(ml->guardsigs, i), 1)) { goto nomatch; } } } return ml; } nomatch: ml = ml->next; } return NULL; }
jl_typemap_entry_t *jl_typemap_assoc_exact(union jl_typemap_t ml_or_cache, jl_value_t **args, size_t n, int8_t offs) { // NOTE: This function is a huge performance hot spot!! jl_typemap_entry_t *ml; if (jl_typeof(ml_or_cache.unknown) == (jl_value_t*)jl_typemap_level_type) { jl_typemap_level_t *cache = ml_or_cache.node; if (n > offs) { jl_value_t *a1 = args[offs]; jl_value_t *ty = (jl_value_t*)jl_typeof(a1); assert(jl_is_datatype(ty)); if (ty == (jl_value_t*)jl_datatype_type && cache->targ != (void*)jl_nothing) { ml_or_cache = mtcache_hash_lookup(cache->targ, a1, 1, offs); ml = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1); if (ml) return ml; } if (cache->arg1 != (void*)jl_nothing) { ml_or_cache = mtcache_hash_lookup(cache->arg1, ty, 0, offs); if (jl_typeof(ml_or_cache.unknown) == (jl_value_t*)jl_typemap_entry_type && ml_or_cache.leaf->simplesig == (void*)jl_nothing && offs < 2 && n > 1) { jl_value_t *a0 = args[1-offs]; jl_value_t *t0 = (jl_value_t*)jl_typeof(a0); if (ml_or_cache.leaf->next==(void*)jl_nothing && n==2 && jl_datatype_nfields(ml_or_cache.leaf->sig)==2 && jl_tparam(ml_or_cache.leaf->sig, 1 - offs) == t0) return ml_or_cache.leaf; if (n==3) { // some manually-unrolled common special cases jl_value_t *a2 = args[2]; if (!jl_is_tuple(a2)) { // issue #6426 jl_typemap_entry_t *mn = ml_or_cache.leaf; if (jl_datatype_nfields(mn->sig)==3 && jl_tparam(mn->sig,1-offs)==t0 && jl_tparam(mn->sig,2)==(jl_value_t*)jl_typeof(a2)) return mn; mn = mn->next; if (mn!=(void*)jl_nothing && jl_datatype_nfields(mn->sig)==3 && jl_tparam(mn->sig,1-offs)==t0 && jl_tparam(mn->sig,2)==(jl_value_t*)jl_typeof(a2)) return mn; } } } ml = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1); if (ml) return ml; } } ml = cache->linear; } else { ml = ml_or_cache.leaf; } while (ml != (void*)jl_nothing) { size_t lensig = jl_datatype_nfields(ml->sig); if (lensig == n || (ml->va && lensig <= n+1)) { int ismatch; if (ml->simplesig != (void*)jl_nothing && !sig_match_simple(args, n, jl_svec_data(ml->simplesig->parameters), 0, jl_datatype_nfields(ml->simplesig))) ismatch = 0; else if (ml->isleafsig) ismatch = sig_match_leaf(args, jl_svec_data(ml->sig->parameters), n); else if (ml->issimplesig) ismatch = sig_match_simple(args, n, jl_svec_data(ml->sig->parameters), ml->va, lensig); else ismatch = jl_tuple_subtype(args, n, ml->sig, 1); if (ismatch) { size_t i, l; for (i = 0, l = jl_svec_len(ml->guardsigs); i < l; i++) { // checking guard entries require a more // expensive subtype check, since guard entries added for ANY might be // abstract. this fixed issue #12967. if (jl_tuple_subtype(args, n, (jl_tupletype_t*)jl_svecref(ml->guardsigs, i), 1)) { break; } } if (i == l) return ml; } } ml = ml->next; } return NULL; }