Skip to content

Commit

Permalink
eliminate stage0 inference
Browse files Browse the repository at this point in the history
all it did was ensure that everything in specializations was inferred
and require a lot of complex infrastructure to make it acceptable to
replace a module during compilation

but instead we can just infer everything in specializations directly
  • Loading branch information
vtjnash committed Apr 19, 2016
1 parent 2aa5d4d commit 03fad40
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 138 deletions.
7 changes: 1 addition & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -211,16 +211,11 @@ CORE_SRCS := $(addprefix $(JULIAHOME)/, \
base/tuple.jl)
BASE_SRCS := $(shell find $(JULIAHOME)/base -name \*.jl)

$(build_private_libdir)/inference0.ji: $(CORE_SRCS) | $(build_private_libdir)
$(build_private_libdir)/inference.ji: $(CORE_SRCS) | $(build_private_libdir)
@$(call PRINT_JULIA, cd $(JULIAHOME)/base && \
$(call spawn,$(JULIA_EXECUTABLE)) -C $(JULIA_CPU_TARGET) --output-ji $(call cygpath_w,$@) -f \
coreimg.jl)

$(build_private_libdir)/inference.ji: $(build_private_libdir)/inference0.ji
@$(call PRINT_JULIA, cd $(JULIAHOME)/base && \
$(call spawn,$(JULIA_EXECUTABLE)) -C $(JULIA_CPU_TARGET) --output-ji $(call cygpath_w,$@) -f \
-J $(call cygpath_w,$<) coreimg.jl)

RELBUILDROOT := $(shell $(JULIAHOME)/contrib/relative_path.sh "$(JULIAHOME)/base" "$(BUILDROOT)/base/")
COMMA:=,
define sysimg_builder
Expand Down
2 changes: 1 addition & 1 deletion base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2055,7 +2055,7 @@ function type_annotate!(linfo::LambdaInfo, states::Array{Any,1}, sv::ANY, rettyp
for i = 1:nargs
decls[i] = states[1][i].typ
end
body = linfo.code
body = linfo.code::Array{Any,1}
for i=1:length(body)
st_i = states[i]
if st_i !== ()
Expand Down
111 changes: 0 additions & 111 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -1138,113 +1138,6 @@ static void jl_serialize_dependency_list(ios_t *s)
JL_GC_POP();
}

static int is_module_replaced(jl_module_t *m)
{
return (jl_value_t*)m != jl_get_global(m->parent, m->name);
}

static int type_has_replaced_module(jl_value_t *t)
{
if (jl_is_datatype(t)) {
jl_datatype_t *dt = (jl_datatype_t*)t;
if (is_module_replaced(dt->name->module))
return 1;
int i;
for(i=0; i < jl_nparams(dt); i++)
if (type_has_replaced_module(jl_tparam(dt,i)))
return 1;
}
// TODO: might eventually need to handle more types here
return 0;
}

static int remove_specializations_from_replaced_modules_visitor(jl_typemap_entry_t *l, void *closure)
{
jl_array_t *a = l->func.method->specializations;
if (a) {
size_t len = jl_array_len(a);
size_t i, insrt=0;
for(i=0; i < len; i++) {
jl_lambda_info_t *li = (jl_lambda_info_t*)jl_cellref(a, i);
if (!(li->rettype && type_has_replaced_module(li->rettype)) &&
!(li->specTypes && type_has_replaced_module((jl_value_t*)li->specTypes))) {
jl_cellset(a, insrt, li);
insrt++;
}
}
jl_array_del_end(a, len-insrt);
}
a = l->func.method->roots;
if (a) {
size_t len = jl_array_len(a);
size_t i;
for(i=0; i < len; i++) {
jl_value_t *ai = jl_cellref(a, i);
if (jl_is_type(ai) && type_has_replaced_module(ai))
jl_cellset(a, i, jl_nothing);
}
}
return 1;
}

static void remove_methods_from_replaced_modules_from_list(jl_typemap_entry_t **pl)
{
jl_typemap_entry_t *l = *pl;
while (l != (void*)jl_nothing) {
jl_module_t *m = NULL;
if (l->func.value) {
if (jl_is_method(l->func.value))
m = l->func.method->module;
else if (jl_is_lambda_info(l->func.value))
m = l->func.linfo->def->module;
}
if ((m != NULL && is_module_replaced(m)) ||
type_has_replaced_module((jl_value_t*)l->sig))
*pl = l->next;
else
pl = &l->next;
l = l->next;
}
}


