aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorMax Horn2009-05-03 09:17:55 +0000
committerMax Horn2009-05-03 09:17:55 +0000
commit5ef0e38fdd4381b174ae7742ff18390dd86a53a2 (patch)
tree0d83c1c325dadfd6197b03d950b76989ecb3716d /engines/sci
parent4d57c1f9a9e849f5d8cd3d56da6bcb51da0789d5 (diff)
downloadscummvm-rg350-5ef0e38fdd4381b174ae7742ff18390dd86a53a2.tar.gz
scummvm-rg350-5ef0e38fdd4381b174ae7742ff18390dd86a53a2.tar.bz2
scummvm-rg350-5ef0e38fdd4381b174ae7742ff18390dd86a53a2.zip
SCI: Changed VM GC code to use Common::Array
svn-id: r40263
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/engine/gc.cpp145
1 files changed, 42 insertions, 103 deletions
diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp
index c3fcfff75f..abdcd9f26f 100644
--- a/engines/sci/engine/gc.cpp
+++ b/engines/sci/engine/gc.cpp
@@ -24,89 +24,39 @@
*/
#include "sci/engine/gc.h"
+#include "common/array.h"
namespace Sci {
-#define WORKLIST_CHUNK_SIZE 32
-
//#define DEBUG_GC
//#define DEBUG_GC_VERBOSE
-struct worklist_t {
- int used;
- reg_t entries[WORKLIST_CHUNK_SIZE];
- worklist_t *next;
-};
-
-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() {
- return fresh_worklist(NULL);
-}
+struct WorklistManager {
+ Common::Array<reg_t> _worklist;
+ reg_t_hash_map _map;
-static void worklist_push(worklist_t **wlp, reg_t_hash_map *hashmap, reg_t reg) {
- worklist_t *wl = *wlp;
+ void push(reg_t reg) {
+ if (!reg.segment) // No numbers
+ return;
- if (!reg.segment) // No numbers
- return;
+ #ifdef DEBUG_GC_VERBOSE
+ sciprintf("[GC] Adding "PREG"\n", PRINT_REG(reg));
+ #endif
-#ifdef DEBUG_GC_VERBOSE
- sciprintf("[GC] Adding "PREG"\n", PRINT_REG(reg));
-#endif
-
- if (hashmap->contains(reg))
- return; // already dealt with it
-
- hashmap->setVal(reg, true);
-
- if (!wl || wl->used == WORKLIST_CHUNK_SIZE)
- *wlp = wl = fresh_worklist(wl);
-
- wl->entries[wl->used++] = reg;
-}
-
-static int worklist_has_next(worklist_t *wl) {
- return (wl && wl->used);
-}
+ if (_map.contains(reg))
+ return; // already dealt with it
-static reg_t worklist_pop(worklist_t **wlp) {
- worklist_t *wl = *wlp;
- reg_t retval;
-
- if (!wl || !wl->used) {
- error("Attempt to pop from empty worklist");
- }
-
- retval = wl->entries[--wl->used];
-
- if (!wl->used) {
- *wlp = wl->next;
- free(wl);
- }
-
- return retval;
-}
-
-static void free_worklist(worklist_t *wl) {
- if (wl) {
- if (wl->next)
- free_worklist(wl->next);
- free(wl);
+ _map.setVal(reg, true);
+ _worklist.push_back(reg);
}
-}
+};
-static reg_t_hash_map *normalise_hashmap_ptrs(reg_t_hash_map *nonnormal_map, SegInterface **interfaces, int interfaces_nr) {
+static reg_t_hash_map *normalise_hashmap_ptrs(reg_t_hash_map &nonnormal_map, const Common::Array<SegInterface *> &interfaces) {
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) {
- SegInterface *interfce;
+ for (reg_t_hash_map::iterator i = nonnormal_map.begin(); i != nonnormal_map.end(); ++i) {
reg_t reg = i->_key;
- interfce = (reg.segment < interfaces_nr) ? interfaces[reg.segment] : NULL;
+ SegInterface *interfce = (reg.segment < interfaces.size()) ? interfaces[reg.segment] : NULL;
if (interfce) {
reg = interfce->findCanonicAddress(reg);
@@ -118,28 +68,19 @@ static reg_t_hash_map *normalise_hashmap_ptrs(reg_t_hash_map *nonnormal_map, Seg
}
-struct worklist_manager_t {
- reg_t_hash_map *nonnormal_map;
- worklist_t **worklist_ref;
-};
-
-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);
+void add_outgoing_refs(void *refcon, reg_t addr) {
+ WorklistManager *wm = (WorklistManager *)refcon;
+ wm->push(addr);
}
reg_t_hash_map *find_all_used_references(EngineState *s) {
SegManager *sm = s->seg_manager;
- SegInterface **interfaces = (SegInterface **)sci_calloc(sizeof(SegInterface *), sm->heap_size);
- reg_t_hash_map *nonnormal_map = new reg_t_hash_map();
+ Common::Array<SegInterface *> interfaces;
reg_t_hash_map *normal_map = NULL;
- worklist_t *worklist = new_worklist();
- worklist_manager_t worklist_manager;
+ WorklistManager wm;
int i;
- worklist_manager.worklist_ref = &worklist;
- worklist_manager.nonnormal_map = nonnormal_map;
-
+ interfaces.resize(sm->heap_size);
for (i = 1; i < sm->heap_size; i++)
if (sm->heap[i] == NULL)
interfaces[i] = NULL;
@@ -148,8 +89,8 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
// Initialise
// Init: Registers
- worklist_push(&worklist, nonnormal_map, s->r_acc);
- worklist_push(&worklist, nonnormal_map, s->r_prev);
+ wm.push(s->r_acc);
+ wm.push(s->r_prev);
// Init: Value Stack
// We do this one by hand since the stack doesn't know the current execution stack
{
@@ -157,7 +98,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
reg_t *pos;
for (pos = s->stack_base; pos < xs.sp; pos++)
- worklist_push(&worklist, nonnormal_map, *pos);
+ wm.push(*pos);
}
#ifdef DEBUG_GC_VERBOSE
sciprintf("[GC] -- Finished adding value stack");
@@ -168,10 +109,10 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
ExecStack &es = s->_executionStack[i];
if (es.type != EXEC_STACK_TYPE_KERNEL) {
- worklist_push(&worklist, nonnormal_map, es.objp);
- worklist_push(&worklist, nonnormal_map, es.sendp);
+ wm.push(es.objp);
+ wm.push(es.sendp);
if (es.type == EXEC_STACK_TYPE_VARSELECTOR)
- worklist_push(&worklist, nonnormal_map, *(es.addr.varp));
+ wm.push(*(es.addr.varp));
}
}
#ifdef DEBUG_GC_VERBOSE
@@ -188,12 +129,12 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
int obj_nr;
// Locals, if present
- worklist_push(&worklist, nonnormal_map, make_reg(script->locals_segment, 0));
+ wm.push(make_reg(script->locals_segment, 0));
// All objects (may be classes, may be indirectly reachable)
for (obj_nr = 0; obj_nr < script->objects_nr; obj_nr++) {
Object *obj = script->objects + obj_nr;
- worklist_push(&worklist, nonnormal_map, obj->pos);
+ wm.push(obj->pos);
}
}
}
@@ -202,29 +143,26 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
#endif
// Run Worklist Algorithm
- while (worklist_has_next(worklist)) {
- reg_t reg = worklist_pop(&worklist);
+ while (!wm._worklist.empty()) {
+ reg_t reg = wm._worklist.back();
+ wm._worklist.pop_back();
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]->listAllOutgoingReferences(s, reg,
- &worklist_manager, add_outgoing_refs);
+ interfaces[reg.segment]->listAllOutgoingReferences(s, reg, &wm, add_outgoing_refs);
}
}
// Normalise
- normal_map = normalise_hashmap_ptrs(nonnormal_map, interfaces, sm->heap_size);
+ normal_map = normalise_hashmap_ptrs(wm._map, interfaces);
// Cleanup
for (i = 1; i < sm->heap_size; i++)
if (interfaces[i])
delete interfaces[i];
- free(interfaces);
- delete nonnormal_map;
-
return normal_map;
}
@@ -237,8 +175,8 @@ struct deallocator_t {
reg_t_hash_map *use_map;
};
-void free_unless_used(void *pre_use_map, reg_t addr) {
- deallocator_t *deallocator = (deallocator_t *)pre_use_map;
+void free_unless_used(void *refcon, reg_t addr) {
+ deallocator_t *deallocator = (deallocator_t *)refcon;
reg_t_hash_map *use_map = deallocator->use_map;
if (!use_map->contains(addr)) {
@@ -246,7 +184,7 @@ void free_unless_used(void *pre_use_map, reg_t addr) {
deallocator->interfce->freeAtAddress(addr);
#ifdef DEBUG_GC
sciprintf("[GC] Deallocating "PREG"\n", PRINT_REG(addr));
- deallocator->segcount[deallocator->interfce->type_id]++;
+ deallocator->segcount[deallocator->interfce->getType()]++;
#endif
}
@@ -258,6 +196,7 @@ void run_gc(EngineState *s) {
SegManager *sm = s->seg_manager;
#ifdef DEBUG_GC
+ extern int c_segtable(EngineState *s);
c_segtable(s);
sciprintf("[GC] Running...\n");
memset(&(deallocator.segcount), 0, sizeof(int) * (MEM_OBJ_MAX + 1));
@@ -269,7 +208,7 @@ void run_gc(EngineState *s) {
if (sm->heap[seg_nr] != NULL) {
deallocator.interfce = sm->getSegInterface(seg_nr);
#ifdef DEBUG_GC
- deallocator.segnames[deallocator.interfce->type_id] = deallocator.interfce->type;
+ deallocator.segnames[deallocator.interfce->getType()] = deallocator.interfce->type;
#endif
deallocator.interfce->listAllDeallocatable(&deallocator, free_unless_used);
delete deallocator.interfce;