Skip to content

Commit 03fad40

Browse files
committed
eliminate stage0 inference
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
1 parent 2aa5d4d commit 03fad40

File tree

7 files changed

+83
-138
lines changed

7 files changed

+83
-138
lines changed

Makefile

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -211,16 +211,11 @@ CORE_SRCS := $(addprefix $(JULIAHOME)/, \
211211
base/tuple.jl)
212212
BASE_SRCS := $(shell find $(JULIAHOME)/base -name \*.jl)
213213

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

219-
$(build_private_libdir)/inference.ji: $(build_private_libdir)/inference0.ji
220-
@$(call PRINT_JULIA, cd $(JULIAHOME)/base && \
221-
$(call spawn,$(JULIA_EXECUTABLE)) -C $(JULIA_CPU_TARGET) --output-ji $(call cygpath_w,$@) -f \
222-
-J $(call cygpath_w,$<) coreimg.jl)
223-
224219
RELBUILDROOT := $(shell $(JULIAHOME)/contrib/relative_path.sh "$(JULIAHOME)/base" "$(BUILDROOT)/base/")
225220
COMMA:=,
226221
define sysimg_builder

base/inference.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2055,7 +2055,7 @@ function type_annotate!(linfo::LambdaInfo, states::Array{Any,1}, sv::ANY, rettyp
20552055
for i = 1:nargs
20562056
decls[i] = states[1][i].typ
20572057
end
2058-
body = linfo.code
2058+
body = linfo.code::Array{Any,1}
20592059
for i=1:length(body)
20602060
st_i = states[i]
20612061
if st_i !== ()

src/dump.c

Lines changed: 0 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,113 +1138,6 @@ static void jl_serialize_dependency_list(ios_t *s)
11381138
JL_GC_POP();
11391139
}
11401140

1141-
static int is_module_replaced(jl_module_t *m)
1142-
{
1143-
return (jl_value_t*)m != jl_get_global(m->parent, m->name);
1144-
}
1145-
1146-
static int type_has_replaced_module(jl_value_t *t)
1147-
{
1148-
if (jl_is_datatype(t)) {
1149-
jl_datatype_t *dt = (jl_datatype_t*)t;
1150-
if (is_module_replaced(dt->name->module))
1151-
return 1;
1152-
int i;
1153-
for(i=0; i < jl_nparams(dt); i++)
1154-
if (type_has_replaced_module(jl_tparam(dt,i)))
1155-
return 1;
1156-
}
1157-
// TODO: might eventually need to handle more types here
1158-
return 0;
1159-
}
1160-
1161-
static int remove_specializations_from_replaced_modules_visitor(jl_typemap_entry_t *l, void *closure)
1162-
{
1163-
jl_array_t *a = l->func.method->specializations;
1164-
if (a) {
1165-
size_t len = jl_array_len(a);
1166-
size_t i, insrt=0;
1167-
for(i=0; i < len; i++) {
1168-
jl_lambda_info_t *li = (jl_lambda_info_t*)jl_cellref(a, i);
1169-
if (!(li->rettype && type_has_replaced_module(li->rettype)) &&
1170-
!(li->specTypes && type_has_replaced_module((jl_value_t*)li->specTypes))) {
1171-
jl_cellset(a, insrt, li);
1172-
insrt++;
1173-
}
1174-
}
1175-
jl_array_del_end(a, len-insrt);
1176-
}
1177-
a = l->func.method->roots;
1178-
if (a) {
1179-
size_t len = jl_array_len(a);
1180-
size_t i;
1181-
for(i=0; i < len; i++) {
1182-
jl_value_t *ai = jl_cellref(a, i);
1183-
if (jl_is_type(ai) && type_has_replaced_module(ai))
1184-
jl_cellset(a, i, jl_nothing);
1185-
}
1186-
}
1187-
return 1;
1188-
}
1189-
1190-
static void remove_methods_from_replaced_modules_from_list(jl_typemap_entry_t **pl)
1191-
{
1192-
jl_typemap_entry_t *l = *pl;
1193-
while (l != (void*)jl_nothing) {
1194-
jl_module_t *m = NULL;
1195-
if (l->func.value) {
1196-
if (jl_is_method(l->func.value))
1197-
m = l->func.method->module;
1198-
else if (jl_is_lambda_info(l->func.value))
1199-
m = l->func.linfo->def->module;
1200-
}
1201-
if ((m != NULL && is_module_replaced(m)) ||
1202-
type_has_replaced_module((jl_value_t*)l->sig))
1203-
*pl = l->next;
1204-
else
1205-
pl = &l->next;
1206-
l = l->next;
1207-
}
1208-
}
1209-
1210-
1211-
static void remove_methods_from_replaced_modules_in_map(union jl_typemap_t *tc);
1212-
static void remove_methods_from_replaced_modules_from_array(jl_array_t *a)
1213-
{
1214-
jl_value_t **data;
1215-
size_t i, l = jl_array_len(a); data = (jl_value_t**)jl_array_data(a);
1216-
for(i=0; i < l; i++) {
1217-
if (data[i] != NULL)
1218-
remove_methods_from_replaced_modules_in_map((union jl_typemap_t*)&data[i]);
1219-
}
1220-
}
1221-
1222-
static void remove_methods_from_replaced_modules_in_map(union jl_typemap_t *tc)
1223-
{
1224-
jl_typemap_entry_t **pl;
1225-
if (jl_typeof(tc->unknown) == (jl_value_t*)jl_typemap_level_type) {
1226-
jl_typemap_level_t *cache = tc->node;
1227-
if ((jl_value_t*)cache->arg1 != jl_nothing)
1228-
remove_methods_from_replaced_modules_from_array(cache->arg1);
1229-
if ((jl_value_t*)cache->targ != jl_nothing)
1230-
remove_methods_from_replaced_modules_from_array(cache->targ);
1231-
pl = &cache->linear;
1232-
}
1233-
else {
1234-
pl = &tc->leaf;
1235-
}
1236-
remove_methods_from_replaced_modules_from_list(pl);
1237-
}
1238-
1239-
static void remove_methods_from_replaced_modules(jl_methtable_t *mt)
1240-
{
1241-
remove_methods_from_replaced_modules_in_map(&mt->defs);
1242-
remove_methods_from_replaced_modules_in_map(&mt->cache);
1243-
jl_typemap_visitor(mt->defs, remove_specializations_from_replaced_modules_visitor, NULL);
1244-
if (mt->kwsorter)
1245-
remove_methods_from_replaced_modules(jl_gf_mtable(mt->kwsorter));
1246-
}
1247-
12481141
// --- deserialize ---
12491142

