Skip to content

Commit

Permalink
Merge pull request #10011 from JuliaLang/ob/gcfix
Browse files Browse the repository at this point in the history
Fix unbounded memory usage & a missing root
  • Loading branch information
JeffBezanson committed Feb 2, 2015
2 parents fcf924f + c01f698 commit 2f97c78
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 17 deletions.
21 changes: 13 additions & 8 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,15 @@ void *jl_gc_managed_malloc(size_t sz)
void *jl_gc_managed_realloc(void *d, size_t sz, size_t oldsz, int isaligned, jl_value_t* owner)
{
maybe_collect();

if (gc_bits(owner) == GC_MARKED) {
perm_scanned_bytes += sz - oldsz;
live_bytes += sz - oldsz;
}
else {
allocd_bytes += sz - oldsz;
}

sz = (sz+15) & -16;
void *b;
#ifdef _P64
Expand All @@ -615,10 +624,7 @@ void *jl_gc_managed_realloc(void *d, size_t sz, size_t oldsz, int isaligned, jl_
#endif
if (b == NULL)
jl_throw(jl_memory_exception);
if (gc_bits(owner) == GC_MARKED)
perm_scanned_bytes += (sz - oldsz);
else
allocd_bytes += (sz - oldsz);

return b;
}

Expand Down Expand Up @@ -1741,7 +1747,8 @@ static void post_mark(arraylist_t *list, int dryrun)
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(v);
int isold = list == &finalizer_list && gc_bits(v) == GC_MARKED;
gc_push_root(fin, 0);
int isold = list == &finalizer_list && gc_bits(v) == GC_MARKED && gc_bits(fin) == GC_MARKED;
if (!dryrun && (isfreed || isold)) {
// remove from this list
if (i < list->len - 2) {
Expand All @@ -1766,9 +1773,7 @@ static void post_mark(arraylist_t *list, int dryrun)
if (!dryrun && isold) {
arraylist_push(&finalizer_list_marked, v);
arraylist_push(&finalizer_list_marked, fin);
gc_bits(fin) = GC_QUEUED;
}
gc_push_root(fin, 0);
}
visit_mark_stack(GC_MARKED_NOESC);
}
Expand Down Expand Up @@ -2127,7 +2132,7 @@ void jl_gc_collect(int full)
promoted_bytes += perm_scanned_bytes - last_perm_scanned_bytes;
// 5. next collection decision
int not_freed_enough = estimate_freed < (7*(actual_allocd/10));
if ((full || (not_freed_enough && (promoted_bytes >= default_collect_interval || prev_sweep_mask == GC_MARKED))) && n_pause > 1) {
if ((full || ((not_freed_enough || promoted_bytes >= collect_interval) && (promoted_bytes >= default_collect_interval || prev_sweep_mask == GC_MARKED))) && n_pause > 1) {
if (prev_sweep_mask != GC_MARKED || full) {
if (full) recollect = 1; // TODO enable this?
}
Expand Down
45 changes: 36 additions & 9 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -657,16 +657,21 @@ static jl_value_t *meet_tvars(jl_tvar_t *a, jl_tvar_t *b);
static jl_value_t *intersect_typevar(jl_tvar_t *a, jl_value_t *b,
cenv_t *penv, cenv_t *eqc, variance_t var)
{
JL_GC_PUSH1(&b);
if (var == covariant) {
// matching T to Type{S} in covariant context
b = type_to_static_parameter_value(b);
}
if (jl_subtype(b, (jl_value_t*)a, 0)) {
if (!a->bound) return b;
if (!a->bound) {
JL_GC_POP();
return b;
}
}
else if (var==invariant && !jl_has_typevars_(b,0)) {
// for typevar a and non-typevar type b, b must be within a's bounds
// in invariant contexts.
JL_GC_POP();
return (jl_value_t*)jl_bottom_type;
}
else if (jl_subtype((jl_value_t*)a, b, 0)) {
Expand All @@ -677,19 +682,29 @@ static jl_value_t *intersect_typevar(jl_tvar_t *a, jl_value_t *b,
should give Type{_<:Vector}
*/
if (jl_is_typevar(b)) {
if (!((jl_tvar_t*)b)->bound) return (jl_value_t*)a;
if (!((jl_tvar_t*)b)->bound){
JL_GC_POP();
return (jl_value_t*)a;
}
}
else {
if (!a->bound) return (jl_value_t*)a;
if (!a->bound) {
JL_GC_POP();
return (jl_value_t*)a;
}
}
}
else {
b = jl_type_intersect(a->ub, b, penv, eqc, covariant);
if (b == jl_bottom_type)
if (b == jl_bottom_type) {
JL_GC_POP();
return b;
}
}
if ((jl_value_t*)a == b)
if ((jl_value_t*)a == b) {
JL_GC_POP();
return b;
}
if (var == invariant) {
if (!jl_has_typevars_(b,0) && !jl_is_typevar(b)) {
int i;
Expand All @@ -698,19 +713,24 @@ static jl_value_t *intersect_typevar(jl_tvar_t *a, jl_value_t *b,
jl_value_t *v = eqc->data[i+1];
if (jl_is_typevar(v))
continue;
if (!jl_types_equal(v, b))
if (!jl_types_equal(v, b)) {
JL_GC_POP();
return (jl_value_t*)jl_bottom_type;
}
break;
}
}
if (i >= eqc->n)
extend((jl_value_t*)a, b, eqc);
JL_GC_POP();
return (jl_value_t*)a;
}
if (jl_is_typevar(b)) {
jl_value_t *both = meet_tvars(a, (jl_tvar_t*)b);
if (both == jl_bottom_type)
if (both == jl_bottom_type) {
JL_GC_POP();
return both;
}
if (!jl_is_typevar(both))
both = (jl_value_t*)jl_new_typevar(underscore_sym, jl_bottom_type, both);
extend((jl_value_t*)a, both, penv);
Expand All @@ -722,25 +742,32 @@ static jl_value_t *intersect_typevar(jl_tvar_t *a, jl_value_t *b,
int i;
for(i=0; i < penv->n; i+=2) {
if (penv->data[i] == (jl_value_t*)a && !jl_is_typevar(penv->data[i+1])) {
if (jl_types_equal(b, penv->data[i+1]))
if (jl_types_equal(b, penv->data[i+1])) {
JL_GC_POP();
return (jl_value_t*)a;
}
jl_value_t *ti = jl_type_intersection(b, penv->data[i+1]);
if (ti == (jl_value_t*)jl_bottom_type)
if (ti == (jl_value_t*)jl_bottom_type) {
JL_GC_POP();
return ti;
}
break;
}
}
extend((jl_value_t*)a, b, penv);
if (jl_is_typevar(b)) {
JL_GC_POP();
return (jl_value_t*)a;
}
else {
jl_tvar_t *new_b = jl_new_typevar(underscore_sym, jl_bottom_type, b);
extend((jl_value_t*)new_b, b, penv);
extend((jl_value_t*)new_b, (jl_value_t*)a, penv);
JL_GC_POP();
return (jl_value_t*)new_b;
}
}
JL_GC_POP();
return (jl_value_t*)a;
}

Expand Down

0 comments on commit 2f97c78

Please sign in to comment.