Repository: JuliaLang/julia
File: src/gf.c (C)

Code before:

            /* outputs */
            /* .min_valid = */ *min_valid,
            /* .max_valid = */ *max_valid,
            /* .ti = */ NULL,
            /* .env = */ jl_emptysvec,
            /* .issubty = */ 0
        },
        /* inputs */
        intersections,
        world,
        lim,
        include_ambiguous,

        /* outputs */
        /* .t = */ jl_an_empty_vec_any,

        /* temporaries */
        /* .matc = */ NULL
    };
    struct jl_typemap_assoc search = {(jl_value_t*)type, world, jl_emptysvec};
    jl_value_t *isect2 = NULL;
    JL_GC_PUSH6(&env.t, &env.matc, &env.match.env, &search.env, &env.match.ti, &isect2);

    if (mt) {
        // first check the leaf cache if the type is small enough (may only match 1 method)
        if (((jl_datatype_t*)unw)->isdispatchtuple) {
            jl_genericmemory_t *leafcache = jl_atomic_load_relaxed(&mt->leafcache);
            jl_typemap_entry_t *entry = lookup_leafcache(leafcache, (jl_value_t*)type, world);
            if (entry) {
                // leafcache found a match, construct the MethodMatch by computing the effective
                // types + sparams and the world bounds
                jl_method_instance_t *mi = entry->func.linfo;
                jl_method_t *meth = mi->def.method;
                if (!jl_is_unionall(meth->sig)) {
                    env.match.env = jl_emptysvec;
                    env.match.ti = unw;
                }
                else if (jl_egal((jl_value_t*)type, mi->specTypes)) {
                    env.match.env = mi->sparam_vals;
                    env.match.ti = mi->specTypes;
                }
                else {
                    // this just calls jl_subtype_env (since we know that `type <: meth->sig` by transitivity)
                    env.match.ti = jl_type_intersection_env((jl_value_t*)type, (jl_value_t*)meth->sig, &env.match.env);
                }
                env.matc = make_method_match((jl_tupletype_t*)env.match.ti,
                    env.match.env, meth, FULLY_COVERS);
                env.t = (jl_value_t*)jl_alloc_vec_any(1);
                jl_array_ptr_set(env.t, 0, env.matc);
                size_t min_world = jl_atomic_load_relaxed(&entry->min_world);

Review comment (performance):
```suggestion
        // first check the leaf cache if the type might have been put in there
```
There are lot of different definitions of type "size", so it is not a useful term. It is legal and valid to check any type here against the cache, but since we (currently) only construct it with dispatch tuples, it is slightly wasteful to bother looking for anything else in there.

Code after:
        }
        if (entry) {
            // mfunc was found in slow path, so log --trace-dispatch
            jl_method_instance_t *mfunc = entry->func.linfo;
            record_dispatch_statement_on_first_dispatch(mfunc);
        }
    }

    jl_method_instance_t *mfunc;
    if (entry) {
have_entry:
        mfunc = entry->func.linfo;
    }
    else {
        assert(tt);
        // cache miss case
        jl_methcache_t *mc = jl_method_table->cache;
        mfunc = jl_mt_assoc_by_type(mc, tt, world);
        if (jl_options.malloc_log)
            jl_gc_sync_total_bytes(last_alloc); // discard allocation count from compilation
        if (mfunc == NULL) {
#ifdef JL_TRACE
            if (error_en)
                show_call(F, args, nargs);
#endif
            jl_method_error(F, args, nargs, world);
            // unreachable
        }
        // mfunc was found in slow path, so log --trace-dispatch
        record_dispatch_statement_on_first_dispatch(mfunc);
    }

#ifdef JL_TRACE
    if (traceen)
        jl_printf(JL_STDOUT, " at %s:%d\n", jl_symbol_name(mfunc->def.method->file), mfunc->def.method->line);
#endif

    return mfunc;
}

JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t *F, jl_value_t **args, uint32_t nargs)
{
    size_t world = jl_current_task->world_age;
    jl_method_instance_t *mfunc = jl_lookup_generic_(F, args, nargs,
                                                     jl_int32hash_fast(jl_return_address()),
                                                     world);
    JL_GC_PROMISE_ROOTED(mfunc);
    return _jl_invoke(F, args, nargs, mfunc, world);
}

static jl_method_match_t *_gf_invoke_lookup(jl_value_t *types JL_PROPAGATES_ROOT, jl_methtable_t *mt, size_t world, int cache_result, size_t *min_valid, size_t *max_valid)