void jl_gc_setmark(jl_value_t *v) { gc_setmark(v); }
static void gc_mark_all() { while (mark_sp > 0) { jl_value_t *v = mark_stack[--mark_sp]; jl_value_t *vt = (jl_value_t*)gc_typeof(v); // some values have special representations if (vt == (jl_value_t*)jl_tuple_type) { size_t l = jl_tuple_len(v); jl_value_t **data = ((jl_tuple_t*)v)->data; for(size_t i=0; i < l; i++) { jl_value_t *elt = data[i]; if (elt != NULL) gc_push_root(elt); } } else if (((jl_datatype_t*)(vt))->name == jl_array_typename) { jl_array_t *a = (jl_array_t*)v; char *data = a->data; if (data == NULL) continue; int ndims = jl_array_ndims(a); char *data0 = data; if (ndims == 1) data0 -= a->offset*a->elsize; if (!a->isinline) { jl_value_t *owner = jl_array_data_owner(a); if (a->ismalloc) { // jl_mallocptr_t if (gc_marked(owner)) continue; gc_setmark(owner); } else { // an array v = owner; if (v != (jl_value_t*)a) { gc_push_root(v); continue; } } } if (a->ptrarray) { size_t l = jl_array_len(a); for(size_t i=0; i < l; i++) { jl_value_t *elt = ((jl_value_t**)data)[i]; if (elt != NULL) gc_push_root(elt); } } } else if (vt == (jl_value_t*)jl_module_type) { gc_mark_module((jl_module_t*)v); } else if (vt == (jl_value_t*)jl_task_type) { jl_task_t *ta = (jl_task_t*)v; if (ta->on_exit) gc_push_root(ta->on_exit); gc_push_root(ta->last); gc_push_root(ta->tls); gc_push_root(ta->consumers); if (ta->start) gc_push_root(ta->start); if (ta->result) gc_push_root(ta->result); if (ta->stkbuf != NULL || ta == jl_current_task) { if (ta->stkbuf != NULL) gc_setmark_buf(ta->stkbuf); #ifdef COPY_STACKS ptrint_t offset; if (ta == jl_current_task) { offset = 0; gc_mark_stack(jl_pgcstack, offset); } else { offset = (char *)ta->stkbuf - ((char *)ta->stackbase - ta->ssize); gc_mark_stack(ta->gcstack, offset); } #else gc_mark_stack(ta->gcstack, 0); #endif } } else { jl_datatype_t *dt = (jl_datatype_t*)vt; int nf = (int)jl_tuple_len(dt->names); for(int i=0; i < nf; i++) { if (dt->fields[i].isptr) { jl_value_t *fld = *(jl_value_t**)((char*)v + dt->fields[i].offset + sizeof(void*)); if (fld) gc_push_root(fld); } } } } }
static void push_root(jl_value_t *v, int d) { assert(v != NULL); jl_value_t *vt = (jl_value_t*)gc_typeof(v); #ifdef OBJPROFILE if (!gc_marked(v)) { void **bp = ptrhash_bp(&obj_counts, vt); if (*bp == HT_NOTFOUND) *bp = (void*)2; else (*((ptrint_t*)bp))++; } #endif gc_setmark(v); if (vt == (jl_value_t*)jl_weakref_type || (jl_is_datatype(vt) && ((jl_datatype_t*)vt)->pointerfree)) { return; } if (d >= MAX_MARK_DEPTH) goto queue_the_root; d++; // some values have special representations if (vt == (jl_value_t*)jl_tuple_type) { size_t l = jl_tuple_len(v); jl_value_t **data = ((jl_tuple_t*)v)->data; for(size_t i=0; i < l; i++) { jl_value_t *elt = data[i]; if (elt != NULL) gc_push_root(elt, d); } } else if (((jl_datatype_t*)(vt))->name == jl_array_typename) { jl_array_t *a = (jl_array_t*)v; if (a->how == 3) { jl_value_t *owner = jl_array_data_owner(a); gc_push_root(owner, d); return; } else if (a->how == 1) { gc_setmark_buf((char*)a->data - a->offset*a->elsize); } if (a->ptrarray && a->data!=NULL) { size_t l = jl_array_len(a); if (l > 100000 && d > MAX_MARK_DEPTH-10) { // don't mark long arrays at high depth, to try to avoid // copying the whole array into the mark queue goto queue_the_root; } else { void *data = a->data; for(size_t i=0; i < l; i++) { jl_value_t *elt = ((jl_value_t**)data)[i]; if (elt != NULL) gc_push_root(elt, d); } } } } else if (vt == (jl_value_t*)jl_module_type) { gc_mark_module((jl_module_t*)v, d); } else if (vt == (jl_value_t*)jl_task_type) { gc_mark_task((jl_task_t*)v, d); } else { jl_datatype_t *dt = (jl_datatype_t*)vt; int nf = (int)jl_tuple_len(dt->names); for(int i=0; i < nf; i++) { if (dt->fields[i].isptr) { jl_value_t *fld = *(jl_value_t**)((char*)v + dt->fields[i].offset + sizeof(void*)); if (fld) gc_push_root(fld, d); } } } return; queue_the_root: if (mark_sp >= mark_stack_size) { size_t newsz = mark_stack_size>0 ? mark_stack_size*2 : 32000; mark_stack = (jl_value_t**)realloc(mark_stack,newsz*sizeof(void*)); if (mark_stack == NULL) exit(1); mark_stack_size = newsz; } mark_stack[mark_sp++] = v; }
static void gc_markval_(jl_value_t *v) { gc_markval_top: assert(v != NULL); //assert(v != lookforme); if (gc_marked_obj(v)) return; jl_value_t *vt = (jl_value_t*)jl_typeof(v); #ifdef OBJPROFILE void **bp = ptrhash_bp(&obj_counts, vt); if (*bp == HT_NOTFOUND) *bp = (void*)2; else (*((ptrint_t*)bp))++; #endif gc_setmark_obj(v); if (gc_typeof(vt) == (jl_value_t*)jl_bits_kind) return; // some values have special representations if (vt == (jl_value_t*)jl_tuple_type) { size_t l = ((jl_tuple_t*)v)->length; for(size_t i=0; i < l; i++) { jl_value_t *elt = ((jl_tuple_t*)v)->data[i]; if (elt != NULL) GC_Markval(elt); } } else if (((jl_struct_type_t*)(vt))->name == jl_array_typename) { jl_array_t *a = (jl_array_t*)v; int ndims = jl_array_ndims(a); int ndimwords = (ndims > 2 ? (ndims-2) : 0); #ifndef __LP64__ // on 32-bit, ndimwords must be odd to preserve 8-byte alignment ndimwords += (~ndimwords)&1; #endif void *data_area = &a->_space[0] + ndimwords*sizeof(size_t); if (a->reshaped) { GC_Markval(*((jl_value_t**)data_area)); } else if (a->data) { char *data = a->data; if (ndims == 1) data -= a->offset*a->elsize; if (data != data_area) { gc_setmark(data); } } if (gc_typeof(jl_tparam0(vt)) != (jl_value_t*)jl_bits_kind) { size_t l = a->length; if (l > 0) { for(size_t i=0; i < l-1; i++) { jl_value_t *elt = ((jl_value_t**)a->data)[i]; if (elt != NULL) GC_Markval(elt); } v = ((jl_value_t**)a->data)[l-1]; if (v != NULL) goto gc_markval_top; } } } else if (vt == (jl_value_t*)jl_module_type) { gc_mark_module((jl_module_t*)v); } else if (vt == (jl_value_t*)jl_task_type) { jl_task_t *ta = (jl_task_t*)v; GC_Markval(ta->on_exit); GC_Markval(ta->tls); if (ta->start) GC_Markval(ta->start); if (ta->result) GC_Markval(ta->result); GC_Markval(ta->state.eh_task); if (ta->stkbuf != NULL) gc_setmark(ta->stkbuf); #ifdef COPY_STACKS ptrint_t offset; if (ta == jl_current_task) { offset = 0; gc_mark_stack(jl_pgcstack, offset); } else { offset = ta->stkbuf - (ta->stackbase-ta->ssize); gc_mark_stack(ta->state.gcstack, offset); } jl_savestate_t *ss = &ta->state; while (ss != NULL) { GC_Markval(ss->ostream_obj); ss = ss->prev; if (ss != NULL) ss = (jl_savestate_t*)((char*)ss + offset); } #else gc_mark_stack(ta->state.gcstack, 0); jl_savestate_t *ss = &ta->state; while (ss != NULL) { GC_Markval(ss->ostream_obj); ss = ss->prev; } #endif } else if (vt == (jl_value_t*)jl_weakref_type) { // don't mark contents } else { int nf = (int)((jl_struct_type_t*)vt)->names->length; if (nf > 0) { int i = 0; if (vt == (jl_value_t*)jl_struct_kind || vt == (jl_value_t*)jl_function_type) { i++; // skip fptr field } for(; i < nf-1; i++) { jl_value_t *fld = ((jl_value_t**)v)[i+1]; if (fld) GC_Markval(fld); } v = ((jl_value_t**)v)[i+1]; if (v) goto gc_markval_top; } } }