diff options
Diffstat (limited to 'engines/sci/engine/gc.cpp')
-rw-r--r-- | engines/sci/engine/gc.cpp | 110 |
1 files changed, 42 insertions, 68 deletions
diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index 7824595229..86ab8f3cd5 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -27,8 +27,8 @@ #define WORKLIST_CHUNK_SIZE 32 -/*#define DEBUG_GC*/ -/*#define DEBUG_GC_VERBOSE*/ +//#define DEBUG_GC +//#define DEBUG_GC_VERBOSE typedef struct _worklist { int used; @@ -36,33 +36,29 @@ typedef struct _worklist { struct _worklist *next; } worklist_t; -static worklist_t * -fresh_worklist(worklist_t *old) { +static worklist_t *fresh_worklist(worklist_t *old) { worklist_t *retval = (worklist_t*)sci_malloc(sizeof(worklist_t)); retval->used = 0; retval->next = old; return retval; } -static worklist_t * -new_worklist() { +static worklist_t *new_worklist() { return fresh_worklist(NULL); } -static void -worklist_push(worklist_t **wlp, reg_t_hash_map *hashmap, reg_t reg) { +static void worklist_push(worklist_t **wlp, reg_t_hash_map *hashmap, reg_t reg) { worklist_t *wl = *wlp; - if (!reg.segment) /* No numbers */ + if (!reg.segment) // No numbers return; #ifdef DEBUG_GC_VERBOSE sciprintf("[GC] Adding "PREG"\n", PRINT_REG(reg)); #endif - if (hashmap->contains(reg)) - return; /* already dealt with it */ + return; // already dealt with it hashmap->setVal(reg, true); @@ -72,13 +68,11 @@ worklist_push(worklist_t **wlp, reg_t_hash_map *hashmap, reg_t reg) { wl->entries[wl->used++] = reg; } -static int -worklist_has_next(worklist_t *wl) { +static int worklist_has_next(worklist_t *wl) { return (wl && wl->used); } -static reg_t -worklist_pop(worklist_t **wlp) { +static reg_t worklist_pop(worklist_t **wlp) { worklist_t *wl = *wlp; reg_t retval; @@ -97,8 +91,7 @@ worklist_pop(worklist_t **wlp) { return retval; } -static void -free_worklist(worklist_t *wl) { +static void free_worklist(worklist_t *wl) { if (wl) { if (wl->next) free_worklist(wl->next); @@ -106,17 +99,14 @@ free_worklist(worklist_t *wl) { } } -static reg_t_hash_map * -normalise_hashmap_ptrs(reg_t_hash_map *nonnormal_map, seg_interface_t **interfaces, int interfaces_nr) { +static reg_t_hash_map * normalise_hashmap_ptrs(reg_t_hash_map *nonnormal_map, seg_interface_t **interfaces, int interfaces_nr) { reg_t_hash_map *normal_map = new reg_t_hash_map(); for (reg_t_hash_map::iterator i = nonnormal_map->begin(); i != nonnormal_map->end(); ++i) { seg_interface_t *interfce; reg_t reg = i->_key; - interfce = (reg.segment < interfaces_nr) - ? interfaces[reg.segment] - : NULL; - + interfce = (reg.segment < interfaces_nr) ? interfaces[reg.segment] : NULL; + if (interfce) { reg = interfce->find_canonic_address(interfce, reg); normal_map->setVal(reg, true); @@ -132,14 +122,12 @@ typedef struct { worklist_t **worklist_ref; } worklist_manager_t; -void -add_outgoing_refs(void *pre_wm, reg_t addr) { +void add_outgoing_refs(void *pre_wm, reg_t addr) { worklist_manager_t *wm = (worklist_manager_t *) pre_wm; worklist_push(wm->worklist_ref, wm->nonnormal_map, addr); } -reg_t_hash_map * -find_all_used_references(state_t *s) { +reg_t_hash_map *find_all_used_references(state_t *s) { seg_manager_t *sm = &(s->seg_manager); seg_interface_t **interfaces = (seg_interface_t**)sci_calloc(sizeof(seg_interface_t *), sm->heap_size); reg_t_hash_map *nonnormal_map = new reg_t_hash_map(); @@ -157,12 +145,12 @@ find_all_used_references(state_t *s) { else interfaces[i] = get_seg_interface(sm, i); - /* Initialise */ - /* Init: Registers */ + // Initialise + // Init: Registers worklist_push(&worklist, nonnormal_map, s->r_acc); worklist_push(&worklist, nonnormal_map, s->r_prev); - /* Init: Value Stack */ - /* We do this one by hand since the stack doesn't know the current execution stack */ + // Init: Value Stack + // We do this one by hand since the stack doesn't know the current execution stack { exec_stack_t *xs = s->execution_stack + s->execution_stack_pos; reg_t *pos; @@ -174,8 +162,7 @@ find_all_used_references(state_t *s) { sciprintf("[GC] -- Finished adding value stack"); #endif - - /* Init: Execution Stack */ + // Init: Execution Stack for (i = 0; i <= s->execution_stack_pos; i++) { exec_stack_t *es = s->execution_stack + i; @@ -190,24 +177,22 @@ find_all_used_references(state_t *s) { sciprintf("[GC] -- Finished adding execution stack"); #endif - /* Init: Explicitly loaded scripts */ + // Init: Explicitly loaded scripts for (i = 1; i < sm->heap_size; i++) if (interfaces[i] && interfaces[i]->type_id == MEM_OBJ_SCRIPT) { script_t *script = &(interfaces[i]->mobj->data.script); - if (script->lockers) { /* Explicitly loaded? */ + if (script->lockers) { // Explicitly loaded? int obj_nr; - /* Locals, if present */ + // Locals, if present worklist_push(&worklist, nonnormal_map, make_reg(script->locals_segment, 0)); - /* All objects (may be classes, may be indirectly reachable) */ + // All objects (may be classes, may be indirectly reachable) for (obj_nr = 0; obj_nr < script->objects_nr; obj_nr++) { object_t *obj = script->objects + obj_nr; - worklist_push(&worklist, - nonnormal_map, - obj->pos); + worklist_push(&worklist, nonnormal_map, obj->pos); } } } @@ -215,37 +200,33 @@ find_all_used_references(state_t *s) { sciprintf("[GC] -- Finished explicitly loaded scripts, done with root set"); #endif - - /* Run Worklist Algorithm */ + // Run Worklist Algorithm while (worklist_has_next(worklist)) { reg_t reg = worklist_pop(&worklist); - if (reg.segment != s->stack_segment) { /* No need to repeat this one */ + if (reg.segment != s->stack_segment) { // No need to repeat this one #ifdef DEBUG_GC_VERBOSE sciprintf("[GC] Checking "PREG"\n", PRINT_REG(reg)); #endif - if (reg.segment < sm->heap_size - && interfaces[reg.segment]) - interfaces[reg.segment]->list_all_outgoing_references(interfaces[reg.segment], - s, - reg, - &worklist_manager, - add_outgoing_refs); + if (reg.segment < sm->heap_size && interfaces[reg.segment]) + interfaces[reg.segment]->list_all_outgoing_references(interfaces[reg.segment], s, reg, + &worklist_manager, add_outgoing_refs); } } - /* Normalise */ + // Normalise normal_map = normalise_hashmap_ptrs(nonnormal_map, interfaces, sm->heap_size); - /* Cleanup */ + // Cleanup for (i = 1; i < sm->heap_size; i++) if (interfaces[i]) interfaces[i]->deallocate_self(interfaces[i]); + free(interfaces); delete nonnormal_map; + return normal_map; } - typedef struct { seg_interface_t *interfce; #ifdef DEBUG_GC @@ -255,13 +236,12 @@ typedef struct { reg_t_hash_map *use_map; } deallocator_t; -void -free_unless_used(void *pre_use_map, reg_t addr) { - deallocator_t *deallocator = (deallocator_t *) pre_use_map; +void free_unless_used(void *pre_use_map, reg_t addr) { + deallocator_t *deallocator = (deallocator_t *)pre_use_map; reg_t_hash_map *use_map = deallocator->use_map; if (!use_map->contains(addr)) { - /* Not found -> we can free it */ + // Not found -> we can free it deallocator->interfce->free_at_address(deallocator->interfce, addr); #ifdef DEBUG_GC sciprintf("[GC] Deallocating "PREG"\n", PRINT_REG(addr)); @@ -271,8 +251,7 @@ free_unless_used(void *pre_use_map, reg_t addr) { } -void -run_gc(state_t *s) { +void run_gc(state_t *s) { int seg_nr; deallocator_t deallocator; seg_manager_t *sm = &(s->seg_manager); @@ -285,19 +264,16 @@ run_gc(state_t *s) { deallocator.use_map = find_all_used_references(s); - for (seg_nr = 1; seg_nr < sm->heap_size; seg_nr++) + for (seg_nr = 1; seg_nr < sm->heap_size; seg_nr++) { if (sm->heap[seg_nr] != NULL) { deallocator.interfce = get_seg_interface(sm, seg_nr); #ifdef DEBUG_GC deallocator.segnames[deallocator.interfce->type_id] = deallocator.interfce->type; #endif - - deallocator.interfce->list_all_deallocatable(deallocator.interfce, - &deallocator, - free_unless_used); - + deallocator.interfce->list_all_deallocatable(deallocator.interfce, &deallocator, free_unless_used); deallocator.interfce->deallocate_self(deallocator.interfce); } + } delete deallocator.use_map; @@ -307,9 +283,7 @@ run_gc(state_t *s) { sciprintf("[GC] Summary:\n"); for (i = 0; i <= MEM_OBJ_MAX; i++) if (deallocator.segcount[i]) - sciprintf("\t%d\t* %s\n", - deallocator.segcount[i], - deallocator.segnames[i]); + sciprintf("\t%d\t* %s\n", deallocator.segcount[i], deallocator.segnames[i]); } #endif } |