Skip to content

Commit c93fc22

Browse files
committed
cleanup and review
1 parent 086e405 commit c93fc22

File tree

5 files changed

+79
-64
lines changed

5 files changed

+79
-64
lines changed

src/aotcompile.cpp

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ static void compile_workqueue(jl_codegen_params_t &params, CompilationPolicy pol
331331
while (!workqueue.empty()) {
332332
auto it = workqueue.pop_back_val();
333333
codeinst = it.first;
334-
auto proto = it.second;
334+
auto &proto = it.second;
335335
// try to emit code for this item from the workqueue
336336
StringRef invokeName = "";
337337
StringRef preal_decl = "";
@@ -370,30 +370,31 @@ static void compile_workqueue(jl_codegen_params_t &params, CompilationPolicy pol
370370
// patch up the prototype we emitted earlier
371371
Module *mod = proto.decl->getParent();
372372
assert(proto.decl->isDeclaration());
373-
Function *preal = nullptr;
374-
if (proto.specsig != preal_specsig || preal_decl.empty()) {
373+
Function *pinvoke = nullptr;
374+
if (preal_decl.empty()) {
375375
if (invokeName.empty() && params.params->trim) {
376376
errs() << "Bailed out to invoke when compiling:";
377377
jl_(codeinst->def);
378378
abort();
379379
}
380-
preal = emit_tojlinvoke(codeinst, invokeName, mod, params);
381-
if (proto.specsig) {
382-
// emit specsig-to-(jl)invoke conversion
383-
proto.decl->setLinkage(GlobalVariable::InternalLinkage);
384-
//protodecl->setAlwaysInline();
385-
jl_init_function(proto.decl, params.TargetTriple);
386-
jl_method_instance_t *mi = codeinst->def;
387-
size_t nrealargs = jl_nparams(mi->specTypes); // number of actual arguments being passed
388-
bool is_opaque_closure = jl_is_method(mi->def.value) && mi->def.method->is_for_opaque_closure;
389-
// TODO: maybe this can be cached in codeinst->specfptr?
390-
emit_cfunc_invalidate(proto.decl, proto.cc, proto.return_roots, mi->specTypes, codeinst->rettype, is_opaque_closure, nrealargs, params, preal, 0, 0);
391-
preal_decl = ""; // no need to fixup the name
392-
}
393-
else {
394-
// emit jlcall1-to-(jl)invoke conversion
395-
preal_decl = preal->getName();
396-
}
380+
pinvoke = emit_tojlinvoke(codeinst, invokeName, mod, params);
381+
if (!proto.specsig)
382+
proto.decl->replaceAllUsesWith(pinvoke);
383+
}
384+
if (proto.specsig && !preal_specsig) {
385+
// get or build an fptr1 that can invoke codeinst
386+
if (pinvoke == nullptr)
387+
pinvoke = get_or_emit_fptr1(preal_decl, mod);
388+
// emit specsig-to-(jl)invoke conversion
389+
proto.decl->setLinkage(GlobalVariable::InternalLinkage);
390+
//protodecl->setAlwaysInline();
391+
jl_init_function(proto.decl, params.TargetTriple);
392+
jl_method_instance_t *mi = codeinst->def;
393+
size_t nrealargs = jl_nparams(mi->specTypes); // number of actual arguments being passed
394+
bool is_opaque_closure = jl_is_method(mi->def.value) && mi->def.method->is_for_opaque_closure;
395+
// TODO: maybe this can be cached in codeinst->specfptr?
396+
emit_specsig_to_fptr1(proto.decl, proto.cc, proto.return_roots, mi->specTypes, codeinst->rettype, is_opaque_closure, nrealargs, params, pinvoke, 0, 0);
397+
preal_decl = ""; // no need to fixup the name
397398
}
398399
if (!preal_decl.empty()) {
399400
// merge and/or rename this prototype to the real function
@@ -410,11 +411,11 @@ static void compile_workqueue(jl_codegen_params_t &params, CompilationPolicy pol
410411
StringRef ocinvokeDecl = invokeName;
411412
// if OC expected a specialized specsig dispatch, but we don't have it, use the inner trampoline here too
412413
// XXX: this invoke translation logic is supposed to exactly match new_opaque_closure
413-
if (ocinvokeDecl == "jl_fptr_args")
414-
ocinvokeDecl = preal->getName(); // TODO: use the original preal_decl it computed from specsig
415-
else if (!preal_specsig || ocinvokeDecl == "jl_fptr_sparam" || ocinvokeDecl == "jl_f_opaque_closure_call" || ocinvokeDecl == "jl_fptr_interpret_call" || ocinvokeDecl == "jl_fptr_const_return")
416-
ocinvokeDecl = preal->getName();
414+
if (!preal_specsig || ocinvokeDecl == "jl_f_opaque_closure_call" || ocinvokeDecl == "jl_fptr_interpret_call" || ocinvokeDecl == "jl_fptr_const_return")
415+
ocinvokeDecl = pinvoke->getName();
417416
assert(!ocinvokeDecl.empty());
417+
assert(ocinvokeDecl != "jl_fptr_args");
418+
assert(ocinvokeDecl != "jl_fptr_sparam");
418419
// merge and/or rename this prototype to the real function
419420
if (Value *specfun = mod->getNamedValue(ocinvokeDecl)) {
420421
if (proto.oc != specfun)

src/codegen.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7151,6 +7151,11 @@ static Value *get_scope_field(jl_codectx_t &ctx)
71517151
return emit_ptrgep(ctx, ct, offsetof(jl_task_t, scope), "current_scope");
71527152
}
71537153

7154+
Function *get_or_emit_fptr1(StringRef preal_decl, Module *M)
7155+
{
7156+
return cast<Function>(M->getOrInsertFunction(preal_decl, get_func_sig(M->getContext()), get_func_attrs(M->getContext())).getCallee());
7157+
}
7158+
71547159
Function *emit_tojlinvoke(jl_code_instance_t *codeinst, StringRef theFptrName, Module *M, jl_codegen_params_t &params) JL_NOTSAFEPOINT
71557160
{
71567161
++EmittedToJLInvokes;
@@ -7200,7 +7205,7 @@ static jl_value_t *get_oc_type(jl_value_t *calltype, jl_value_t *rettype) JL_ALW
72007205
return oc_type;
72017206
}
72027207

7203-
void emit_cfunc_invalidate(
7208+
void emit_specsig_to_fptr1(
72047209
Function *gf_thunk, jl_returninfo_t::CallingConv cc, unsigned return_roots,
72057210
jl_value_t *calltype, jl_value_t *rettype, bool is_for_opaque_closure,
72067211
size_t nargs,
@@ -7696,7 +7701,7 @@ static Function* gen_cfun_wrapper(
76967701
// build a specsig -> jl_apply_generic converter thunk
76977702
// this builds a method that calls jl_apply_generic (as a closure over a singleton function pointer),
76987703
// but which has the signature of a specsig
7699-
emit_cfunc_invalidate(gf_thunk, returninfo.cc, returninfo.return_roots, lam->specTypes, codeinst->rettype, is_opaque_closure, nargs + 1, ctx.emission_context,
7704+
emit_specsig_to_fptr1(gf_thunk, returninfo.cc, returninfo.return_roots, lam->specTypes, codeinst->rettype, is_opaque_closure, nargs + 1, ctx.emission_context,
77007705
prepare_call_in(gf_thunk->getParent(), jlapplygeneric_func), min_world, max_world);
77017706
returninfo.decl = FunctionCallee(returninfo.decl.getFunctionType(), ctx.builder.CreateSelect(age_ok, returninfo.decl.getCallee(), gf_thunk));
77027707
}
@@ -10034,7 +10039,7 @@ static jl_llvm_functions_t jl_emit_oc_wrapper(orc::ThreadSafeModule &m, jl_codeg
1003410039
Function *gf_thunk = cast<Function>(returninfo.decl.getCallee());
1003510040
jl_init_function(gf_thunk, ctx.emission_context.TargetTriple);
1003610041
size_t nrealargs = jl_nparams(mi->specTypes);
10037-
emit_cfunc_invalidate(gf_thunk, returninfo.cc, returninfo.return_roots,
10042+
emit_specsig_to_fptr1(gf_thunk, returninfo.cc, returninfo.return_roots,
1003810043
mi->specTypes, rettype, true, nrealargs, ctx.emission_context,
1003910044
prepare_call_in(gf_thunk->getParent(), jlopaque_closure_call_func), // TODO: this could call emit_oc_call directly
1004010045
ctx.min_world, ctx.max_world);

src/jitlayers.cpp

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ static int jl_analyze_workqueue(jl_code_instance_t *callee, jl_codegen_params_t
273273
std::swap(params.workqueue, edges);
274274
for (auto &it : edges) {
275275
jl_code_instance_t *codeinst = it.first;
276-
auto proto = it.second;
276+
auto &proto = it.second;
277277
// try to emit code for this item from the workqueue
278278
StringRef invokeName = "";
279279
StringRef preal_decl = "";
@@ -316,38 +316,38 @@ static int jl_analyze_workqueue(jl_code_instance_t *callee, jl_codegen_params_t
316316
// if we have a prototype emitted, compare it to what we emitted earlier
317317
Module *mod = proto.decl->getParent();
318318
assert(proto.decl->isDeclaration());
319-
Function *preal = nullptr;
320-
if (proto.specsig != preal_specsig || preal_decl.empty()) {
321-
isedge = false;
319+
Function *pinvoke = nullptr;
320+
if (preal_decl.empty()) {
322321
if (invoke != nullptr && invokeName.empty()) {
323-
if (invoke == jl_fptr_args_addr)
324-
invokeName = "jl_fptr_args";
325-
else if (invoke == jl_fptr_sparam_addr)
322+
assert(invoke != jl_fptr_args_addr);
323+
if (invoke == jl_fptr_sparam_addr)
326324
invokeName = "jl_fptr_sparam";
327325
else if (invoke == jl_f_opaque_closure_call_addr)
328326
invokeName = "jl_f_opaque_closure_call";
329327
else
330328
invokeName = jl_ExecutionEngine->getFunctionAtAddress((uintptr_t)invoke, invoke, codeinst);
331329
}
332-
preal = emit_tojlinvoke(codeinst, invokeName, mod, params);
333-
if (proto.specsig) {
334-
// emit specsig-to-(jl)invoke conversion
335-
proto.decl->setLinkage(GlobalVariable::InternalLinkage);
336-
//protodecl->setAlwaysInline();
337-
jl_init_function(proto.decl, params.TargetTriple);
338-
// TODO: maybe this can be cached in codeinst->specfptr?
339-
int8_t gc_state = jl_gc_unsafe_enter(ct->ptls); // codegen may contain safepoints (such as jl_subtype calls)
340-
jl_method_instance_t *mi = codeinst->def;
341-
size_t nrealargs = jl_nparams(mi->specTypes); // number of actual arguments being passed
342-
bool is_opaque_closure = jl_is_method(mi->def.value) && mi->def.method->is_for_opaque_closure;
343-
emit_cfunc_invalidate(proto.decl, proto.cc, proto.return_roots, mi->specTypes, codeinst->rettype, is_opaque_closure, nrealargs, params, preal, 0, 0);
344-
jl_gc_unsafe_leave(ct->ptls, gc_state);
345-
preal_decl = ""; // no need to fixup the name
346-
}
347-
else {
348-
// emit jlcall1-to-(jl)invoke conversion
349-
preal_decl = preal->getName();
350-
}
330+
pinvoke = emit_tojlinvoke(codeinst, invokeName, mod, params);
331+
if (!proto.specsig)
332+
proto.decl->replaceAllUsesWith(pinvoke);
333+
isedge = false;
334+
}
335+
if (proto.specsig && !preal_specsig) {
336+
// get or build an fptr1 that can invoke codeinst
337+
if (pinvoke == nullptr)
338+
pinvoke = get_or_emit_fptr1(preal_decl, mod);
339+
// emit specsig-to-(jl)invoke conversion
340+
proto.decl->setLinkage(GlobalVariable::InternalLinkage);
341+
//protodecl->setAlwaysInline();
342+
jl_init_function(proto.decl, params.TargetTriple);
343+
// TODO: maybe this can be cached in codeinst->specfptr?
344+
int8_t gc_state = jl_gc_unsafe_enter(ct->ptls); // codegen may contain safepoints (such as jl_subtype calls)
345+
jl_method_instance_t *mi = codeinst->def;
346+
size_t nrealargs = jl_nparams(mi->specTypes); // number of actual arguments being passed
347+
bool is_opaque_closure = jl_is_method(mi->def.value) && mi->def.method->is_for_opaque_closure;
348+
emit_specsig_to_fptr1(proto.decl, proto.cc, proto.return_roots, mi->specTypes, codeinst->rettype, is_opaque_closure, nrealargs, params, pinvoke, 0, 0);
349+
jl_gc_unsafe_leave(ct->ptls, gc_state);
350+
preal_decl = ""; // no need to fixup the name
351351
}
352352
if (!preal_decl.empty()) {
353353
// merge and/or rename this prototype to the real function
@@ -359,26 +359,34 @@ static int jl_analyze_workqueue(jl_code_instance_t *callee, jl_codegen_params_t
359359
proto.decl->setName(preal_decl);
360360
}
361361
}
362-
if (proto.oc) { // additionally, if we are dealing with an oc, then we might also need to fix up the fptr1 reference too
362+
if (proto.oc) { // additionally, if we are dealing with an OC constructor, then we might also need to fix up the fptr1 reference too
363363
assert(proto.specsig);
364364
StringRef ocinvokeDecl = invokeName;
365365
if (invoke != nullptr && ocinvokeDecl.empty()) {
366-
if (invoke == jl_fptr_args_addr)
367-
ocinvokeDecl = "jl_fptr_args";
368-
else if (invoke == jl_fptr_sparam_addr)
369-
ocinvokeDecl = "jl_fptr_sparam";
366+
// check for some special tokens used by opaque_closure.c and convert those to their real functions
367+
assert(invoke != jl_fptr_args_addr);
368+
assert(invoke != jl_fptr_sparam_addr);
369+
if (invoke == jl_fptr_interpret_call_addr)
370+
ocinvokeDecl = "jl_fptr_interpret_call";
371+
else if (invoke == jl_fptr_const_return_addr)
372+
ocinvokeDecl = "jl_fptr_const_return";
370373
else if (invoke == jl_f_opaque_closure_call_addr)
371374
ocinvokeDecl = "jl_f_opaque_closure_call";
375+
//else if (invoke == jl_interpret_opaque_closure_addr)
372376
else
373377
ocinvokeDecl = jl_ExecutionEngine->getFunctionAtAddress((uintptr_t)invoke, invoke, codeinst);
374378
}
375379
// if OC expected a specialized specsig dispatch, but we don't have it, use the inner trampoline here too
376380
// XXX: this invoke translation logic is supposed to exactly match new_opaque_closure
377-
if (ocinvokeDecl == "jl_fptr_args")
378-
ocinvokeDecl = preal->getName(); // TODO: use the original preal_decl it computed from specsig
379-
else if (!preal_specsig || ocinvokeDecl == "jl_fptr_sparam" || ocinvokeDecl == "jl_f_opaque_closure_call" || ocinvokeDecl == "jl_fptr_interpret_call" || ocinvokeDecl == "jl_fptr_const_return")
380-
ocinvokeDecl = preal->getName();
381+
if (!preal_specsig || ocinvokeDecl == "jl_f_opaque_closure_call" || ocinvokeDecl == "jl_fptr_interpret_call" || ocinvokeDecl == "jl_fptr_const_return") {
382+
if (pinvoke == nullptr)
383+
ocinvokeDecl = get_or_emit_fptr1(preal_decl, mod)->getName();
384+
else
385+
ocinvokeDecl = pinvoke->getName();
386+
}
381387
assert(!ocinvokeDecl.empty());
388+
assert(ocinvokeDecl != "jl_fptr_args");
389+
assert(ocinvokeDecl != "jl_fptr_sparam");
382390
// merge and/or rename this prototype to the real function
383391
if (Value *specfun = mod->getNamedValue(ocinvokeDecl)) {
384392
if (proto.oc != specfun)

src/jitlayers.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,13 +281,14 @@ Function *jl_cfunction_object(jl_function_t *f, jl_value_t *rt, jl_tupletype_t *
281281
jl_codegen_params_t &params);
282282

283283
Function *emit_tojlinvoke(jl_code_instance_t *codeinst, StringRef theFptrName, Module *M, jl_codegen_params_t &params) JL_NOTSAFEPOINT;
284-
void emit_cfunc_invalidate(
284+
void emit_specsig_to_fptr1(
285285
Function *gf_thunk, jl_returninfo_t::CallingConv cc, unsigned return_roots,
286286
jl_value_t *calltype, jl_value_t *rettype, bool is_for_opaque_closure,
287287
size_t nargs,
288288
jl_codegen_params_t &params,
289289
Function *target,
290290
size_t min_world, size_t max_world) JL_NOTSAFEPOINT;
291+
Function *get_or_emit_fptr1(StringRef Name, Module *M) JL_NOTSAFEPOINT;
291292
void jl_init_function(Function *F, const Triple &TT) JL_NOTSAFEPOINT;
292293

293294
void add_named_global(StringRef name, void *addr) JL_NOTSAFEPOINT;

src/julia.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ typedef struct _jl_code_instance_t {
474474
// & 0b100 == From image
475475
_Atomic(uint8_t) precompile; // if set, this will be added to the output system image
476476
uint8_t relocatability; // nonzero if all roots are built into sysimg or tagged by module key
477-
_Atomic(jl_callptr_t) invoke; // jlcall entry point
477+
_Atomic(jl_callptr_t) invoke; // jlcall entry point usually, but if this codeinst belongs to an OC Method, then this is an jl_fptr_args_t fptr1 instead, unless it is not, because it is a special token object instead
478478
union _jl_generic_specptr_t {
479479
_Atomic(void*) fptr;
480480
_Atomic(jl_fptr_args_t) fptr1;

0 commit comments

Comments
 (0)