Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: use interpreter to execute functions that are all generic calls #15855

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ function _iisconst(s::Symbol, sv)
end

_ieval(x::ANY, sv) =
ccall(:jl_interpret_toplevel_expr_in, Any, (Any, Any, Any, Any),
sv.mod, x, svec(), svec())
ccall(:jl_interpret_toplevel_expr_in, Any, (Any, Any, Ptr{Void}),
sv.mod, x, C_NULL)

_topmod(sv::InferenceState) = _topmod(sv.mod)
_topmod(m::Module) = ccall(:jl_base_relative_to, Any, (Any,), m)::Module
Expand Down
74 changes: 54 additions & 20 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,8 @@ typedef struct {
int nReqArgs;
std::vector<bool> boundsCheck;
std::vector<bool> inbounds;
bool allGeneric;
int nGenericCalls;

CallInst *ptlsStates;
#ifdef JULIA_ENABLE_THREADING
Expand Down Expand Up @@ -847,29 +849,38 @@ static void to_function(jl_lambda_info_t *li)
JL_UNLOCK(codegen);
jl_rethrow_with_add("error compiling %s", jl_symbol_name(li->name));
}
// record that this function name came from this linfo,
// so we can build a reverse mapping for debug-info.
if (li->name != anonymous_sym) {
const DataLayout &DL =

if (li->jlcall_api != 2) {
// record that this function name came from this linfo,
// so we can build a reverse mapping for debug-info.
if (li->name != anonymous_sym) {
const DataLayout &DL =
#ifdef LLVM35
m->getDataLayout();
m->getDataLayout();
#else
*jl_data_layout;
*jl_data_layout;
#endif
// but don't remember anonymous symbols because
// they may not be rooted in the gc for the life of the program,
// and the runtime doesn't notify us when the code becomes unreachable :(
jl_add_linfo_in_flight((specf ? specf : f)->getName(), li, DL);
}
// but don't remember anonymous symbols because
// they may not be rooted in the gc for the life of the program,
// and the runtime doesn't notify us when the code becomes unreachable :(
jl_add_linfo_in_flight((specf ? specf : f)->getName(), li, DL);
}

// success. add the result to the execution engine now
jl_finalize_module(std::move(m));
li->functionID = jl_assign_functionID(f, 0);
if (specf)
li->specFunctionID = jl_assign_functionID(specf, 1);
if (f->getFunctionType() != jl_func_sig)
// mark the pointer as jl_fptr_sparam_t calling convention
li->jlcall_api = 1;
// success. add the result to the execution engine now
jl_finalize_module(std::move(m));

li->functionID = jl_assign_functionID(f, 0);
if (specf)
li->specFunctionID = jl_assign_functionID(specf, 1);
if (f->getFunctionType() != jl_func_sig)
// mark the pointer as jl_fptr_sparam_t calling convention
li->jlcall_api = 1;
}
else {
li->functionObjects.functionObject = NULL;
li->functionObjects.specFunctionObject = NULL;
li->functionObjects.cFunctionList = NULL;
}