static void remove_methods_from_replaced_modules_in_map(union jl_typemap_t *tc);
static void remove_methods_from_replaced_modules_from_array(jl_array_t *a)
{
jl_value_t **data;
size_t i, l = jl_array_len(a); data = (jl_value_t**)jl_array_data(a);
for(i=0; i < l; i++) {
if (data[i] != NULL)
remove_methods_from_replaced_modules_in_map((union jl_typemap_t*)&data[i]);
}
}

static void remove_methods_from_replaced_modules_in_map(union jl_typemap_t *tc)
{
jl_typemap_entry_t **pl;
if (jl_typeof(tc->unknown) == (jl_value_t*)jl_typemap_level_type) {
jl_typemap_level_t *cache = tc->node;
if ((jl_value_t*)cache->arg1 != jl_nothing)
remove_methods_from_replaced_modules_from_array(cache->arg1);
if ((jl_value_t*)cache->targ != jl_nothing)
remove_methods_from_replaced_modules_from_array(cache->targ);
pl = &cache->linear;
}
else {
pl = &tc->leaf;
}
remove_methods_from_replaced_modules_from_list(pl);
}

static void remove_methods_from_replaced_modules(jl_methtable_t *mt)
{
remove_methods_from_replaced_modules_in_map(&mt->defs);
remove_methods_from_replaced_modules_in_map(&mt->cache);
jl_typemap_visitor(mt->defs, remove_specializations_from_replaced_modules_visitor, NULL);
if (mt->kwsorter)
remove_methods_from_replaced_modules(jl_gf_mtable(mt->kwsorter));
}

// --- deserialize ---

static jl_fptr_t jl_deserialize_fptr(ios_t *s)
Expand Down Expand Up @@ -1974,10 +1867,6 @@ static void jl_save_system_image_to_stream(ios_t *f)
}
}

// remove constructors (which go in a single shared method table) from modules
// that were replaced during bootstrap.
remove_methods_from_replaced_modules(jl_datatype_type->name->mt);

jl_idtable_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("ObjectIdDict")) : NULL;

