[Scummvm-cvs-logs] SF.net SVN: scummvm:[40263] scummvm/trunk/engines/sci/engine/gc.cpp

fingolfin at users.sourceforge.net fingolfin at users.sourceforge.net
Sun May 3 11:17:55 CEST 2009


Revision: 40263
          http://scummvm.svn.sourceforge.net/scummvm/?rev=40263&view=rev
Author:   fingolfin
Date:     2009-05-03 09:17:55 +0000 (Sun, 03 May 2009)

Log Message:
-----------
SCI: Changed VM GC code to use Common::Array

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/gc.cpp

Modified: scummvm/trunk/engines/sci/engine/gc.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/gc.cpp	2009-05-03 09:00:53 UTC (rev 40262)
+++ scummvm/trunk/engines/sci/engine/gc.cpp	2009-05-03 09:17:55 UTC (rev 40263)
@@ -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;
-};
+struct WorklistManager {
+	Common::Array<reg_t> _worklist;
+	reg_t_hash_map _map;
 
-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;
-}
+	void push(reg_t reg) {
+		if (!reg.segment) // No numbers
+			return;
 
-static worklist_t *new_worklist() {
-	return fresh_worklist(NULL);
-}
+	#ifdef DEBUG_GC_VERBOSE
+		sciprintf("[GC] Adding "PREG"\n", PRINT_REG(reg));
+	#endif
 
-static void worklist_push(worklist_t **wlp, reg_t_hash_map *hashmap, reg_t reg) {
-	worklist_t *wl = *wlp;
+		if (_map.contains(reg))
+			return; // already dealt with it
 
-	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
-
-	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);
-}
-
-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");
+		_map.setVal(reg, true);
+		_worklist.push_back(reg);
 	}
+};
 
-	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);
-	}
-}
-
-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 @@
 }
 
 
-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 @@
 
 	// 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 *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 @@
 		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 @@
 				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 @@
 #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 @@
 	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 @@
 		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 @@
 	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 @@
 		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;


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list