Skip to content

Commit

Permalink
add --compile={yes|no|all} option
Browse files Browse the repository at this point in the history
yes - default
no - turn JIT off
all - when building system image, compile exhaustively
an image built with compile=all can run with compile=no

make constructors work with static compilation, again
passing static parameters through closure environments

move ctor_factory to TypeName, since there is only one
per family of types anyway.
  • Loading branch information
JeffBezanson authored and Keno committed Aug 20, 2014
1 parent 114e4dc commit 4fbf716
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 85 deletions.
50 changes: 31 additions & 19 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -566,11 +566,13 @@ DLLEXPORT jl_sym_t *jl_tagged_gensym(const char *str, int32_t len)

jl_typename_t *jl_new_typename(jl_sym_t *name)
{
jl_typename_t *tn=(jl_typename_t*)newobj((jl_value_t*)jl_typename_type, 4);
jl_typename_t *tn=(jl_typename_t*)newobj((jl_value_t*)jl_typename_type, 6);
tn->name = name;
tn->module = jl_current_module;
tn->primary = NULL;
tn->cache = (jl_value_t*)jl_null;
tn->ctor_factory = (jl_value_t*)jl_null;
tn->static_ctor_factory = NULL;
return tn;
}

Expand All @@ -593,36 +595,47 @@ void jl_add_constructors(jl_datatype_t *t)

jl_initialize_generic_function((jl_function_t*)t, t->name->name);