// done compiling: restore global state
if (old != NULL) {
Expand Down Expand Up @@ -991,6 +1002,8 @@ uint64_t jl_get_llvm_fptr(llvm::Function *llvmf)
// and forces compilation of the lambda info
extern "C" void jl_generate_fptr(jl_lambda_info_t *li)
{
if (li->jlcall_api == 2)
return;
JL_LOCK(codegen);
// objective: assign li->fptr
assert(li->functionObjects.functionObject);
Expand All @@ -1009,6 +1022,8 @@ extern "C" void jl_generate_fptr(jl_lambda_info_t *li)
// or generate object code for it
extern "C" void jl_compile_linfo(jl_lambda_info_t *li)
{
if (li->jlcall_api == 2)
return;
if (li->functionObjects.functionObject == NULL) {
// objective: assign li->functionObject
to_function(li);
Expand Down Expand Up @@ -2782,6 +2797,7 @@ static jl_cgval_t emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx,
if (f != NULL) {
// function is a compile-time constant
if (jl_typeis(f, jl_intrinsic_type)) {
ctx->allGeneric = false;
result = emit_intrinsic((intrinsic)*(uint32_t*)jl_data_ptr(f), args, nargs, ctx);
if (result.typ == (jl_value_t*)jl_any_type) // the select_value intrinsic may be missing type information
result = remark_julia_type(result, expr_type(expr, ctx));
Expand All @@ -2791,16 +2807,23 @@ static jl_cgval_t emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx,
if (jl_subtype(f, (jl_value_t*)jl_builtin_type, 1)) {
bool handled = emit_builtin_call(&result, (jl_value_t*)f, args, nargs, ctx, expr);
if (handled) {
ctx->allGeneric = false;
JL_GC_POP();
return result;
}
}
if (ctx->allGeneric && (jl_is_topnode(args[0]) || jl_is_globalref(args[0]))) {
// inline called constants for the benefit of the interpreter
// TODO: nicer way to do this
args[0] = jl_new_struct(jl_quotenode_type, (jl_value_t*)f); jl_gc_wb(((jl_expr_t*)expr)->args, args[0]);
}
}

// special case for known builtin not handled by emit_builtin_call
if (f && jl_subtype(f, (jl_value_t*)jl_builtin_type, 1)) {
std::map<jl_fptr_t,Function*>::iterator it = builtin_func_map.find(jl_get_builtin_fptr(f));
if (it != builtin_func_map.end()) {
ctx->nGenericCalls++;
theFptr = (*it).second;
result = mark_julia_type(emit_jlcall(theFptr, V_null, &args[1], nargs, ctx), true, expr_type(expr,ctx), ctx);
JL_GC_POP();
Expand All @@ -2819,7 +2842,9 @@ static jl_cgval_t emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx,
jl_sprint((jl_value_t*)aty));
}*/
jl_lambda_info_t *li = jl_get_specialization1((jl_tupletype_t*)aty);
if (li != NULL) {
// TODO: if li->jlcall_api == 2 then directly call interpreter
if (li != NULL && li->jlcall_api != 2) {
ctx->allGeneric = false;
assert(li->functionObjects.functionObject != NULL);
theFptr = (Value*)li->functionObjects.functionObject;
jl_cgval_t fval;
Expand Down Expand Up @@ -2860,6 +2885,7 @@ static jl_cgval_t emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx,
myargs, ConstantInt::get(T_int32, nargs));
#endif
result = mark_julia_type(callval, true, expr_type(expr, ctx), ctx);
ctx->nGenericCalls++;

JL_GC_POP();
return result;
Expand Down Expand Up @@ -3333,6 +3359,7 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx)
return ghostValue(jl_void_type);
}
else if (head == static_typeof_sym) {
ctx->allGeneric = false;
jl_value_t *extype = expr_type((jl_value_t*)ex, ctx);
if (jl_is_type_type(extype)) {
extype = jl_tparam0(extype);
Expand Down Expand Up @@ -3952,6 +3979,8 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
ctx.inbounds.push_back(false);
ctx.boundsCheck.push_back(false);
ctx.spvals_ptr = NULL;
ctx.allGeneric = true;
ctx.nGenericCalls = 0;

// step 2. process var-info lists to see what vars need boxing
int n_gensyms = jl_is_long(lam->gensymtypes) ? jl_unbox_long(lam->gensymtypes) : jl_array_len(lam->gensymtypes);
Expand Down Expand Up @@ -4794,6 +4823,11 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func

JL_GC_POP();

if (ctx.allGeneric && ctx.nGenericCalls > 0) {
lam->jlcall_api = 2;
lam->code = code; jl_gc_wb(lam, lam->code);
}

return std::unique_ptr<Module>(M);
}

Expand Down
5 changes: 2 additions & 3 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -839,8 +839,7 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v)
// save functionObject pointers
write_int32(s, li->functionID);
write_int32(s, li->specFunctionID);
if (li->functionID)
write_int8(s, li->jlcall_api);
write_int8(s, li->jlcall_api);
write_int8(s, li->needs_sparam_vals_ducttape);
}
else if (jl_typeis(v, jl_module_type)) {
Expand Down Expand Up @@ -1473,7 +1472,7 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t
func_llvm = read_int32(s);
cfunc_llvm = read_int32(s);
jl_delayed_fptrs(li, func_llvm, cfunc_llvm);
li->jlcall_api = func_llvm ? read_int8(s) : 0;
li->jlcall_api = read_int8(s);
li->needs_sparam_vals_ducttape = read_int8(s);
return (jl_value_t*)li;
}
Expand Down
2 changes: 2 additions & 0 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,8 @@ static jl_value_t *jl_call_unspecialized(jl_svec_t *sparam_vals, jl_lambda_info_
assert(jl_svec_len(meth->sparam_syms) == jl_svec_len(sparam_vals));
if (__likely(meth->jlcall_api == 0))
return meth->fptr(args[0], &args[1], nargs-1);
else if (meth->jlcall_api == 2)
return jl_interpret_call(meth, args, nargs, sparam_vals);
else
return ((jl_fptr_sparam_t)meth->fptr)(sparam_vals, args[0], &args[1], nargs-1);
}
Expand Down
Loading