@@ -35,28 +35,6 @@ JL_DLLEXPORT size_t jl_get_tls_world_age(void)
35
35
return jl_get_ptls_states ()-> world_age ;
36
36
}
37
37
38
- JL_DLLEXPORT jl_value_t * jl_invoke (jl_method_instance_t * meth , jl_value_t * * args , uint32_t nargs )
39
- {
40
- jl_callptr_t fptr = meth -> invoke ;
41
- if (fptr != jl_fptr_trampoline ) {
42
- return fptr (meth , args , nargs );
43
- }
44
- else {
45
- // if this hasn't been inferred (compiled) yet,
46
- // inferring it might not be able to handle the world range
47
- // so we just do a generic apply here
48
- // because that might actually be faster
49
- // since it can go through the unrolled caches for this world
50
- // and if inference is successful, this meth would get updated anyways,
51
- // and we'll get the fast path here next time
52
-
53
- // TODO: if `meth` came from an `invoke` call, we should make sure
54
- // meth->def is called instead of doing normal dispatch.
55
-
56
- return jl_apply (args , nargs );
57
- }
58
- }
59
-
60
38
/// ----- Handling for Julia callbacks ----- ///
61
39
62
40
JL_DLLEXPORT int8_t jl_is_in_pure_context (void )
@@ -2235,6 +2213,8 @@ JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup(jl_value_t *types JL_PROPAGATES_ROO
2235
2213
return (jl_value_t * )entry ;
2236
2214
}
2237
2215
2216
+ jl_value_t * jl_gf_invoke_by_method (jl_method_t * method , jl_value_t * * args , size_t nargs );
2217
+
2238
2218
// invoke()
2239
2219
// this does method dispatch with a set of types to match other than the
2240
2220
// types of the actual arguments. this means it sometimes does NOT call the
@@ -2247,13 +2227,10 @@ JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup(jl_value_t *types JL_PROPAGATES_ROO
2247
2227
jl_value_t * jl_gf_invoke (jl_value_t * types0 , jl_value_t * * args , size_t nargs )
2248
2228
{
2249
2229
size_t world = jl_get_ptls_states ()-> world_age ;
2250
- jl_svec_t * tpenv = jl_emptysvec ;
2251
- jl_tupletype_t * tt = NULL ;
2252
2230
jl_value_t * types = NULL ;
2253
- JL_GC_PUSH3 (& types , & tpenv , & tt );
2231
+ JL_GC_PUSH1 (& types );
2254
2232
jl_value_t * gf = args [0 ];
2255
2233
types = jl_argtype_with_function (gf , types0 );
2256
- jl_methtable_t * mt = jl_gf_mtable (gf );
2257
2234
jl_typemap_entry_t * entry = (jl_typemap_entry_t * )jl_gf_invoke_lookup (types , world );
2258
2235
2259
2236
if ((jl_value_t * )entry == jl_nothing ) {
@@ -2263,10 +2240,19 @@ jl_value_t *jl_gf_invoke(jl_value_t *types0, jl_value_t **args, size_t nargs)
2263
2240
2264
2241
// now we have found the matching definition.
2265
2242
// next look for or create a specialization of this definition.
2243
+ JL_GC_POP ();
2244
+ return jl_gf_invoke_by_method (entry -> func .method , args , nargs );
2245
+ }
2266
2246
2267
- jl_method_t * method = entry -> func .method ;
2247
+ jl_value_t * jl_gf_invoke_by_method (jl_method_t * method , jl_value_t * * args , size_t nargs )
2248
+ {
2249
+ size_t world = jl_get_ptls_states ()-> world_age ;
2268
2250
jl_method_instance_t * mfunc = NULL ;
2269
2251
jl_typemap_entry_t * tm = NULL ;
2252
+ jl_methtable_t * mt = jl_gf_mtable (args [0 ]);
2253
+ jl_svec_t * tpenv = jl_emptysvec ;
2254
+ jl_tupletype_t * tt = NULL ;
2255
+ JL_GC_PUSH2 (& tpenv , & tt );
2270
2256
if (method -> invokes != NULL )
2271
2257
tm = jl_typemap_assoc_exact (method -> invokes , args , nargs , jl_cachearg_offset (mt ), world );
2272
2258
if (tm ) {
@@ -2283,7 +2269,7 @@ jl_value_t *jl_gf_invoke(jl_value_t *types0, jl_value_t **args, size_t nargs)
2283
2269
if (method -> invokes == NULL )
2284
2270
method -> invokes = jl_nothing ;
2285
2271
2286
- mfunc = cache_method (mt , & method -> invokes , entry -> func . value , tt , method , world , tpenv , 1 );
2272
+ mfunc = cache_method (mt , & method -> invokes , ( jl_value_t * ) method , tt , method , world , tpenv , 1 );
2287
2273
JL_UNLOCK (& method -> writelock );
2288
2274
}
2289
2275
JL_GC_POP ();
@@ -2339,6 +2325,33 @@ JL_DLLEXPORT jl_value_t *jl_get_invoke_lambda(jl_methtable_t *mt,
2339
2325
return (jl_value_t * )mfunc ;
2340
2326
}
2341
2327
2328
+ JL_DLLEXPORT jl_value_t * jl_invoke (jl_method_instance_t * meth , jl_value_t * * args , uint32_t nargs )
2329
+ {
2330
+ jl_callptr_t fptr = meth -> invoke ;
2331
+ if (fptr != jl_fptr_trampoline ) {
2332
+ return fptr (meth , args , nargs );
2333
+ }
2334
+ else {
2335
+ // if this hasn't been inferred (compiled) yet,
2336
+ // inferring it might not be able to handle the world range
2337
+ // so we just do a generic apply here
2338
+ // because that might actually be faster
2339
+ // since it can go through the unrolled caches for this world
2340
+ // and if inference is successful, this meth would get updated anyways,
2341
+ // and we'll get the fast path here next time
2342
+
2343
+ jl_method_instance_t * mfunc = jl_lookup_generic_ (args , nargs ,
2344
+ jl_int32hash_fast (jl_return_address ()),
2345
+ jl_get_ptls_states ()-> world_age );
2346
+ // check whether `jl_apply_generic` would call the right method
2347
+ if (mfunc -> def .method == meth -> def .method )
2348
+ return mfunc -> invoke (mfunc , args , nargs );
2349
+
2350
+ // no; came from an `invoke` call
2351
+ return jl_gf_invoke_by_method (meth -> def .method , args , nargs );
2352
+ }
2353
+ }
2354
+
2342
2355
// Return value is rooted globally
2343
2356
jl_function_t * jl_new_generic_function_with_supertype (jl_sym_t * name , jl_module_t * module , jl_datatype_t * st , int iskw )
2344
2357
{
0 commit comments