void gc_mark_object(Object* object) { ObjectHeader* head = &((ObjectHeader*)object)[-1]; debug("mark %p\n",head); long size; if (!heap_find(vm, head)) { debug2("******** unfind in heap %p\n", &head[1]); return; } debug2("find\n"); if (head->marked) return; long* bitmap; head->marked = 1; switch(head->type) { case OBJ_BOXED_ARRAY: debug("BOXED_ARRAY\n"); size = ((int)head->size) / sizeof(long); debug2("size=%ld\n",size); for(int i = 0; i < size; i++) gc_mark_object(object->field[i]); debug2("END\n"); break; case OBJ_PAIR: debug("PAIR\n"); gc_mark_object(object->fst); gc_mark_object(object->snd); break; case OBJ_UNBOXED_ARRAY: debug("UNBOXED ARRAY\n"); break; case OBJ_VM: debug("VM\n"); break; case OBJ_RECORD: size = ((int)head->size) / sizeof(long); debug("RECORD size=%ld\n", size); bitmap = &object->longs[size]; debug2("size=%ld\n",size); for(int i = 0; i < size; i++) { if(bitmap[i/sizeof(long)] & (1 << (i % sizeof(long)))) gc_mark_object(object->field[i]); else { debug2("skip %d\n", i); } } break; } }
/* return a list of nodes representing the shortest path from v * we can't have negative edges, distances are either an overestimate * or exact (that's why we don't update downstream nodes */ void graph_explore_dijkstra(graph_t *g, graph_vertex_t *s, graph_vertex_t *e, visit_func_t visit) { /* clear graph search assets unless we're exploring the whole graph */ if (g) graph_clear_pathtrace(g); /* mark starting point's prev as a self reference to avoid looping back */ s->path.prev = s; /* just a simple queue for breadth first search */ heap_t *prioq = heap_init(NULL, (cmp_func_t)min_path_cmp); heap_insert(prioq, s); while ((s = heap_pop(prioq))) { int clock = 0; list_node_t *it; /* break if searching for a specific destination */ if (e && e == s) break; s->path.visited = 1; s->path.pre_clock = clock++; if (visit) visit(s); for (it = s->edges->first; it != NULL; it = it->next) { graph_edge_t *ve = (graph_edge_t *)it->data; graph_vertex_t *v = ve->connection; if (!v->path.prev || v->path.distance > s->path.distance + ve->weight) { v->path.prev = s; v->path.distance = s->path.distance + ve->weight; /* check if destination is already on the heap */ ssize_t idx = heap_find(prioq, v); if (idx != -1) heap_bubble_up(prioq, v, idx); else heap_insert(prioq, v); } } } heap_destroy(prioq); }
Object* gc_copy(VM* vm, Object* object) { ObjectHeader* head = &((ObjectHeader*)object)[-1]; debug("gc copy %p\n",head); long size; if (!heap_find(vm, head)) return object; long* bitmap; Object* obj; switch(head->type) { case OBJ_BOXED_ARRAY: obj = gc_alloc((ObjectType)head->type, head->size); size = ((int)head->size) / sizeof(long); debug("size=%ld\n",size); for(int i = 0; i < size; i++) obj->field[i] = gc_copy(vm,object->field[i]); break; case OBJ_PAIR: obj = gc_alloc((ObjectType)head->type, head->size); obj->fst = gc_copy(vm,object->fst); obj->snd = gc_copy(vm,object->snd); break; case OBJ_UNBOXED_ARRAY: case OBJ_VM: obj = gc_alloc((ObjectType)head->type, head->size); memcpy(obj, object, head->size); break; case OBJ_RECORD: size = ((int)head->size) / sizeof(long); obj = gc_alloc((ObjectType)head->type, head->size); memcpy(obj, object, head->size); bitmap = &object->longs[size]; for(int i = 0; i < size; i++) { if(bitmap[i/sizeof(long)] & (1 << (i % sizeof(long)))) obj->field[i] = gc_copy(vm,object->field[i]); } break; } return obj; }
void gc_mark_object(Object* object) { ObjectHeader* head = &((ObjectHeader*)object)[-1]; debug("mark %p\n",head); long size; if (!heap_find(head)) return; if (head->marked) return; long* bitmap; head->marked = 1; switch(head->type) { case OBJ_BOXED_ARRAY: size = ((int)head->size) / sizeof(long); debug("size=%ld\n",size); for(int i = 0; i < size; i++) gc_mark_object(object->field[i]); break; case OBJ_PAIR: debug("PAIR\n"); gc_mark_object(object->pair.fst); gc_mark_object(object->pair.snd); break; case OBJ_UNBOXED_ARRAY: break; case OBJ_RECORD: size = ((int)head->size) / sizeof(long); debug("RECORD size=%ld\n", size); bitmap = &object->longs[size]; debug("size=%ld\n",size); for(int i = 0; i < size; i++) { if(bitmap[i/sizeof(long)] & (1 << (i % sizeof(long)))) gc_mark_object(object->field[i]); else debug("skip %d\n", i); } break; } }