static void * node_contains(comparer c, node n, void * e) { if (n == NULL) return NULL; else if (c(e, n->data) < 0) return node_contains(c,n->left,e); else if (c(e, n->data) > 0) { return node_contains(c,n->right,e); } else { return n->data; } }
bool node_contains(list_node_t *n, uint64_t v) { if(n == NULL) { return false; } else if(n->value == v) { return true; } else { return node_contains(n->next, v); } }
/// Uppgift #2 bool list_contains_rec(list_t *l, uint64_t v) { return node_contains(l->first, v); }
void * tree_get(tree t, void * e) { return node_contains(t->comp, t->header, e); }
void seek_live(term_t *tp, apr_memnode_t *newest, heap_t *hp) { term_t t = *tp; apr_memnode_t *node; term_box_t *ptr; // newest node - the node last generation the term may belong to // the node chain starts with the newest and goes to hp->gc_spot if (is_immed(t)) return; ptr = peel(t); node = newest; while (node != hp->gc_spot) { if (node_contains(node, ptr)) { // the term belongs to the newer generation // of terms; recurse to find possible references // to live terms in hp->gc_spot // only tuples, conses, funs (frozen) // and binaries (data, parent) contain references // order of popularity: // cons - tuple - binary - fun if (is_cons(t)) { seek_live(&ptr->cons.head, node, hp); seek_live(&ptr->cons.tail, node, hp); } else if (is_tuple(t)) { int i; int n = ptr->tuple.size; for (i = 0; i < n; i++) seek_live(&ptr->tuple.elts[i], node, hp); } else if (is_binary(t)) { if (ptr->binary.parent != noval) { term_box_t *parent; seek_live(&ptr->binary.parent, node, hp); parent = peel(ptr->binary.parent); ptr->binary.data = parent->binary.data + ptr->binary.offset; } } else if (is_fun(t)) { seek_live(&ptr->fun.frozen, node, hp); } return; } node = node->next; } if (node_contains(hp->gc_spot, ptr)) { // the term should be recreated // the term may have already been moved // and the term value has been replaced with // the buried reference to the new location if (is_grave(t)) { *tp = ptr->grave.skeleton; return; } // list - tuple - binary - fun - bignum - pid - float if (is_list(t)) { term_t cons = heap_cons2(hp, ptr->cons.head, ptr->cons.tail); term_box_t *box = peel(cons); seek_live(&box->cons.head, hp->gc_spot, hp); seek_live(&box->cons.tail, hp->gc_spot, hp); *tp = cons; } else if (is_tuple(t)) { term_t tuple = heap_tuple(hp, ptr->tuple.size); term_box_t *box = peel(tuple); int i; for (i = 0; i < ptr->tuple.size; i++) { box->tuple.elts[i] = ptr->tuple.elts[i]; seek_live(&box->tuple.elts[i], hp->gc_spot, hp); } *tp = tuple; } else if (is_binary(t)) { term_t parent = ptr->binary.parent; term_t b; if (parent == noval) b = heap_binary(hp, ptr->binary.bit_size, ptr->binary.data); else { apr_byte_t *data; seek_live(&parent, hp->gc_spot, hp); data = peel(parent)->binary.data + ptr->binary.offset; b = heap_binary_shared(hp, ptr->binary.bit_size, data, parent); } *tp = b; } else if (is_fun(t)) { term_t f = heap_fun(hp, ptr->fun.module, ptr->fun.function, ptr->fun.arity, ptr->fun.uniq, ptr->fun.index, ptr->fun.frozen); seek_live(&peel(f)->fun.frozen, hp->gc_spot, hp); *tp = f; } else if (is_bignum(t)) { mp_int ma = bignum_to_mp(t); *tp = heap_bignum(hp, SIGN(&ma), USED(&ma), DIGITS(&ma)); } else if (is_long_id(t)) { *tp = heap_long_id(hp, ptr->long_id.node, ptr->long_id.serial, ptr->long_id.tag_creation); } else // if (is_float(t)) { assert(is_float(t)); *tp = heap_float(hp, float_value(t)); } // bury the term ptr->grave.cross = MAGIC_CROSS; ptr->grave.skeleton = *tp; return; } else { // the term belong to the older generation or // to the literal pool of the module -- ignore return; } }