diff --git a/Makefile b/Makefile index 041c35374e3046..e96fa7ef69e0d1 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/base/inference.jl b/base/inference.jl index ae9c7f5e6a49e0..d5f55a2769006c 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -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 !== () diff --git a/src/dump.c b/src/dump.c index c32144b9115594..78d8268b5fd0ff 100644 --- a/src/dump.c +++ b/src/dump.c @@ -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) @@ -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); diff --git a/src/gf.c b/src/gf.c index 9ac811c5b3b536..e01dd9ee81c90a 100644 --- a/src/gf.c +++ b/src/gf.c @@ -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; @@ -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 || @@ -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); @@ -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; diff --git a/src/init.c b/src/init.c index aa92a14cb4fa5d..45152f3bc375a8 100644 --- a/src/init.c +++ b/src/init.c @@ -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)); diff --git a/src/julia_internal.h b/src/julia_internal.h index 97b332844afe9f..1e0b9e5883a8c8 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -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); diff --git a/src/toplevel.c b/src/toplevel.c index 2728dbec3efd8f..9a929a1d846096 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -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; @@ -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); }