if (t->ctor_factory == (jl_value_t*)jl_nothing ||
t->ctor_factory == (jl_value_t*)jl_null) {
if (t->name->ctor_factory == (jl_value_t*)jl_nothing ||
t->name->ctor_factory == (jl_value_t*)jl_null) {
}
else {
assert(jl_tuple_len(t->parameters) > 0);
if (t != (jl_datatype_t*)t->name->primary) {
if (t == (jl_datatype_t*)t->name->primary)
return;
jl_function_t *cfactory = NULL;
jl_tuple_t *env = NULL;
JL_GC_PUSH2(&cfactory, &env);
if (jl_compileropts.compile_enabled) {
// instantiating
assert(jl_is_function(t->ctor_factory));

assert(jl_is_function(t->name->ctor_factory));
// add type's static parameters to the ctor factory
size_t np = jl_tuple_len(t->parameters);
jl_tuple_t *sparams = jl_alloc_tuple_uninit(np*2);
jl_function_t *cfactory = NULL;
JL_GC_PUSH2(&sparams, &cfactory);
env = jl_alloc_tuple_uninit(np*2);
for(size_t i=0; i < np; i++) {
jl_tupleset(sparams, i*2+0,
jl_tupleset(env, i*2+0,
jl_tupleref(((jl_datatype_t*)t->name->primary)->parameters, i));
jl_tupleset(sparams, i*2+1,
jl_tupleset(env, i*2+1,
jl_tupleref(t->parameters, i));
}
cfactory = jl_instantiate_method((jl_function_t*)t->ctor_factory,
sparams);
cfactory = jl_instantiate_method((jl_function_t*)t->name->ctor_factory, env);
cfactory->linfo->ast = jl_prepare_ast(cfactory->linfo,
cfactory->linfo->sparams);

// call user-defined constructor factory on (type,)
jl_value_t *cfargs[1] = { (jl_value_t*)t };
jl_apply(cfactory, cfargs, 1);
JL_GC_POP();
}
else {
cfactory = ((jl_datatype_t*)t)->name->static_ctor_factory;
if (cfactory == NULL) {
JL_PRINTF(JL_STDERR,"code missing for type %s\n", t->name->name);
exit(1);
}
// in generically-compiled case, pass static parameters via closure
// environment.
env = jl_tuple_append((jl_tuple_t*)cfactory->env, t->parameters);
cfactory = jl_new_closure(cfactory->fptr, (jl_value_t*)env, cfactory->linfo);
}
// call user-defined constructor factory on (type,)
jl_value_t *cfargs[1] = { (jl_value_t*)t };
jl_apply(cfactory, cfargs, 1);
JL_GC_POP();
}
}

Expand Down Expand Up @@ -713,7 +726,6 @@ jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super,
t->fptr = jl_f_no_function;
t->env = (jl_value_t*)t;
t->linfo = NULL;
t->ctor_factory = (jl_value_t*)jl_null;
t->instance = NULL;
t->struct_decl = NULL;
t->size = 0;
Expand Down
7 changes: 2 additions & 5 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2172,11 +2172,8 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs,
break;
}
if (i > nargs) {
jl_value_t *ty =
jl_interpret_toplevel_expr_in(ctx->module, expr,
&jl_tupleref(ctx->sp,0),
jl_tuple_len(ctx->sp)/2);
if (jl_is_leaf_type(ty)) {
jl_value_t *ty = static_eval(expr, ctx, true, true);
if (ty!=NULL && jl_is_leaf_type(ty)) {
if (jl_has_typevars(ty)) {
// add root for types not cached. issue #7065
jl_add_linfo_root(ctx->linfo, ty);
Expand Down
2 changes: 0 additions & 2 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,6 @@ static void jl_serialize_datatype(ios_t *s, jl_datatype_t *dt)
jl_serialize_value(s, dt->parameters);
jl_serialize_value(s, dt->name);
jl_serialize_value(s, dt->super);
jl_serialize_value(s, dt->ctor_factory);
jl_serialize_value(s, dt->env);
jl_serialize_value(s, dt->linfo);
if (has_instance)
Expand Down Expand Up @@ -646,7 +645,6 @@ static jl_value_t *jl_deserialize_datatype(ios_t *s, int pos)
dt->parameters = (jl_tuple_t*)jl_deserialize_value(s);
dt->name = (jl_typename_t*)jl_deserialize_value(s);
dt->super = (jl_datatype_t*)jl_deserialize_value(s);
dt->ctor_factory = jl_deserialize_value(s);
dt->env = jl_deserialize_value(s);
dt->linfo = (jl_lambda_info_t*)jl_deserialize_value(s);
if (has_instance) {
Expand Down
122 changes: 87 additions & 35 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -798,15 +798,18 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type,
return newmeth;
}
else {
if (0 /* no jit mode */) {
if (jl_compileropts.compile_enabled == 0) {
if (method->linfo->unspecialized == NULL) {
// not yet handled
JL_PRINTF(JL_STDERR,"code missing for %s", method->linfo->name->name);
jl_static_show(JL_STDERR, (jl_value_t*)type);
JL_PRINTF(JL_STDERR, "\n");
exit(1);
}
newmeth = method->linfo->unspecialized;
jl_function_t *unspec = method->linfo->unspecialized;
if (method->env == (jl_value_t*)jl_null)
newmeth = unspec;
else
newmeth = jl_new_closure(unspec->fptr, method->env, unspec->linfo);

if (sparams != jl_null) {
temp = (jl_value_t*)jl_alloc_tuple(jl_tuple_len(sparams)/2);
Expand Down Expand Up @@ -1378,6 +1381,60 @@ jl_function_t *jl_get_specialization(jl_function_t *f, jl_tuple_t *types)

void jl_trampoline_compile_function(jl_function_t *f, int always_infer, jl_tuple_t *sig);

static void parameters_to_closureenv(jl_value_t *ast, jl_tuple_t *tvars)
{
jl_array_t *closed = jl_lam_capt((jl_expr_t*)ast);
jl_value_t **tvs;
int tvarslen;
if (jl_is_typevar(tvars)) {
tvs = (jl_value_t**)&tvars;
tvarslen = 1;
}
else {
tvs = &jl_t0(tvars);
tvarslen = jl_tuple_len(tvars);
}
size_t i;
jl_array_t *vi=NULL;
JL_GC_PUSH1(&vi);
for(i=0; i < tvarslen; i++) {
vi = jl_alloc_cell_1d(3);
jl_cellset(vi, 0, ((jl_tvar_t*)tvs[i])->name);
jl_cellset(vi, 1, jl_any_type);
jl_cellset(vi, 2, jl_box_long(1));
jl_cell_1d_push(closed, (jl_value_t*)vi);
}
JL_GC_POP();
}

static void all_p2c(jl_value_t *ast, jl_tuple_t *tvars)
{
if (jl_is_lambda_info(ast)) {
jl_lambda_info_t *li = (jl_lambda_info_t*)ast;
li->ast = jl_prepare_ast(li, jl_null);
parameters_to_closureenv(li->ast, tvars);
}
else if (jl_is_expr(ast)) {
jl_expr_t *e = (jl_expr_t*)ast;
for(size_t i=0; i < jl_array_len(e->args); i++)
all_p2c(jl_exprarg(e,i), tvars);
}
}

static void precompile_unspecialized(jl_function_t *func, jl_tuple_t *sig, jl_tuple_t *tvars)
{
func->linfo->specTypes = sig;
if (tvars != jl_null) {
// add static parameter names to end of closure env; compile
// assuming they are there. method cache will fill them in when
// it constructs closures for new "specializations".
func->linfo->ast = jl_prepare_ast(func->linfo, jl_null);
parameters_to_closureenv(func->linfo->ast, tvars);
all_p2c(func->linfo->ast, tvars);
}
jl_trampoline_compile_function(func, 1, sig ? sig : jl_tuple_type);
}

void jl_compile_all_defs(jl_function_t *gf)
{
assert(jl_is_gf(gf));
Expand All @@ -1392,33 +1449,7 @@ void jl_compile_all_defs(jl_function_t *gf)
else if (m->func->linfo->unspecialized == NULL) {
jl_function_t *func = jl_instantiate_method(m->func, jl_null);
m->func->linfo->unspecialized = func;
func->linfo->specTypes = m->sig;
if (m->tvars != jl_null) {
// add static parameter names to end of closure env; compile
// assuming they are there. method cache will fill them in when
// it constructs closures for new "specializations".
func->linfo->ast = jl_prepare_ast(func->linfo, jl_null);
jl_array_t *closed = jl_lam_capt((jl_expr_t*)func->linfo->ast);
jl_value_t **tvs;
int tvarslen;
if (jl_is_typevar(m->tvars)) {
tvs = (jl_value_t**)&m->tvars;
tvarslen = 1;
}
else {
tvs = &jl_t0(m->tvars);
tvarslen = jl_tuple_len(m->tvars);
}
size_t i;
for(i=0; i < tvarslen; i++) {
jl_array_t *vi = jl_alloc_cell_1d(3);
jl_cellset(vi, 0, ((jl_tvar_t*)tvs[i])->name);
jl_cellset(vi, 1, jl_any_type);
jl_cellset(vi, 2, jl_box_long(1));
jl_cell_1d_push(closed, (jl_value_t*)vi);
}
}
jl_trampoline_compile_function(func, 1, m->sig);
precompile_unspecialized(func, m->sig, m->tvars);
}
m = m->next;
}
Expand All @@ -1436,11 +1467,20 @@ static void _compile_all(jl_module_t *m, htable_t *h)
jl_binding_t *b = (jl_binding_t*)table[i];
if (b->value != NULL) {
jl_value_t *v = b->value;
if (jl_is_gf(v)) {
jl_compile_all_defs((jl_function_t*)v);
if (jl_is_datatype(v)) {
jl_datatype_t *dt = (jl_datatype_t*)v;
if (dt->fptr == jl_f_ctor_trampoline) {
jl_add_constructors(dt);
jl_compile_all_defs((jl_function_t*)dt);
}
if (v == dt->name->primary && dt->parameters != jl_null &&
jl_is_function(dt->name->ctor_factory) &&
dt->name->static_ctor_factory == NULL) {
dt->name->static_ctor_factory = jl_instantiate_method((jl_function_t*)dt->name->ctor_factory, jl_null);
precompile_unspecialized(dt->name->static_ctor_factory, NULL, dt->parameters);
}
}
else if (jl_is_datatype(v) && ((jl_function_t*)v)->fptr == jl_f_ctor_trampoline) {
jl_add_constructors((jl_datatype_t*)v);
if (jl_is_gf(v)) {
jl_compile_all_defs((jl_function_t*)v);
}
else if (jl_is_module(v)) {
Expand All @@ -1452,9 +1492,21 @@ static void _compile_all(jl_module_t *m, htable_t *h)
}
}
free(table);

if (m->constant_table != NULL) {
for(i=0; i < jl_array_len(m->constant_table); i++) {
jl_value_t *el = jl_cellref(m->constant_table,i);
if (jl_is_lambda_info(el)) {
jl_lambda_info_t *li = (jl_lambda_info_t*)el;
jl_function_t *func = jl_new_closure(li->fptr, (jl_value_t*)jl_null, li);
li->unspecialized = func;
precompile_unspecialized(func, NULL, jl_null);
}
}
}
}

void jl_compile_all()
void jl_compile_all(void)
{
htable_t h;
htable_new(&h, 0);
Expand Down
8 changes: 6 additions & 2 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ jl_compileropts_t jl_compileropts = { NULL, // build_path
0, // malloc_log
JL_COMPILEROPT_CHECK_BOUNDS_DEFAULT,
JL_COMPILEROPT_DUMPBITCODE_OFF,
0 // int32_literals
0, // int_literals
JL_COMPILEROPT_COMPILE_DEFAULT
};

int jl_boot_file_loaded = 0;
Expand Down Expand Up @@ -991,6 +992,8 @@ DLLEXPORT void jl_install_sigint_handler()
extern int asprintf(char **str, const char *fmt, ...);
extern void *__stack_chk_guard;

void jl_compile_all(void);

DLLEXPORT int julia_trampoline(int argc, char **argv, int (*pmain)(int ac,char *av[]))
{
#if defined(_OS_WINDOWS_)
Expand All @@ -1008,7 +1011,8 @@ DLLEXPORT int julia_trampoline(int argc, char **argv, int (*pmain)(int ac,char *
int ret = pmain(argc, argv);
char *build_path = jl_compileropts.build_path;
if (build_path) {
jl_compile_all();
if (jl_compileropts.compile_enabled == JL_COMPILEROPT_COMPILE_ALL)
jl_compile_all();
char *build_ji;
if (asprintf(&build_ji, "%s.ji",build_path) > 0) {
jl_save_system_image(build_ji);
Expand Down
4 changes: 2 additions & 2 deletions src/interpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
(jl_tuple_t*)temp, NULL,
0, args[6]==jl_true ? 1 : 0);
dt->fptr = jl_f_ctor_trampoline;
dt->ctor_factory = eval(args[3], locals, nl);
dt->name->ctor_factory = eval(args[3], locals, nl);

jl_binding_t *b = jl_get_binding_wr(jl_current_module, (jl_sym_t*)name);
temp = b->value; // save old value
Expand Down Expand Up @@ -413,7 +413,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
jl_add_constructors(dt);
}
else {
// TODO: remove all old ctors and set temp->ctor_factory = dt->ctor_factory
// TODO: remove all old ctors and set temp->name->ctor_factory = dt->name->ctor_factory
}

JL_GC_POP();
Expand Down
Loading

0 comments on commit 4fbf716

Please sign in to comment.