jl_serialize_value(f, jl_main_module);
Expand Down
79 changes: 75 additions & 4 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1177,10 +1177,18 @@ JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt, jl_tupletype_t
"def" is the original method definition of which this is an instance;
can be equal to "li->def" if not applicable.
*/
void jl_type_infer(jl_lambda_info_t *li)
void jl_type_infer(jl_lambda_info_t *li, int force)
{
#ifdef ENABLE_INFERENCE
if (jl_typeinf_func != NULL && (li->def == NULL || li->def->module != jl_gf_mtable(jl_typeinf_func)->module)) {
jl_module_t *mod = NULL;
if (li->def != NULL)
mod = li->def->module;
static int inInference = 0;
int lastIn = inInference;
inInference = 1;
if (jl_typeinf_func != NULL && (force ||
(mod != jl_gf_mtable(jl_typeinf_func)->module &&
(mod != jl_core_module || !lastIn)))) { // avoid any potential recursion in calling jl_typeinf_func on itself
JL_LOCK(codegen); // Might GC
assert(li->inInference == 0);
li->inInference = 1;
Expand All @@ -1196,9 +1204,72 @@ void jl_type_infer(jl_lambda_info_t *li)
assert(li->def || li->inInference == 0); // if this is toplevel expr, make sure inference finished
JL_UNLOCK(codegen);
}
inInference = lastIn;
#endif
}

static int get_method_unspec_list(jl_typemap_entry_t *def, void *closure)
{
jl_array_t *spec = def->func.method->specializations;
if (spec == NULL)
return 1;
size_t i, l;
for (i = 0, l = jl_array_len(spec); i < l; i++) {
jl_value_t *li = jl_cellref(spec, i);
if (jl_is_lambda_info(li) && !((jl_lambda_info_t*)li)->inferred)
jl_cell_1d_push(closure, li);
}
return 1;
}

static void jl_reset_mt_caches(jl_module_t *m, jl_array_t *unspec)
{
// removes all method caches
size_t i;
void **table = m->bindings.table;
for(i=1; i < m->bindings.size; i+=2) {
if (table[i] != HT_NOTFOUND) {
jl_binding_t *b = (jl_binding_t*)table[i];
if (b->owner == m && b->value && b->constp) {
if (jl_is_datatype(b->value)) {
jl_typename_t *tn = ((jl_datatype_t*)b->value)->name;
if (tn->module == m && tn->name == b->name) {
jl_methtable_t *mt = tn->mt;
if (mt != NULL && (jl_value_t*)mt != jl_nothing) {
if (mt->defs.unknown != jl_nothing) // make sure not to reset builtin functions
mt->cache.unknown = jl_nothing;
jl_typemap_visitor(mt->defs, get_method_unspec_list, (void*)unspec);
}
}
}
else if (jl_is_module(b->value)) {
jl_module_t *child = (jl_module_t*)b->value;
if (child != m && child->parent == m && child->name == b->name) {
// this is the original/primary binding for the submodule
jl_reset_mt_caches((jl_module_t*)b->value, unspec);
}
}
}
}
}
}

jl_function_t *jl_typeinf_func=NULL;

JL_DLLEXPORT void jl_set_typeinf_func(jl_value_t *f)
{
jl_typeinf_func = (jl_function_t*)f;
// give type inference a chance to see all of these
jl_array_t *unspec = jl_alloc_cell_1d(0);
JL_GC_PUSH1(&unspec);
jl_reset_mt_caches(jl_main_module, unspec);
size_t i, l;
for (i = 0, l = jl_array_len(unspec); i < l; i++) {
jl_type_infer((jl_lambda_info_t*)jl_cellref(unspec, i), 1);
}
JL_GC_POP();
}

static int very_general_type(jl_value_t *t)
{
return (t && (t==(jl_value_t*)jl_any_type || t == (jl_value_t*)jl_type_type ||
Expand Down Expand Up @@ -1569,7 +1640,7 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, union jl_typemap_t *ca
jl_gc_wb(definition, definition->specializations);
if (jl_options.compile_enabled != JL_OPTIONS_COMPILE_OFF) // don't bother with typeinf if compile is off
if (jl_symbol_name(definition->name)[0] != '@') // don't bother with typeinf on macros
jl_type_infer(newmeth);
jl_type_infer(newmeth, 0);
}
JL_GC_POP();
JL_UNLOCK(codegen);
Expand Down Expand Up @@ -2096,7 +2167,7 @@ static void _compile_all_deq(jl_array_t *found)

if (!linfo->inferred) {
// force this function to be recompiled
jl_type_infer(linfo);
jl_type_infer(linfo, 1);
linfo->functionObjectsDecls.functionObject = NULL;
linfo->functionObjectsDecls.specFunctionObject = NULL;
linfo->functionObjectsDecls.cFunctionList = NULL;
Expand Down
7 changes: 0 additions & 7 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -777,13 +777,6 @@ static void julia_save(void)
JL_GC_POP();
}

jl_function_t *jl_typeinf_func=NULL;

JL_DLLEXPORT void jl_set_typeinf_func(jl_value_t *f)
{
jl_typeinf_func = (jl_function_t*)f;
}

static jl_value_t *core(char *name)
{
return jl_get_global(jl_core_module, jl_symbol(name));
Expand Down
2 changes: 1 addition & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ jl_value_t *jl_interpret_toplevel_expr(jl_value_t *e);
jl_value_t *jl_static_eval(jl_value_t *ex, void *ctx_, jl_module_t *mod,
jl_lambda_info_t *li, int sparams, int allow_alloc);
int jl_is_toplevel_only_expr(jl_value_t *e);
void jl_type_infer(jl_lambda_info_t *li);
void jl_type_infer(jl_lambda_info_t *li, int force);
void jl_lambda_info_set_ast(jl_lambda_info_t *li, jl_value_t *ast);

jl_lambda_info_t *jl_get_unspecialized(jl_lambda_info_t *method);
Expand Down
13 changes: 5 additions & 8 deletions src/toplevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,12 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex)
jl_errorf("invalid redefinition of constant %s",
jl_symbol_name(name));
}
if (jl_generating_output() && jl_options.incremental) {
jl_errorf("cannot replace module %s during incremental compile",
jl_symbol_name(name));
}
if (!jl_generating_output()) {
// suppress warning "replacing module Core.Inference" during bootstrapping
jl_printf(JL_STDERR, "WARNING: replacing module %s\n",
if (jl_generating_output()) {
jl_errorf("cannot replace module %s during compilation",
jl_symbol_name(name));
}
jl_printf(JL_STDERR, "WARNING: replacing module %s\n",
jl_symbol_name(name));
}
jl_module_t *newm = jl_new_module(name);
newm->parent = parent_module;
Expand Down Expand Up @@ -544,7 +541,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast)

thk->specTypes = (jl_tupletype_t*)jl_typeof(jl_emptytuple); // no gc_wb needed
if (ewc) {
jl_type_infer(thk);
jl_type_infer(thk, 0);
jl_value_t *dummy_f_arg=NULL;
result = jl_call_method_internal(thk, &dummy_f_arg, 1);
}
Expand Down

0 comments on commit 03fad40

Please sign in to comment.