示例#1
0
static void destroy_instance(lily_value *v)
{
    lily_instance_val *iv = v->value.instance;
    if (iv->gc_entry == lily_gc_stopper)
        return;

    int full_destroy = 1;
    if (iv->gc_entry) {
        if (iv->gc_entry->last_pass == -1) {
            full_destroy = 0;
            iv->gc_entry = lily_gc_stopper;
        }
        else
            iv->gc_entry->value.generic = NULL;
    }

    int i;
    for (i = 0;i < iv->num_values;i++) {
        lily_deref(iv->values[i]);
        lily_free(iv->values[i]);
    }

    lily_free(iv->values);

    if (full_destroy)
        lily_free(iv);
}
示例#2
0
void lily_pop_value(lily_state *s)
{
    s->call_chain->total_regs--;
    lily_value *z = s->regs_from_main[s->call_chain->total_regs];
    lily_deref(z);
    z->flags = 0;
}
示例#3
0
void lily_list_delete_at(lily_vm_state *vm, uint16_t argc, uint16_t *code)
{
    lily_value **vm_regs = vm->vm_regs;
    lily_list_val *list_val = vm_regs[code[1]]->value.list;
    int64_t pos = vm_regs[code[2]]->value.integer;

    if (list_val->num_values == 0)
        lily_raise(vm->raiser, lily_IndexError, "Cannot delete from an empty list.\n");

    pos = get_relative_index(vm, list_val, pos);

    if (list_val->extra_space == 0)
        make_extra_space_in_list(list_val);

    lily_value *to_delete = list_val->elems[pos];
    lily_deref(to_delete);
    lily_free(to_delete);

    /* Shove everything leftward hide the hole from erasing the value. */
    if (pos != list_val->num_values)
        memmove(list_val->elems + pos, list_val->elems + pos + 1,
                (list_val->num_values - pos) * sizeof(lily_value *));

    list_val->num_values--;
    list_val->extra_space++;
}
示例#4
0
/* This assigns 'left' to the value within 'right', but does not give 'right' a
   ref increase. One use case for this is List.pop, which takes the element out
   of the List and places it into the result. The value has been assigned over,
   (so all flags carry), but still has the same # of refs. */
void lily_value_assign_noref(lily_value *left, lily_value *right)
{
    if (left->flags & VAL_IS_DEREFABLE)
        lily_deref(left);

    left->value = right->value;
    left->flags = right->flags;
}
示例#5
0
/* Assign one value to another. The right may get a ref, and the left may get a
   deref. Both sides are assumed to be equivalent type-wise (only value and
   flags move over). */
