SCI: Fix DEBUG_GC mode and permanently enable it
svn-id: r50430
This commit is contained in:
parent
31b2902714
commit
6c0205b104
3 changed files with 64 additions and 48 deletions
|
@ -28,8 +28,6 @@
|
||||||
|
|
||||||
namespace Sci {
|
namespace Sci {
|
||||||
|
|
||||||
//#define DEBUG_GC
|
|
||||||
|
|
||||||
struct WorklistManager {
|
struct WorklistManager {
|
||||||
Common::Array<reg_t> _worklist;
|
Common::Array<reg_t> _worklist;
|
||||||
reg_t_hash_map _map;
|
reg_t_hash_map _map;
|
||||||
|
@ -151,68 +149,41 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
|
||||||
return normal_map;
|
return normal_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct deallocator_t {
|
|
||||||
SegManager *segMan;
|
|
||||||
SegmentObj *mobj;
|
|
||||||
#ifdef DEBUG_GC
|
|
||||||
char *segnames[SEG_TYPE_MAX + 1];
|
|
||||||
int segcount[SEG_TYPE_MAX + 1];
|
|
||||||
#endif
|
|
||||||
reg_t_hash_map *use_map;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void free_unless_used(deallocator_t *deallocator, reg_t addr) {
|
|
||||||
reg_t_hash_map *use_map = deallocator->use_map;
|
|
||||||
|
|
||||||
if (!use_map->contains(addr)) {
|
|
||||||
// Not found -> we can free it
|
|
||||||
deallocator->mobj->freeAtAddress(deallocator->segMan, addr);
|
|
||||||
#ifdef DEBUG_GC
|
|
||||||
debugC(2, kDebugLevelGC, "[GC] Deallocating %04x:%04x", PRINT_REG(addr));
|
|
||||||
deallocator->segcount[deallocator->mobj->getType()]++;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void run_gc(EngineState *s) {
|
void run_gc(EngineState *s) {
|
||||||
uint seg_nr;
|
uint seg_nr;
|
||||||
deallocator_t deallocator;
|
|
||||||
SegManager *segMan = s->_segMan;
|
SegManager *segMan = s->_segMan;
|
||||||
|
|
||||||
#ifdef DEBUG_GC
|
const char *segnames[SEG_TYPE_MAX + 1];
|
||||||
|
int segcount[SEG_TYPE_MAX + 1];
|
||||||
debugC(2, kDebugLevelGC, "[GC] Running...");
|
debugC(2, kDebugLevelGC, "[GC] Running...");
|
||||||
memset(&(deallocator.segcount), 0, sizeof(int) * (SEG_TYPE_MAX + 1));
|
memset(segcount, 0, sizeof(segcount));
|
||||||
#endif
|
|
||||||
|
|
||||||
deallocator.segMan = segMan;
|
reg_t_hash_map *use_map = find_all_used_references(s);
|
||||||
deallocator.use_map = find_all_used_references(s);
|
|
||||||
|
|
||||||
for (seg_nr = 1; seg_nr < segMan->_heap.size(); seg_nr++) {
|
for (seg_nr = 1; seg_nr < segMan->_heap.size(); seg_nr++) {
|
||||||
if (segMan->_heap[seg_nr] != NULL) {
|
if (segMan->_heap[seg_nr] != NULL) {
|
||||||
deallocator.mobj = segMan->_heap[seg_nr];
|
SegmentObj *mobj = segMan->_heap[seg_nr];
|
||||||
#ifdef DEBUG_GC
|
segnames[mobj->getType()] = SegmentObj::getSegmentTypeName(mobj->getType());
|
||||||
deallocator.segnames[deallocator.mobj->getType()] = deallocator.mobj->type; // FIXME: add a segment "name"
|
const Common::Array<reg_t> tmp = mobj->listAllDeallocatable(seg_nr);
|
||||||
#endif
|
|
||||||
const Common::Array<reg_t> tmp = deallocator.mobj->listAllDeallocatable(seg_nr);
|
|
||||||
for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) {
|
for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) {
|
||||||
free_unless_used(&deallocator, *it);
|
const reg_t addr = *it;
|
||||||
|
if (!use_map->contains(addr)) {
|
||||||
|
// Not found -> we can free it
|
||||||
|
mobj->freeAtAddress(segMan, addr);
|
||||||
|
debugC(2, kDebugLevelGC, "[GC] Deallocating %04x:%04x", PRINT_REG(addr));
|
||||||
|
segcount[mobj->getType()]++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete deallocator.use_map;
|
delete use_map;
|
||||||
|
|
||||||
#ifdef DEBUG_GC
|
debugC(2, kDebugLevelGC, "[GC] Summary:");
|
||||||
{
|
for (int i = 0; i <= SEG_TYPE_MAX; i++)
|
||||||
int i;
|
if (segcount[i])
|
||||||
debugC(2, kDebugLevelGC, "[GC] Summary:");
|
debugC(2, kDebugLevelGC, "\t%d\t* %s", segcount[i], segnames[i]);
|
||||||
for (i = 0; i <= SEG_TYPE_MAX; i++)
|
|
||||||
if (deallocator.segcount[i])
|
|
||||||
debugC(2, kDebugLevelGC, "\t%d\t* %s", deallocator.segcount[i], deallocator.segnames[i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End of namespace Sci
|
} // End of namespace Sci
|
||||||
|
|
|
@ -86,6 +86,50 @@ SegmentObj *SegmentObj::createSegmentObj(SegmentType type) {
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *SegmentObj::getSegmentTypeName(SegmentType type) {
|
||||||
|
switch (type) {
|
||||||
|
case SEG_TYPE_SCRIPT:
|
||||||
|
return "script";
|
||||||
|
break;
|
||||||
|
case SEG_TYPE_CLONES:
|
||||||
|
return "clones";
|
||||||
|
break;
|
||||||
|
case SEG_TYPE_LOCALS:
|
||||||
|
return "locals";
|
||||||
|
break;
|
||||||
|
case SEG_TYPE_SYS_STRINGS:
|
||||||
|
return "strings";
|
||||||
|
break;
|
||||||
|
case SEG_TYPE_STACK:
|
||||||
|
return "stack";
|
||||||
|
break;
|
||||||
|
case SEG_TYPE_HUNK:
|
||||||
|
return "hunk";
|
||||||
|
break;
|
||||||
|
case SEG_TYPE_LISTS:
|
||||||
|
return "lists";
|
||||||
|
break;
|
||||||
|
case SEG_TYPE_NODES:
|
||||||
|
return "nodes";
|
||||||
|
break;
|
||||||
|
case SEG_TYPE_DYNMEM:
|
||||||
|
return "dynmem";
|
||||||
|
break;
|
||||||
|
#ifdef ENABLE_SCI32
|
||||||
|
case SEG_TYPE_ARRAY:
|
||||||
|
return "array";
|
||||||
|
break;
|
||||||
|
case SEG_TYPE_STRING:
|
||||||
|
return "string";
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
error("Unknown SegmentObj type %d", type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// This helper function is used by Script::relocateLocal and Object::relocate
|
// This helper function is used by Script::relocateLocal and Object::relocate
|
||||||
// Duplicate in segment.cpp and script.cpp
|
// Duplicate in segment.cpp and script.cpp
|
||||||
static bool relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location, size_t scriptSize) {
|
static bool relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location, size_t scriptSize) {
|
||||||
|
|
|
@ -82,6 +82,7 @@ struct SegmentObj : public Common::Serializable {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static SegmentObj *createSegmentObj(SegmentType type);
|
static SegmentObj *createSegmentObj(SegmentType type);
|
||||||
|
static const char *getSegmentTypeName(SegmentType type);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SegmentObj(SegmentType type) : _type(type) {}
|
SegmentObj(SegmentType type) : _type(type) {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue