Exemple #1
0
static void gc_mark_module(jl_module_t *m)
{
    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];
            gc_setmark_buf(b);
            if (b->value != NULL)
                gc_push_root(b->value);
            gc_push_root(b->type);
        }
    }
}
Exemple #2
0
static void gc_mark_task(jl_task_t *ta, int d)
{
    if (ta->parent) gc_push_root(ta->parent, d);
    if (ta->last) gc_push_root(ta->last, d);
    gc_push_root(ta->tls, d);
    gc_push_root(ta->consumers, d);
    gc_push_root(ta->donenotify, d);
    gc_push_root(ta->exception, d);
    if (ta->start)  gc_push_root(ta->start, d);
    if (ta->result) gc_push_root(ta->result, d);
    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, d);
        }
        else {
            offset = (char *)ta->stkbuf - ((char *)ta->stackbase - ta->ssize);
            gc_mark_stack(ta->gcstack, offset, d);
        }
#else
        gc_mark_stack(ta->gcstack, 0, d);
#endif
    }
}
Exemple #3
0
static scheme_object* read_pair(vm* context, FILE* in)
{
	int c;
	scheme_object* car = NULL;
	scheme_object* cdr = NULL;
	eat_whitespace(in);
	c = getc(in);
	
	if(c ==')')
	{
		return the_empty_list;
	}

	gc_push_root((void**) &car);
	gc_push_root((void**) &cdr);
	
	ungetc(c, in);
	
	car = read(context, in);
	eat_whitespace(in);
	
	c = getc(in);
	if(c == '.')
	{
		if(!is_delimiter(peek(in)))
		{
			fprintf(stderr, "Expected a delimiter after '.'...\n");
			exit(1);
		}		
		cdr = read(context, in);
		
		eat_whitespace(in);

		c = getc(in);
		if(c != ')')
		{
			fprintf(stderr, "Expected a ')'\n");
			exit(1);
		}
	}
	else
	{
		ungetc(c, in);
		cdr = read_pair(context, in);
	}
	gc_pop_root();
	gc_pop_root();
	return cons(context, car, cdr);
}
Exemple #4
0
static void gc_mark_stack(jl_gcframe_t *s, ptrint_t offset, int d)
{
    while (s != NULL) {
        s = (jl_gcframe_t*)((char*)s + offset);
        jl_value_t ***rts = (jl_value_t***)(((void**)s)+2);
        size_t nr = s->nroots>>1;
        if (s->nroots & 1) {
            for(size_t i=0; i < nr; i++) {
                jl_value_t **ptr = (jl_value_t**)((char*)rts[i] + offset);
                if (*ptr != NULL)
                    gc_push_root(*ptr, d);
            }
        }
        else {
            for(size_t i=0; i < nr; i++) {
                if (rts[i] != NULL)
                    gc_push_root(rts[i], d);
            }
        }
        s = s->prev;
    }
}
Exemple #5
0
static void gc_mark_module(jl_module_t *m, int d)
{
    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];
            gc_setmark_buf(b);
            if (b->value != NULL)
                gc_push_root(b->value, d);
            if (b->type != (jl_value_t*)jl_any_type)
                gc_push_root(b->type, d);
        }
    }
    // this is only necessary because bindings for "using" modules
    // are added only when accessed. therefore if a module is replaced
    // after "using" it but before accessing it, this array might
    // contain the only reference.
    for(i=0; i < m->usings.len; i++) {
        gc_push_root(m->usings.items[i], d);
    }
    if (m->constant_table)
        gc_push_root(m->constant_table, d);
}
Exemple #6
0
static void gc_mark_stack(jl_gcframe_t *s, ptrint_t offset)
{
    while (s != NULL) {
        s = (jl_gcframe_t*)((char*)s + offset);
        size_t i;
        jl_value_t ***rts = (jl_value_t***)((char*)s->roots + offset);
        if (s->indirect) {
            size_t nr = s->nroots;
            for(i=0; i < nr; i++) {
                jl_value_t **ptr = (jl_value_t**)((char*)rts[i] + offset);
                if (*ptr != NULL)
                    gc_push_root(*ptr);
            }
        }
        else {
            size_t nr = s->nroots;
            for(i=0; i < nr; i++) {
                if (rts[i] != NULL)
                    gc_push_root(rts[i]);
            }
        }
        s = s->prev;
    }
}
Exemple #7
0
static void gc_mark(void)
{
    // mark all roots

    // active tasks
    gc_push_root(jl_root_task, 0);
    gc_push_root(jl_current_task, 0);

    // modules
    gc_push_root(jl_main_module, 0);
    gc_push_root(jl_internal_main_module, 0);
    gc_push_root(jl_current_module, 0);
    if (jl_old_base_module) gc_push_root(jl_old_base_module, 0);

    // invisible builtin values
    if (jl_an_empty_cell) gc_push_root(jl_an_empty_cell, 0);
    gc_push_root(jl_exception_in_transit, 0);
    gc_push_root(jl_task_arg_in_transit, 0);
    gc_push_root(jl_unprotect_stack_func, 0);
    gc_push_root(jl_bottom_func, 0);
    gc_push_root(jl_typetype_type, 0);
    gc_push_root(jl_tupletype_type, 0);
    gc_push_root(typeToTypeId, 0);
    if (jl_module_init_order != NULL)
        gc_push_root(jl_module_init_order, 0);

    // constants
    gc_push_root(jl_null, 0);
    gc_push_root(jl_true, 0);
    gc_push_root(jl_false, 0);

    jl_mark_box_caches();

    size_t i;

    // stuff randomly preserved
    for(i=0; i < preserved_values.len; i++) {
        gc_push_root((jl_value_t*)preserved_values.items[i], 0);
    }

    // objects currently being finalized
    for(i=0; i < to_finalize.len; i++) {
        gc_push_root(to_finalize.items[i], 0);
    }

    visit_mark_stack();

    // find unmarked objects that need to be finalized.
    // this must happen last.
    for(i=0; i < finalizer_table.size; i+=2) {
        if (finalizer_table.table[i+1] != HT_NOTFOUND) {
            jl_value_t *v = (jl_value_t*)finalizer_table.table[i];
            if (!gc_marked(v)) {
                jl_value_t *fin = (jl_value_t*)finalizer_table.table[i+1];
                if (gc_typeof(fin) == (jl_value_t*)jl_voidpointer_type) {
                    void *p = ((void**)fin)[1];
                    if (p)
                        ((void (*)(void*))p)(jl_data_ptr(v));
                    finalizer_table.table[i+1] = HT_NOTFOUND;
                    continue;
                }
                gc_push_root(v, 0);
                schedule_finalization(v);
            }
            gc_push_root(finalizer_table.table[i+1], 0);
        }
    }

    visit_mark_stack();
}
Exemple #8
0
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;
}
Exemple #9
0
static void gc_mark(void)
{
    // mark all roots

    // active tasks
    gc_push_root(jl_root_task);
    gc_push_root(jl_current_task);

    // modules
    gc_push_root(jl_main_module);
    gc_push_root(jl_current_module);

    // invisible builtin values
    if (jl_an_empty_cell) gc_push_root(jl_an_empty_cell);
    gc_push_root(jl_exception_in_transit);
    gc_push_root(jl_task_arg_in_transit);
    gc_push_root(jl_unprotect_stack_func);
    gc_push_root(jl_bottom_func);
    gc_push_root(jl_typetype_type);
    gc_push_root(jl_tupletype_type);

    // constants
    gc_push_root(jl_null);
    gc_push_root(jl_true);
    gc_push_root(jl_false);

    // libuv loops
    gc_mark_uv_state(jl_global_event_loop());

    jl_mark_box_caches();

    size_t i;

    // stuff randomly preserved
    for(i=0; i < preserved_values.len; i++) {
        gc_push_root((jl_value_t*)preserved_values.items[i]);
    }

    // objects currently being finalized
    for(i=0; i < to_finalize.len; i++) {
        gc_push_root(to_finalize.items[i]);
    }

    gc_mark_all();

    // find unmarked objects that need to be finalized.
    // this must happen last.
    for(i=0; i < finalizer_table.size; i+=2) {
        if (finalizer_table.table[i+1] != HT_NOTFOUND) {
            jl_value_t *v = finalizer_table.table[i];
            if (!gc_marked(v)) {
                gc_push_root(v);
                schedule_finalization(v);
            }
            gc_push_root(finalizer_table.table[i+1]);
        }
    }

    gc_mark_all();
}
Exemple #10
0
static void gc_mark_uv_handle(uv_handle_t *handle, void *arg)
{
    if(handle->data) {
        gc_push_root((jl_value_t*)(handle->data));
    }
}
Exemple #11
0
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);
            }
        }
    }
    }
}