void lily_value_assign(lily_value *left, lily_value *right)
{
    if (right->flags & VAL_IS_DEREFABLE)
        right->value.generic->refcount++;

    if (left->flags & VAL_IS_DEREFABLE)
        lily_deref(left);

    left->value = right->value;
    left->flags = right->flags;
}
示例#6
0
static void destroy_list(lily_value *v)
{

    lily_list_val *lv = v->value.list;

    int i;
    for (i = 0;i < lv->num_values;i++) {
        lily_deref(lv->elems[i]);
        lily_free(lv->elems[i]);
    }

    lily_free(lv->elems);
    lily_free(lv);
}
示例#7
0
void lily_destroy_any(lily_value *v)
{
    lily_any_val *av = v->value.any;

    /* Values of type 'any' always have a gc entry, so make sure the value of it
       is set to NULL. This prevents the gc from trying to access this 'any'
       that is about to be destroyed. */
    av->gc_entry->value.generic = NULL;

    lily_deref(av->inner_value);

    lily_free(av->inner_value);
    lily_free(av);
}
示例#8
0
void lily_list_clear(lily_vm_state *vm, uint16_t argc, uint16_t *code)
{
    lily_value **vm_regs = vm->vm_regs;
    lily_list_val *list_val = vm_regs[code[1]]->value.list;
    int i;

    for (i = 0;i < list_val->num_values;i++) {
        lily_deref(list_val->elems[i]);
        lily_free(list_val->elems[i]);
    }

    list_val->extra_space += list_val->num_values;
    list_val->num_values = 0;
}
示例#9
0
static void destroy_function(lily_value *v)
{
    lily_function_val *fv = v->value.function;
    if (fv->gc_entry == lily_gc_stopper)
        return;

    if (fv->num_upvalues == (uint16_t)-1) {
        lily_free(fv->docstring);
        lily_free(fv->code);
        lily_free(fv);
    }
    else {
        int full_destroy = 1;

        if (fv->gc_entry) {
            if (fv->gc_entry->last_pass == -1) {
                full_destroy = 0;
                fv->gc_entry = lily_gc_stopper;
            }
            else
                fv->gc_entry->value.generic = NULL;
        }

        lily_value **upvalues = fv->upvalues;
        int count = fv->num_upvalues;
        int i;

        for (i = 0;i < count;i++) {
            lily_value *up = upvalues[i];
            if (up) {
                up->cell_refcount--;

                if (up->cell_refcount == 0) {
                    lily_deref(up);
                    lily_free(up);
                }
            }
        }
        lily_free(upvalues);

        if (full_destroy)
            lily_free(fv);
    }
}
示例#10
0
static void free_literals(lily_value_stack *literals)
{
    while (lily_vs_pos(literals)) {
        lily_literal *lit = (lily_literal *)lily_vs_pop(literals);

        /* Literals are marked where their refcount won't be adjusted during
           the vm's run. Any literal that isn't primitive will have 1 ref, and
           can be destroyed by sending it to deref. */
        if ((lit->flags &
            (VAL_IS_BOOLEAN | VAL_IS_INTEGER | VAL_IS_DOUBLE)) == 0) {
            lit->flags |= VAL_IS_DEREFABLE;
            lily_deref((lily_value *)lit);
        }

        lily_free(lit);
    }

    lily_free_value_stack(literals);
}
示例#11
0
void lily_destroy_list(lily_value *v)
{
    lily_list_val *lv = v->value.list;

    /* If this list has a gc entry, then make the value of it NULL. This
        prevents the gc from trying to access the list once it has been
        destroyed. */
    if (lv->gc_entry != NULL)
        lv->gc_entry->value.generic = NULL;

    int i;
    for (i = 0;i < lv->num_values;i++) {
        lily_deref(lv->elems[i]);
        lily_free(lv->elems[i]);
    }

    lily_free(lv->elems);
    lily_free(lv);
}
示例#12
0
static void free_ties(lily_symtab *symtab, lily_tie *tie_iter)
{
    lily_tie *tie_next;

    while (tie_iter) {
        tie_next = tie_iter->next;
        /* Literals are marked where their refcount won't be adjusted during
           the vm's run. Any literal that isn't primitive will have 1 ref, and
           can be destroyed by sending it to deref. */
        if ((tie_iter->move_flags &
            (VAL_IS_BOOLEAN | VAL_IS_INTEGER | VAL_IS_DOUBLE)) == 0) {
            lily_value v;
            v.flags = tie_iter->move_flags | VAL_IS_DEREFABLE;
            v.value = tie_iter->value;

            lily_deref(&v);
        }
        lily_free(tie_iter);
        tie_iter = tie_next;
    }
}
示例#13
0
static void destroy_dynamic(lily_value *v)
{
    lily_dynamic_val *dv = v->value.dynamic;
    if (dv->gc_entry == lily_gc_stopper)
        return;

    int full_destroy = 1;
    if (dv->gc_entry) {
        if (dv->gc_entry->last_pass == -1) {
            full_destroy = 0;
            dv->gc_entry = lily_gc_stopper;
        }
        else
            dv->gc_entry->value.generic = NULL;
    }

    lily_deref(dv->inner_value);
    lily_free(dv->inner_value);

    if (full_destroy)
        lily_free(dv);
}