12501143
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)
19741867
}
19751868
}
19761869

1977-
// remove constructors (which go in a single shared method table) from modules
1978-
// that were replaced during bootstrap.
1979-
remove_methods_from_replaced_modules(jl_datatype_type->name->mt);
1980-
19811870
jl_idtable_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("ObjectIdDict")) : NULL;
19821871

19831872
jl_serialize_value(f, jl_main_module);

src/gf.c

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,10 +1177,18 @@ JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt, jl_tupletype_t
11771177
"def" is the original method definition of which this is an instance;
11781178
can be equal to "li->def" if not applicable.
11791179
*/
1180-
void jl_type_infer(jl_lambda_info_t *li)
1180+
void jl_type_infer(jl_lambda_info_t *li, int force)
11811181
{
11821182
#ifdef ENABLE_INFERENCE
1183-
if (jl_typeinf_func != NULL && (li->def == NULL || li->def->module != jl_gf_mtable(jl_typeinf_func)->module)) {
1183+
jl_module_t *mod = NULL;
1184+
if (li->def != NULL)
1185+
mod = li->def->module;
1186+
static int inInference = 0;
1187+
int lastIn = inInference;
1188+
inInference = 1;
1189+
if (jl_typeinf_func != NULL && (force ||
1190+
(mod != jl_gf_mtable(jl_typeinf_func)->module &&
1191+
(mod != jl_core_module || !lastIn)))) { // avoid any potential recursion in calling jl_typeinf_func on itself
11841192
JL_LOCK(codegen); // Might GC
11851193
assert(li->inInference == 0);
11861194
li->inInference = 1;
@@ -1196,9 +1204,72 @@ void jl_type_infer(jl_lambda_info_t *li)
11961204
assert(li->def || li->inInference == 0); // if this is toplevel expr, make sure inference finished
11971205
JL_UNLOCK(codegen);
11981206
}
1207+
inInference = lastIn;
11991208
#endif
12001209
}
12011210

1211+
static int get_method_unspec_list(jl_typemap_entry_t *def, void *closure)
1212+
{
1213+
jl_array_t *spec = def->func.method->specializations;
1214+
if (spec == NULL)
1215+
return 1;
1216+
size_t i, l;
1217+
for (i = 0, l = jl_array_len(spec); i < l; i++) {
1218+
jl_value_t *li = jl_cellref(spec, i);
1219+
if (jl_is_lambda_info(li) && !((jl_lambda_info_t*)li)->inferred)
1220+
jl_cell_1d_push(closure, li);
1221+
}
1222+
return 1;
1223+
}
1224+
1225+
static void jl_reset_mt_caches(jl_module_t *m, jl_array_t *unspec)
1226+
{
1227+
// removes all method caches
1228+
size_t i;
1229+
void **table = m->bindings.table;
1230+
for(i=1; i < m->bindings.size; i+=2) {
1231+
if (table[i] != HT_NOTFOUND) {
1232+
jl_binding_t *b = (jl_binding_t*)table[i];
1233+
if (b->owner == m && b->value && b->constp) {
1234+
if (jl_is_datatype(b->value)) {
1235+
jl_typename_t *tn = ((jl_datatype_t*)b->value)->name;
1236+
if (tn->module == m && tn->name == b->name) {
1237+
jl_methtable_t *mt = tn->mt;
1238+
if (mt != NULL && (jl_value_t*)mt != jl_nothing) {
1239+
if (mt->defs.unknown != jl_nothing) // make sure not to reset builtin functions
1240+
mt->cache.unknown = jl_nothing;
1241+
jl_typemap_visitor(mt->defs, get_method_unspec_list, (void*)unspec);
1242+
}
1243+
}
1244+
}
1245+
else if (jl_is_module(b->value)) {
1246+
jl_module_t *child = (jl_module_t*)b->value;
1247+
if (child != m && child->parent == m && child->name == b->name) {
1248+
// this is the original/primary binding for the submodule
1249+
jl_reset_mt_caches((jl_module_t*)b->value, unspec);
1250+
}
1251+
}
1252+
}
1253+
}
1254+
}
1255+
}
1256+
1257+
jl_function_t *jl_typeinf_func=NULL;
1258+
1259+
JL_DLLEXPORT void jl_set_typeinf_func(jl_value_t *f)
1260+
{
1261+
jl_typeinf_func = (jl_function_t*)f;
1262+
// give type inference a chance to see all of these
1263+
jl_array_t *unspec = jl_alloc_cell_1d(0);
1264+
JL_GC_PUSH1(&unspec);
1265+
jl_reset_mt_caches(jl_main_module, unspec);
1266+
size_t i, l;
1267+
for (i = 0, l = jl_array_len(unspec); i < l; i++) {
1268+
jl_type_infer((jl_lambda_info_t*)jl_cellref(unspec, i), 1);
1269+
}
1270+
JL_GC_POP();
1271+
}
1272+
12021273
static int very_general_type(jl_value_t *t)
12031274
{
12041275
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
15691640
jl_gc_wb(definition, definition->specializations);
15701641
if (jl_options.compile_enabled != JL_OPTIONS_COMPILE_OFF) // don't bother with typeinf if compile is off
15711642
if (jl_symbol_name(definition->name)[0] != '@') // don't bother with typeinf on macros
1572-
jl_type_infer(newmeth);
1643+
jl_type_infer(newmeth, 0);
15731644
}
15741645
JL_GC_POP();
15751646
JL_UNLOCK(codegen);
@@ -2096,7 +2167,7 @@ static void _compile_all_deq(jl_array_t *found)
20962167

20972168
if (!linfo->inferred) {
20982169
// force this function to be recompiled
2099-
jl_type_infer(linfo);
2170+
jl_type_infer(linfo, 1);
21002171
linfo->functionObjectsDecls.functionObject = NULL;
21012172
linfo->functionObjectsDecls.specFunctionObject = NULL;
21022173
linfo->functionObjectsDecls.cFunctionList = NULL;

src/init.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -777,13 +777,6 @@ static void julia_save(void)
777777
JL_GC_POP();
778778
}
779779

780-
jl_function_t *jl_typeinf_func=NULL;
781-
782-
JL_DLLEXPORT void jl_set_typeinf_func(jl_value_t *f)
783-
{
784-
jl_typeinf_func = (jl_function_t*)f;
785-
}
786-
787780
static jl_value_t *core(char *name)
788781
{
789782
return jl_get_global(jl_core_module, jl_symbol(name));

src/julia_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ jl_value_t *jl_interpret_toplevel_expr(jl_value_t *e);
201201
jl_value_t *jl_static_eval(jl_value_t *ex, void *ctx_, jl_module_t *mod,
202202
jl_lambda_info_t *li, int sparams, int allow_alloc);
203203
int jl_is_toplevel_only_expr(jl_value_t *e);
204-
void jl_type_infer(jl_lambda_info_t *li);
204+
void jl_type_infer(jl_lambda_info_t *li, int force);
205205
void jl_lambda_info_set_ast(jl_lambda_info_t *li, jl_value_t *ast);
206206

207207
jl_lambda_info_t *jl_get_unspecialized(jl_lambda_info_t *method);

src/toplevel.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,12 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex)
118118
jl_errorf("invalid redefinition of constant %s",
119119
jl_symbol_name(name));
120120
}
121-
if (jl_generating_output() && jl_options.incremental) {
122-
jl_errorf("cannot replace module %s during incremental compile",
123-
jl_symbol_name(name));
124-
}
125-
if (!jl_generating_output()) {
126-
// suppress warning "replacing module Core.Inference" during bootstrapping
127-
jl_printf(JL_STDERR, "WARNING: replacing module %s\n",
121+
if (jl_generating_output()) {
122+
jl_errorf("cannot replace module %s during compilation",
128123
jl_symbol_name(name));
129124
}
125+
jl_printf(JL_STDERR, "WARNING: replacing module %s\n",
126+
jl_symbol_name(name));
130127
}
131128
jl_module_t *newm = jl_new_module(name);
132129
newm->parent = parent_module;
@@ -544,7 +541,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast)
544541

545542
thk->specTypes = (jl_tupletype_t*)jl_typeof(jl_emptytuple); // no gc_wb needed
546543
if (ewc) {
547-
jl_type_infer(thk);
544+
jl_type_infer(thk, 0);
548545
jl_value_t *dummy_f_arg=NULL;
549546
result = jl_call_method_internal(thk, &dummy_f_arg, 1);
550547
}

0 commit comments

Comments
 (0)