diff --git a/src/ast.c b/src/ast.c index 9cd837046dff0..15b92f286585c 100644 --- a/src/ast.c +++ b/src/ast.c @@ -380,15 +380,22 @@ static jl_value_t *scm_to_julia_(value_t e, int eo) } static value_t julia_to_scm_(jl_value_t *v); +typedef struct { + ssize_t idx; + size_t val; +} jlgensym_str; + static arraylist_t jlgensym_to_flisp; static value_t julia_to_scm(jl_value_t *v) { value_t temp; - if (jlgensym_to_flisp.len) - jlgensym_to_flisp.len = 0; // in case we didn't free it last time we got here (for example, if we threw an error) - else - arraylist_new(&jlgensym_to_flisp, 0); + if (jlgensym_to_flisp.len) { + // in case we didn't free it last time we got here (for example, if we threw an error) + jlgensym_to_flisp.len = 0; + } else { + arraylist_str(&jlgensym_to_flisp, 0, sizeof(jlgensym_str)); + } // need try/catch to reset GC handle stack in case of error FL_TRY_EXTERN { temp = julia_to_scm_(v); @@ -405,7 +412,7 @@ static void array_to_list(jl_array_t *a, value_t *pv) if (jl_array_len(a) > 300000) lerror(OutOfMemoryError, "expression too large"); value_t temp; - for(long i=jl_array_len(a)-1; i >= 0; i--) { + for (long i=jl_array_len(a)-1; i >= 0; i--) { *pv = fl_cons(FL_NIL, *pv); temp = julia_to_scm_(jl_cellref(a,i)); // note: must be separate statement @@ -429,15 +436,18 @@ static value_t julia_to_scm_(jl_value_t *v) return symbol(((jl_sym_t*)v)->name); if (jl_is_gensym(v)) { size_t idx = ((jl_gensym_t*)v)->id; - size_t i; - for (i = 0; i < jlgensym_to_flisp.len; i+=2) { - if ((ssize_t)jlgensym_to_flisp.items[i] == idx) - return fl_list2(fl_jlgensym_sym, fixnum((size_t)jlgensym_to_flisp.items[i+1])); + size_t len = jlgensym_to_flisp.len; + if (len) { + jlgensym_str *jlgenp = (jlgensym_str *)jlgensym_to_flisp.items; + do { + if (jlgenp->idx == idx) return fl_list2(fl_jlgensym_sym, fixnum(jlgenp->val)); + jlgenp++; + } while (--len); } - arraylist_push(&jlgensym_to_flisp, (void*)idx); value_t flv = fl_applyn(0, symbol_value(symbol("make-jlgensym"))); assert(iscons(flv) && car_(flv) == fl_jlgensym_sym); - arraylist_push(&jlgensym_to_flisp, (void*)(size_t)numval(car_(cdr_(flv)))); + jlgensym_str jlgensym_tmp = {idx, numval(car_(cdr_(flv)))}; + arraylist_push_str(&jlgensym_to_flisp, (void *)&jlgensym_tmp); return flv; } if (v == jl_true) @@ -569,9 +579,7 @@ jl_value_t *jl_expand(jl_value_t *expr) value_t arg = julia_to_scm(expr); value_t e = fl_applyn(1, symbol_value(symbol("jl-expand-to-thunk")), arg); jl_value_t *result = scm_to_julia(e,0); - while (jl_gc_n_preserved_values() > np) { - jl_gc_unpreserve(); - } + jl_gc_reset_preserved_values(np); return result; } @@ -580,11 +588,8 @@ DLLEXPORT jl_value_t *jl_macroexpand(jl_value_t *expr) int np = jl_gc_n_preserved_values(); value_t arg = julia_to_scm(expr); value_t e = fl_applyn(1, symbol_value(symbol("jl-macroexpand")), arg); - jl_value_t *result; - result = scm_to_julia(e,0); - while (jl_gc_n_preserved_values() > np) { - jl_gc_unpreserve(); - } + jl_value_t *result = scm_to_julia(e,0); + jl_gc_reset_preserved_values(np); return result; } diff --git a/src/dump.c b/src/dump.c index 8b5bb36eb4038..f7bbe8ec5e3f6 100644 --- a/src/dump.c +++ b/src/dump.c @@ -37,7 +37,7 @@ static jl_value_t *deser_symbols[256]; // table of all objects that have been deserialized, indexed by pos // (the order in the serializer stream) in MODE_MODULE, the low // bit is reserved for flagging certain entries and pos is -// left shift by 1 +// left shifted by 1 static htable_t backref_table; int backref_table_numel; static arraylist_t backref_list; @@ -45,10 +45,17 @@ static arraylist_t backref_list; // list of (jl_value_t **loc, size_t pos) entries // for anything that was flagged by the serializer for later // type-rewriting of some sort +typedef struct { + jl_value_t **loc; + ssize_t pos; +} flagref_str; static arraylist_t flagref_list; // list of (size_t pos, (void *f)(jl_value_t*)) entries // for the serializer to mark values in need of rework by function f +typedef struct { + uint32_t pos; +} reinit_str; static arraylist_t reinit_list; // list of any methtable objects that were deserialized in MODE_MODULE @@ -302,7 +309,7 @@ static void jl_deserialize_globalvals(ios_t *s) while (1) { intptr_t key = read_int32(s); if (key == 0) break; - jl_deserialize_gv(s, (jl_value_t*)backref_list.items[key]); + jl_deserialize_gv(s, ((jl_value_t **)backref_list.items)[key]); } } @@ -503,9 +510,14 @@ static void jl_serialize_module(ios_t *s, jl_module_t *m) jl_serialize_value(s, (jl_value_t*)jl_core_module); } else { - write_int32(s, m->usings.len); - for(i=0; i < m->usings.len; i++) { - jl_serialize_value(s, (jl_value_t*)m->usings.items[i]); + size_t len = m->usings.len; + assert((int32_t)len == len); + write_int32(s, (int32_t)len); + if (len) { + jl_value_t **valp = (jl_value_t **)(m->usings.items); + do { + jl_serialize_value(s, *valp++); + } while (--len); } } jl_serialize_value(s, m->constant_table); @@ -544,6 +556,7 @@ static int literal_val_id(jl_value_t *v) static void jl_serialize_value_(ios_t *s, jl_value_t *v) { + reinit_str reinit_tmp; if (v == NULL) { write_uint8(s, Null_tag); return; @@ -589,8 +602,8 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) pos <<= 1; ptrhash_put(&backref_table, v, (void*)pos); if (jl_typeof(v) == jl_idtable_type) { - arraylist_push(&reinit_list, (void*)pos); - arraylist_push(&reinit_list, (void*)1); + reinit_tmp.pos = pos; + arraylist_push_str(&reinit_list, (void*)&reinit_tmp); } } @@ -909,7 +922,7 @@ static jl_value_t *jl_deserialize_datatype(ios_t *s, int pos, jl_value_t **loc) if (tag == 7) { jl_svec_t *parameters = (jl_svec_t*)jl_deserialize_value(s, NULL); dtv = jl_apply_type(dtv, parameters); - backref_list.items[pos] = dtv; + ((jl_value_t **)backref_list.items)[pos] = dtv; } return dtv; } @@ -946,13 +959,14 @@ static jl_value_t *jl_deserialize_datatype(ios_t *s, int pos, jl_value_t **loc) jl_set_typeof(dt->instance, dt); } assert(tree_literal_values==NULL && mode != MODE_AST); - backref_list.items[pos] = dt; + ((jl_datatype_t **)backref_list.items)[pos] = dt; if (tag == 5) { - arraylist_push(&flagref_list, loc); - arraylist_push(&flagref_list, (void*)(uptrint_t)pos); + flagref_str flagref_tmp = {loc, pos}; + arraylist_push_str(&flagref_list, (void *)&flagref_tmp); if (has_instance) { - arraylist_push(&flagref_list, &jl_astaggedvalue(dt->instance)->type); - arraylist_push(&flagref_list, (void*)(uptrint_t)-1); + flagref_tmp.loc = &jl_astaggedvalue(dt->instance)->type; + flagref_tmp.pos = -1; + arraylist_push_str(&flagref_list, (void *)&flagref_tmp); } } @@ -1015,11 +1029,11 @@ static jl_value_t *jl_deserialize_value(ios_t *s, jl_value_t **loc) offs >>= 1; } assert(offs >= 0 && offs < backref_list.len); - jl_value_t *bp = (jl_value_t*)backref_list.items[offs]; + jl_value_t *bp = ((jl_value_t **)backref_list.items)[offs]; assert(bp); if (isdatatype && loc != NULL) { - arraylist_push(&flagref_list, loc); - arraylist_push(&flagref_list, (void*)(uptrint_t)-1); + flagref_str flagref_tmp = {loc, -1}; + arraylist_push_str(&flagref_list, (void *)&flagref_tmp); } return (jl_value_t*)bp; } @@ -1049,7 +1063,7 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t len = read_int32(s); jl_svec_t *sv = jl_alloc_svec_uninit(len); if (usetable) - arraylist_push(&backref_list, (jl_value_t*)sv); + arraylist_push(&backref_list, sv); jl_value_t **data = sv->data; for(i=0; i < len; i++) { data[i] = jl_deserialize_value(s, &data[i]); @@ -1100,7 +1114,7 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t dims[i] = jl_unbox_long(jl_deserialize_value(s, NULL)); jl_array_t *a = jl_new_array_for_deserialization((jl_value_t*)aty, ndims, dims, isunboxed, elsize); if (usetable) - backref_list.items[pos] = a; + ((jl_array_t **)backref_list.items)[pos] = a; if (!a->ptrarray) { size_t tot = jl_array_len(a) * a->elsize; ios_read(s, (char*)jl_array_data(a), tot); @@ -1130,7 +1144,7 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t arraylist_push(&backref_list, NULL); jl_expr_t *e = jl_exprn((jl_sym_t*)jl_deserialize_value(s, NULL), len); if (usetable) - backref_list.items[pos] = e; + ((jl_expr_t **)backref_list.items)[pos] = e; e->etype = jl_deserialize_value(s, &e->etype); gc_wb(e, e->etype); jl_value_t **data = (jl_value_t**)(e->args->data); @@ -1224,12 +1238,12 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t if (ref_only) { jl_value_t *m_ref = jl_get_global((jl_module_t*)jl_deserialize_value(s, NULL), mname); if (usetable) - backref_list.items[pos] = m_ref; + ((jl_value_t **)backref_list.items)[pos] = m_ref; return m_ref; } jl_module_t *m = jl_new_module(mname); if (usetable) - backref_list.items[pos] = m; + ((jl_module_t **)backref_list.items)[pos] = m; m->parent = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&m->parent); gc_wb(m, m->parent); @@ -1251,13 +1265,14 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t b->imported = (flags) & 1; jl_deserialize_gv(s, (jl_value_t*)b); } - size_t i = m->usings.len; size_t ni = read_int32(s); - arraylist_grow(&m->usings, ni); - ni += i; - while (i < ni) { - m->usings.items[i] = jl_deserialize_value(s, (jl_value_t**)&m->usings.items[i]); - i++; + if (ni) { + arraylist_grow(&m->usings, ni); + jl_value_t **valp = &((jl_value_t **)m->usings.items)[m->usings.len - ni]; + do { + *valp = jl_deserialize_value(s, valp); + valp++; + } while (--ni); } m->constant_table = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&m->constant_table); if (m->constant_table != NULL) gc_wb(m, m->constant_table); @@ -1293,7 +1308,7 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t assert(jl_is_datatype(dt)); jl_value_t *v = (jl_value_t*)dt->name; if (usetable) - backref_list.items[pos] = v; + ((jl_value_t **)backref_list.items)[pos] = v; return v; } } @@ -1323,12 +1338,12 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t } } if (usetable) - backref_list.items[pos] = v; + ((jl_value_t **)backref_list.items)[pos] = v; } else { v = jl_new_struct_uninit(dt); if (usetable) - backref_list.items[pos] = v; + ((jl_value_t **)backref_list.items)[pos] = v; char *data = (char*)jl_data_ptr(v); for(i=0; i < nf; i++) { jl_set_nth_field(v, i, jl_deserialize_value(s, @@ -1348,12 +1363,11 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t assert(mode != MODE_MODULE_LAMBDAS); jl_value_t *v = (jl_value_t*)alloc_0w(); if (usetable) { - uptrint_t pos = backref_list.len; - arraylist_push(&backref_list, (void*)v); + arraylist_push(&backref_list, (void *)v); if (mode == MODE_MODULE) { assert(loc != NULL); - arraylist_push(&flagref_list, loc); - arraylist_push(&flagref_list, (void*)pos); + flagref_str flagref_tmp = {loc, backref_list.len - 1}; + arraylist_push_str(&flagref_list, (void *)&flagref_tmp); } } return v; @@ -1423,7 +1437,7 @@ void jl_save_system_image_to_stream(ios_t *f) jl_gc_collect(0); int en = jl_gc_enable(0); htable_reset(&backref_table, 250000); - arraylist_new(&reinit_list, 0); + arraylist_str(&reinit_list, 0, sizeof(reinit_str)); // orphan old Base module if present jl_base_module = (jl_module_t*)jl_get_global(jl_main_module, jl_symbol("Base")); @@ -1457,9 +1471,10 @@ void jl_save_system_image_to_stream(ios_t *f) write_int32(f, jl_get_gs_ctr()); // record reinitialization functions - for (i = 0; i < reinit_list.len; i += 2) { - write_int32(f, (int)((uintptr_t) reinit_list.items[i])); - write_int32(f, (int)((uintptr_t) reinit_list.items[i+1])); + reinit_str *reinitp = (reinit_str *)reinit_list.items; + for (i = 0; i < reinit_list.len; i++, reinitp++) { + write_int32(f, reinitp->pos); + write_int32(f, 1); // Unneeded! } write_int32(f, -1); @@ -1574,7 +1589,7 @@ void jl_restore_system_image_from_stream(ios_t *f) // run reinitialization functions int pos = read_int32(f); while (pos != -1) { - jl_value_t *v = (jl_value_t*)backref_list.items[pos]; + jl_value_t *v = ((jl_value_t **)backref_list.items)[pos]; switch (read_int32(f)) { case 1: { jl_array_t **a = (jl_array_t**)&v->fieldptr[0]; @@ -1784,7 +1799,7 @@ jl_module_t *jl_restore_new_module(const char *fname) } arraylist_new(&backref_list, 4000); arraylist_push(&backref_list, jl_main_module); - arraylist_new(&flagref_list, 0); + arraylist_str(&flagref_list, 0, sizeof(flagref_str)); arraylist_new(&methtable_list, 0); int en = jl_gc_enable(0); @@ -1800,8 +1815,10 @@ jl_module_t *jl_restore_new_module(const char *fname) b->value = jl_deserialize_value(&f, &b->value); size_t i = 0; + flagref_str *flagrefp = (flagref_str *)flagref_list.items; while (i < flagref_list.len) { - jl_value_t **loc = (jl_value_t**)flagref_list.items[i++]; + jl_value_t **loc = flagrefp[i].loc; + int offs = flagrefp[i++].pos; jl_value_t *v, *o = *loc; jl_datatype_t *dt; if (jl_is_datatype(o)) { @@ -1813,48 +1830,46 @@ jl_module_t *jl_restore_new_module(const char *fname) v = o; } jl_datatype_t *t = (jl_datatype_t*)jl_cache_type_(dt); - int offs = (int)(intptr_t)flagref_list.items[i++]; if (t != dt) { - jl_set_typeof(dt, (jl_value_t*)(ptrint_t)6); // invalidate the old value to help catch errors + // invalidate the old value to help catch errors + jl_set_typeof(dt, (jl_value_t*)(ptrint_t)6); if ((jl_value_t*)dt == o) { if (loc) *loc = (jl_value_t*)t; - if (offs > 0) backref_list.items[offs] = t; + if (offs > 0) ((jl_datatype_t **)backref_list.items)[offs] = t; } } if (t->instance != v) { - jl_set_typeof(v, (jl_value_t*)(ptrint_t)4); // invalidate the old value to help catch errors + // invalidate the old value to help catch errors + jl_set_typeof(v, (jl_value_t*)(ptrint_t)4); if (v == o) { if (loc) *loc = v; - if (offs > 0) backref_list.items[offs] = v; + if (offs > 0) ((jl_value_t **)backref_list.items)[offs] = v; } } size_t j = i; while (j < flagref_list.len) { - if (flagref_list.items[j] == dt) { + jl_value_t **loc = flagrefp[j].loc; + if (loc == (jl_value_t **)dt) { if (t != dt) { - jl_value_t **loc = (jl_value_t**)flagref_list.items[j]; - int offs = (int)(intptr_t)flagref_list.items[j+1]; + int offs = flagrefp[j].pos; if (loc) *loc = (jl_value_t*)t; - if (offs > 0) backref_list.items[offs] = t; + if (offs > 0) ((jl_datatype_t **)backref_list.items)[offs] = t; } } - else if (flagref_list.items[j] == v) { + else if (loc == (jl_value_t **)v) { if (t->instance != v) { - jl_value_t **loc = (jl_value_t**)flagref_list.items[j]; - int offs = (int)(intptr_t)flagref_list.items[j+1]; + int offs = flagrefp[j].pos; if (loc) *loc = v; - if (offs > 0) backref_list.items[offs] = v; + if (offs > 0) ((jl_value_t **)backref_list.items)[offs] = v; } } else { - j += 2; + j++; continue; } - flagref_list.len -= 2; - if (j >= flagref_list.len) + if (j >= --flagref_list.len) break; - flagref_list.items[j+0] = flagref_list.items[flagref_list.len+0]; - flagref_list.items[j+1] = flagref_list.items[flagref_list.len+1]; + flagrefp[j] = flagrefp[flagref_list.len]; } } @@ -1864,7 +1879,7 @@ jl_module_t *jl_restore_new_module(const char *fname) jl_module_init_order = (jl_array_t*)jl_deserialize_value(&f, NULL); for (i = 0; i < methtable_list.len; i++) { - jl_methtable_t *mt = (jl_methtable_t*)methtable_list.items[i]; + jl_methtable_t *mt = ((jl_methtable_t **)methtable_list.items)[i]; jl_array_t *cache_targ = mt->cache_targ; jl_array_t *cache_arg1 = mt->cache_arg1; mt->cache_targ = (jl_array_t*)jl_nothing; diff --git a/src/gc.c b/src/gc.c index 02e2485bda4c8..ba8ab1f846eff 100644 --- a/src/gc.c +++ b/src/gc.c @@ -103,18 +103,21 @@ static arraylist_t finalizer_list; static arraylist_t finalizer_list_marked; static arraylist_t to_finalize; -static void schedule_finalization(void *o, void *f) +typedef struct { + jl_value_t *obj; + jl_function_t *fun; +} finalizer; + +static void schedule_finalization(finalizer fin) { - arraylist_push(&to_finalize, o); - arraylist_push(&to_finalize, f); + arraylist_push_str(&to_finalize, &fin); } -static void run_finalizer(jl_value_t *o, jl_value_t *ff) +static void run_finalizer(finalizer fin) { - jl_function_t *f = (jl_function_t*)ff; - assert(jl_is_function(f)); + assert(jl_is_function(fin.fun)); JL_TRY { - jl_apply(f, (jl_value_t**)&o, 1); + jl_apply(fin.fun, &fin.obj, 1); } JL_CATCH { jl_printf(JL_STDERR, "error in running finalizer: "); @@ -123,21 +126,25 @@ static void run_finalizer(jl_value_t *o, jl_value_t *ff) } } -static int finalize_object(jl_value_t *o) +static int finalize_object(jl_value_t *obj) { int success = 0; - jl_value_t *f = NULL; - JL_GC_PUSH1(&f); - for(int i = 0; i < finalizer_list.len; i+=2) { - if (o == (jl_value_t*)finalizer_list.items[i]) { - f = (jl_value_t*)finalizer_list.items[i+1]; - if (i < finalizer_list.len - 2) { - finalizer_list.items[i] = finalizer_list.items[finalizer_list.len-2]; - finalizer_list.items[i+1] = finalizer_list.items[finalizer_list.len-1]; - i -= 2; + finalizer fin; + finalizer *finpnt; + fin.fun = NULL; + JL_GC_PUSH1(&fin.fun); + finpnt = (finalizer *)finalizer_list.items; + for (int i = 0; i < finalizer_list.len; i++) { + fin = finpnt[i]; + if (obj == finpnt[i].obj) { + fin.obj = obj; + fin.fun = finpnt[i].fun; + finalizer_list.len--; + if (i < finalizer_list.len) { + finpnt[i] = finpnt[finalizer_list.len]; + i--; } - finalizer_list.len -= 2; - run_finalizer(o, f); + run_finalizer(fin); success = 1; } } @@ -147,12 +154,11 @@ static int finalize_object(jl_value_t *o) static void run_finalizers(void) { - void *o = NULL, *f = NULL; - JL_GC_PUSH2(&o, &f); + finalizer fin; + JL_GC_PUSH2(&fin.obj, &fin.fun); while (to_finalize.len > 0) { - f = arraylist_pop(&to_finalize); - o = arraylist_pop(&to_finalize); - run_finalizer((jl_value_t*)o, (jl_value_t*)f); + arraylist_pop_str(&to_finalize, (void *)&fin); + run_finalizer(fin); } JL_GC_POP(); } @@ -160,12 +166,13 @@ static void run_finalizers(void) static void schedule_all_finalizers(arraylist_t* flist) { // Multi-thread version should steal the entire list while holding a lock. - for(size_t i=0; i < flist->len; i+=2) { - jl_value_t *f = (jl_value_t*)flist->items[i+1]; - if (f != HT_NOTFOUND && !jl_is_cpointer(f)) { - schedule_finalization(flist->items[i], flist->items[i+1]); + finalizer *fin = (finalizer *)flist->items; + for (size_t i=0; i < flist->len; i++, fin++) { + if (fin->fun != HT_NOTFOUND && !jl_is_cpointer(fin->fun)) { + schedule_finalization(*fin); } } + // Shouldn't this return the malloc'ed memory? flist->len = 0; } @@ -178,8 +185,8 @@ void jl_gc_run_all_finalizers(void) DLLEXPORT void jl_gc_add_finalizer(jl_value_t *v, jl_function_t *f) { - arraylist_push(&finalizer_list, (void*)v); - arraylist_push(&finalizer_list, (void*)f); + finalizer fin = {v, f}; + arraylist_push_str(&finalizer_list, (void *)&fin); } void jl_finalize(jl_value_t *o) @@ -483,11 +490,11 @@ static int verifying; static void add_lostval_parent(jl_value_t* parent) { for(int i = 0; i < lostval_parents_done.len; i++) { - if ((jl_value_t*)lostval_parents_done.items[i] == parent) + if (((jl_value_t **)lostval_parents_done.items)[i] == parent) return; } for(int i = 0; i < lostval_parents.len; i++) { - if ((jl_value_t*)lostval_parents.items[i] == parent) + if (((jl_value_t **)lostval_parents.items)[i] == parent) return; } arraylist_push(&lostval_parents, parent); @@ -802,10 +809,20 @@ DLLEXPORT void jl_gc_preserve(jl_value_t *v) DLLEXPORT void jl_gc_unpreserve(void) { FOR_CURRENT_HEAP - (void)arraylist_pop(&preserved_values); + if (preserved_values.len) { + preserved_values.len--; + } END } +void jl_gc_reset_preserved_values(size_t np) +{ + FOR_CURRENT_HEAP + if (preserved_values.len > np) { + preserved_values.len = np; + } + END +} // weak references DLLEXPORT jl_weakref_t *jl_gc_new_weakref(jl_value_t *value) @@ -824,7 +841,7 @@ static void sweep_weak_refs(void) FOR_EACH_HEAP size_t n=0, ndel=0, l=weak_refs.len; jl_weakref_t *wr; - void **lst = weak_refs.items; + void **lst = (void **)weak_refs.items; void *tmp; #define SWAP_wr(a,b) (tmp=a,a=b,b=tmp,1) if (l == 0) @@ -1558,7 +1575,7 @@ NOINLINE static int gc_mark_module(jl_module_t *m, int d) // after "using" it but before accessing it, this array might // contain the only reference. for(i=0; i < m->usings.len; i++) { - refyoung |= gc_push_root(m->usings.items[i], d); + refyoung |= gc_push_root(((jl_value_t **)m->usings.items)[i], d); } if (m->constant_table) { verify_parent1("module", m, &m->constant_table, "constant_table"); @@ -1854,13 +1871,13 @@ static void pre_mark(void) // stuff randomly preserved FOR_EACH_HEAP for(i=0; i < preserved_values.len; i++) { - gc_push_root((jl_value_t*)preserved_values.items[i], 0); + gc_push_root(((jl_value_t **)preserved_values.items)[i], 0); } END // objects currently being finalized for(i=0; i < to_finalize.len; i++) { - gc_push_root(to_finalize.items[i], 0); + gc_push_root(((finalizer *)to_finalize.items)[i].obj, 0); } jl_mark_box_caches(); @@ -1884,36 +1901,33 @@ static int n_finalized; static void post_mark(arraylist_t *list, int dryrun) { n_finalized = 0; - for(size_t i=0; i < list->len; i+=2) { - jl_value_t *v = (jl_value_t*)list->items[i]; - jl_value_t *fin = (jl_value_t*)list->items[i+1]; - int isfreed = !gc_marked(jl_astaggedvalue(v)); - gc_push_root(fin, 0); - int isold = list == &finalizer_list && gc_bits(jl_astaggedvalue(v)) == GC_MARKED && gc_bits(jl_astaggedvalue(fin)) == GC_MARKED; + finalizer *fin = (finalizer *)list->items; + for (size_t i=0; i < list->len; i++) { + jl_value_t *obj = fin[i].obj; + jl_function_t *fun = fin[i].fun; + int isfreed = !gc_marked(jl_astaggedvalue(obj)); + gc_push_root(fun, 0); + int isold = (list == &finalizer_list) && + gc_bits(jl_astaggedvalue(obj)) == GC_MARKED && + gc_bits(jl_astaggedvalue(fun)) == GC_MARKED; if (!dryrun && (isfreed || isold)) { - // remove from this list - if (i < list->len - 2) { - list->items[i] = list->items[list->len-2]; - list->items[i+1] = list->items[list->len-1]; - i -= 2; - } - list->len -= 2; + arraylist_remove(list, i); + i--; } if (isfreed) { // schedule finalizer or execute right away if it is not julia code - if (gc_typeof(fin) == (jl_value_t*)jl_voidpointer_type) { - void *p = jl_unbox_voidpointer(fin); + if (gc_typeof(fun) == (jl_value_t*)jl_voidpointer_type) { + void *p = jl_unbox_voidpointer((jl_value_t *)fun); if (!dryrun && p) - ((void (*)(void*))p)(jl_data_ptr(v)); + ((void (*)(void*))p)(jl_data_ptr(obj)); continue; } - gc_push_root(v, 0); - if (!dryrun) schedule_finalization(v, fin); + gc_push_root(obj, 0); + if (!dryrun) schedule_finalization(*fin); n_finalized++; } if (!dryrun && isold) { - arraylist_push(&finalizer_list_marked, v); - arraylist_push(&finalizer_list_marked, fin); + arraylist_push_str(&finalizer_list_marked, (void *)fin); } } visit_mark_stack(GC_MARKED_NOESC); @@ -2019,7 +2033,7 @@ static void gc_verify_track(void) } jl_value_t* lostval_parent = NULL; for(int i = 0; i < lostval_parents.len; i++) { - lostval_parent = (jl_value_t*)lostval_parents.items[i]; + lostval_parent = ((jl_value_t **)lostval_parents.items)[i]; int clean_len = bits_save[GC_CLEAN].len; for(int j = 0; j < clean_len + bits_save[GC_QUEUED].len; j++) { void* p = bits_save[j >= clean_len ? GC_QUEUED : GC_CLEAN].items[j >= clean_len ? j - clean_len : j]; @@ -2193,17 +2207,17 @@ void jl_gc_collect(int full) FOR_EACH_HEAP // avoid counting remembered objects & bindings twice in perm_scanned_bytes for(int i = 0; i < last_remset->len; i++) { - jl_value_t *item = (jl_value_t*)last_remset->items[i]; + jl_value_t *item = ((jl_value_t **)last_remset->items)[i]; objprofile_count(jl_typeof(item), 2, 0); gc_bits(jl_astaggedvalue(item)) = GC_MARKED; } for (int i = 0; i < rem_bindings.len; i++) { - void *ptr = rem_bindings.items[i]; + void *ptr = ((void **)rem_bindings.items)[i]; gc_bits(gc_val_buf(ptr)) = GC_MARKED; } for (int i = 0; i < last_remset->len; i++) { - jl_value_t *item = (jl_value_t*)last_remset->items[i]; + jl_value_t *item = ((jl_value_t **)last_remset->items)[i]; push_root(item, 0, GC_MARKED); } END @@ -2212,12 +2226,12 @@ void jl_gc_collect(int full) int n_bnd_refyoung = 0; FOR_EACH_HEAP for (int i = 0; i < rem_bindings.len; i++) { - jl_binding_t *ptr = (jl_binding_t*)rem_bindings.items[i]; + jl_binding_t *ptr = ((jl_binding_t **)rem_bindings.items)[i]; // A null pointer can happen here when the binding is cleaned up // as an exception is thrown after it was already queued (#10221) if (!ptr->value) continue; if (gc_push_root(ptr->value, 0) == GC_MARKED_NOESC) { - rem_bindings.items[n_bnd_refyoung] = ptr; + ((jl_binding_t **)rem_bindings.items)[n_bnd_refyoung] = ptr; n_bnd_refyoung++; } } @@ -2320,11 +2334,10 @@ void jl_gc_collect(int full) FOR_EACH_HEAP if (sweep_mask == GC_MARKED_NOESC) { for (int i = 0; i < remset->len; i++) { - gc_bits(jl_astaggedvalue(remset->items[i])) = GC_QUEUED; + gc_bits(jl_astaggedvalue(((jl_value_t **)remset->items)[i])) = GC_QUEUED; } for (int i = 0; i < rem_bindings.len; i++) { - void *ptr = rem_bindings.items[i]; - gc_bits(gc_val_buf(ptr)) = GC_QUEUED; + gc_bits(gc_val_buf(((void **)rem_bindings.items)[i])) = GC_QUEUED; } } else { @@ -2546,8 +2559,8 @@ void jl_gc_init(void) { jl_mk_thread_heap(); - arraylist_new(&finalizer_list, 0); - arraylist_new(&to_finalize, 0); + arraylist_str(&finalizer_list, 0, sizeof(finalizer)); + arraylist_str(&to_finalize, 0, sizeof(finalizer)); collect_interval = default_collect_interval; allocd_bytes = -default_collect_interval; diff --git a/src/julia.h b/src/julia.h index ce54f74098014..379ec85bb1661 100644 --- a/src/julia.h +++ b/src/julia.h @@ -554,6 +554,7 @@ DLLEXPORT void jl_gc_collect(int); DLLEXPORT void jl_gc_preserve(jl_value_t *v); DLLEXPORT void jl_gc_unpreserve(void); DLLEXPORT int jl_gc_n_preserved_values(void); +void jl_gc_reset_preserved_values(size_t np); DLLEXPORT void jl_gc_add_finalizer(jl_value_t *v, jl_function_t *f); DLLEXPORT void jl_finalize(jl_value_t *o); diff --git a/src/module.c b/src/module.c index a86eb5a166cdc..bbcf284b1d066 100644 --- a/src/module.c +++ b/src/module.c @@ -30,7 +30,7 @@ jl_module_t *jl_new_module(jl_sym_t *name) m->istopmod = 0; m->uuid = uv_now(uv_default_loop()); htable_new(&m->bindings, 0); - arraylist_new(&m->usings, 0); + arraylist_str(&m->usings, 0, sizeof(jl_module_t *)); if (jl_core_module) { jl_module_using(m, jl_core_module); } @@ -158,53 +158,60 @@ typedef struct _modstack_t { } modstack_t; // get binding for reading. might return NULL for unbound. -static jl_binding_t *jl_get_binding_(jl_module_t *m, jl_sym_t *var, modstack_t *st) +static jl_binding_t *jl_get_binding_(jl_module_t *mod, jl_sym_t *var, modstack_t *st) { - modstack_t top = { m, st }; + modstack_t top = { mod, st }; modstack_t *tmp = st; while (tmp != NULL) { - if (tmp->m == m) { + if (tmp->m == mod) { // import cycle without finding actual location return NULL; } tmp = tmp->prev; } - jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var); - if (b == HT_NOTFOUND || b->owner == NULL) { + jl_binding_t *bnd = (jl_binding_t*)ptrhash_get(&mod->bindings, var); + if (bnd == HT_NOTFOUND || bnd->owner == NULL) { jl_module_t *owner = NULL; - for(int i=(int)m->usings.len-1; i >= 0; --i) { - jl_module_t *imp = (jl_module_t*)m->usings.items[i]; - jl_binding_t *tempb = (jl_binding_t*)ptrhash_get(&imp->bindings, var); - if (tempb != HT_NOTFOUND && tempb->exportp) { - tempb = jl_get_binding_(imp, var, &top); - if (tempb == NULL || tempb->owner == NULL) - // couldn't resolve; try next using (see issue #6105) - continue; - if (owner != NULL && tempb->owner != b->owner && - !(tempb->constp && tempb->value && b->constp && b->value == tempb->value)) { - jl_printf(JL_STDERR, - "Warning: both %s and %s export \"%s\"; uses of it in module %s must be qualified\n", - owner->name->name, imp->name->name, var->name, m->name->name); - // mark this binding resolved, to avoid repeating the warning - (void)jl_get_binding_wr(m, var); - return NULL; + size_t len = mod->usings.len; + if (len) { + jl_module_t **usingp = (jl_module_t **)mod->usings.items; + do { + jl_module_t *imp = *usingp++; + jl_binding_t *tempb = (jl_binding_t*)ptrhash_get(&imp->bindings, var); + if (tempb != HT_NOTFOUND && tempb->exportp) { + tempb = jl_get_binding_(imp, var, &top); + if (tempb == NULL || tempb->owner == NULL) + // couldn't resolve; try next using (see issue #6105) + continue; + if (owner != NULL && tempb->owner != bnd->owner && + !(tempb->constp && tempb->value && + bnd->constp && bnd->value == tempb->value)) { + jl_printf(JL_STDERR, + "Warning: both %s and %s export \"%s\";" + "uses of it in module %s must be qualified\n", + owner->name->name, imp->name->name, var->name, + mod->name->name); + // mark this binding resolved, to avoid repeating the warning + (void)jl_get_binding_wr(mod, var); + return NULL; + } + owner = imp; + bnd = tempb; } - owner = imp; - b = tempb; - } + } while (--len); } if (owner != NULL) { // do a full import to prevent the result of this lookup // from changing, for example if this var is assigned to // later. - module_import_(m, b->owner, var, 0); - return b; + module_import_(mod, bnd->owner, var, 0); + return bnd; } return NULL; } - if (b->owner != m) - return jl_get_binding_(b->owner, var, &top); - return b; + if (bnd->owner != mod) + return jl_get_binding_(bnd->owner, var, &top); + return bnd; } DLLEXPORT jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var) @@ -323,9 +330,12 @@ void jl_module_using(jl_module_t *to, jl_module_t *from) { if (to == from) return; - for(size_t i=0; i < to->usings.len; i++) { - if (from == to->usings.items[i]) - return; + size_t len = to->usings.len; + if (len) { + jl_module_t **usingp = (jl_module_t **)to->usings.items; + do { + if (from == *usingp++) return; + } while (--len); } // print a warning if something visible via this "using" conflicts with // an existing identifier. note that an identifier added later may still @@ -349,8 +359,7 @@ void jl_module_using(jl_module_t *to, jl_module_t *from) } } } - - arraylist_push(&to->usings, from); + arraylist_push_str(&to->usings, (void *)from); } void jl_module_export(jl_module_t *from, jl_sym_t *s) @@ -455,17 +464,22 @@ DLLEXPORT void jl_set_current_module(jl_value_t *m) jl_current_module = (jl_module_t*)m; } -DLLEXPORT jl_value_t *jl_module_usings(jl_module_t *m) -{ - jl_array_t *a = jl_alloc_array_1d(jl_array_any_type, 0); - JL_GC_PUSH1(&a); - for(int i=(int)m->usings.len-1; i >= 0; --i) { - jl_array_grow_end(a, 1); - jl_module_t *imp = (jl_module_t*)m->usings.items[i]; - jl_cellset(a,jl_array_dim0(a)-1, (jl_value_t*)imp); +DLLEXPORT jl_value_t *jl_module_usings(jl_module_t *mod) +{ + jl_array_t *arr = jl_alloc_array_1d(jl_array_any_type, 0); + size_t len = mod->usings.len; + if (len) { + JL_GC_PUSH1(&arr); + // Why doesn't this grow the array all at once? + // jl_array_grow_end(arr, len); + jl_module_t **usingp = (jl_module_t **)mod->usings.items; + do { + jl_array_grow_end(arr, 1); + jl_cellset(arr,jl_array_dim0(arr)-1, *usingp++); + } while (--len); + JL_GC_POP(); } - JL_GC_POP(); - return (jl_value_t*)a; + return (jl_value_t*)arr; } DLLEXPORT jl_value_t *jl_module_names(jl_module_t *m, int all, int imported) diff --git a/src/support/arraylist.c b/src/support/arraylist.c index 25e26b481efc7..c4b43605f5284 100644 --- a/src/support/arraylist.c +++ b/src/support/arraylist.c @@ -13,67 +13,82 @@ extern "C" { #endif -arraylist_t *arraylist_new(arraylist_t *a, size_t size) +arraylist_t *arraylist_str(arraylist_t *arr, size_t size, size_t elesz) { - a->len = 0; - if (size <= AL_N_INLINE) { - a->items = &a->_space[0]; - a->max = AL_N_INLINE; + arr->elesz = elesz; + if (size*elesz <= sizeof(arr->_space)) { + arr->items = arr->_space; + arr->max = sizeof(arr->_space)/elesz; } else { - a->items = (void**)LLT_ALLOC(size*sizeof(void*)); - a->max = size; + // This should probably be rounded up + arr->items = (void **)LLT_ALLOC(size*elesz); + if (arr->items == NULL) return NULL; + arr->max = size; } - if (a->items == NULL) return NULL; - return a; + return arr; } -void arraylist_free(arraylist_t *a) +void arraylist_free(arraylist_t *arr) { - if (a->items != &a->_space[0]) - LLT_FREE(a->items); - a->len = 0; - a->max = AL_N_INLINE; - a->items = &a->_space[0]; + if (arr->items != (void **)arr->_space && arr->items) + LLT_FREE(arr->items); + arr->len = 0; + arr->max = sizeof(arr->_space)/arr->elesz; + arr->items = (void **)arr->_space; } -void arraylist_grow(arraylist_t *a, size_t n) +void arraylist_grow(arraylist_t *arr, size_t num) { - if (a->len+n > a->max) { - if (a->items == &a->_space[0]) { - void **p = (void**)LLT_ALLOC((a->len+n)*sizeof(void*)); - if (p == NULL) return; - memcpy(p, a->items, a->len*sizeof(void*)); - a->items = p; - a->max = a->len+n; + size_t newlen = arr->len + num; + if (newlen > arr->max) { + if (arr->items == (void **)arr->_space) { + void *pnt = (void *)LLT_ALLOC(newlen * arr->elesz); + if (pnt == NULL) return; + memcpy(pnt, (void *)arr->items, arr->len * arr->elesz); + arr->max = newlen; + arr->items = (void **)pnt; } else { - size_t nm = a->max*2; - if (nm == 0) nm = 1; - while (a->len+n > nm) nm*=2; - void **p = (void**)LLT_REALLOC(a->items, nm*sizeof(void*)); - if (p == NULL) return; - a->items = p; - a->max = nm; + size_t nm = arr->max * 2; + while (newlen > nm) nm *= 2; + void *pnt = (void *)LLT_REALLOC(arr->items, nm * arr->elesz); + if (pnt == NULL) return; + arr->max = nm; + arr->items = (void **)pnt; } } - a->len += n; + arr->len = newlen; } -void arraylist_push(arraylist_t *a, void *elt) +void arraylist_push_str(arraylist_t *arr, void *elt) { - arraylist_grow(a, 1); - a->items[a->len-1] = elt; + arraylist_grow(arr, 1); + memcpy((void *)arr->items + (arr->len-1) * arr->elesz, elt, arr->elesz); } -void *arraylist_pop(arraylist_t *a) +void arraylist_push(arraylist_t *arr, void *elt) { - if (a->len == 0) return NULL; - void *p = a->items[--a->len]; - a->items[a->len] = NULL; - return p; + arraylist_grow(arr, 1); + ((void **)arr->items)[arr->len-1] = elt; } +void arraylist_pop_str(arraylist_t *arr, void *elt) +{ + if (arr->len != 0) { + arr->len--; + memcpy(elt, (void *)arr->items + (arr->len * arr->elesz), arr->elesz); + } +} + +// remove from this list +void arraylist_remove(arraylist_t *arr, size_t pos) +{ + size_t len = --(arr->len); + if (pos < len) { + memcpy(arr->items + (pos*arr->elesz), arr->items + (len*arr->elesz), arr->elesz); + } +} #ifdef __cplusplus } #endif diff --git a/src/support/arraylist.h b/src/support/arraylist.h index 3440367e90849..44a15fc8b1411 100644 --- a/src/support/arraylist.h +++ b/src/support/arraylist.h @@ -3,25 +3,31 @@ #ifndef ARRAYLIST_H #define ARRAYLIST_H -#define AL_N_INLINE 29 - #ifdef __cplusplus extern "C" { #endif +#define AL_N_INLINE 28 + typedef struct { + void *items; size_t len; size_t max; - void **items; - void *_space[AL_N_INLINE]; + size_t elesz; + unsigned char _space[AL_N_INLINE*sizeof(void *)]; } arraylist_t; -arraylist_t *arraylist_new(arraylist_t *a, size_t size); -void arraylist_free(arraylist_t *a); +void arraylist_free(arraylist_t *arr); +void arraylist_grow(arraylist_t *arr, size_t num); + +arraylist_t *arraylist_str(arraylist_t *arr, size_t size, size_t elesz); +void arraylist_push_str(arraylist_t *arr, void *elt); +void arraylist_pop_str(arraylist_t *arr, void *elt); +void arraylist_remove(arraylist_t *arr, size_t pos); -void arraylist_push(arraylist_t *a, void *elt); -void *arraylist_pop(arraylist_t *a); -void arraylist_grow(arraylist_t *a, size_t n); +#define arraylist_new(arr, size) arraylist_str(arr, size, sizeof(void *)) +void *arraylist_pop(arraylist_t *arr); +void arraylist_push(arraylist_t *arr, void *elt); #ifdef __cplusplus } diff --git a/src/toplevel.c b/src/toplevel.c index 4eb57252d7600..34445744613b8 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -196,7 +196,7 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) if (outermost == NULL || jl_current_module == jl_main_module) { size_t i, l=module_stack.len; for(i = stackidx; i < l; i++) { - jl_module_load_time_initialize((jl_module_t*)module_stack.items[i]); + jl_module_load_time_initialize(((jl_module_t **)module_stack.items)[i]); } assert(module_stack.len == l); module_stack.len = stackidx;