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 {
|
||||
|
||||
//#define DEBUG_GC
|
||||
|
||||
struct WorklistManager {
|
||||
Common::Array<reg_t> _worklist;
|
||||
reg_t_hash_map _map;
|
||||
|
@ -151,68 +149,41 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
|
|||
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) {
|
||||
uint seg_nr;
|
||||
deallocator_t deallocator;
|
||||
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...");
|
||||
memset(&(deallocator.segcount), 0, sizeof(int) * (SEG_TYPE_MAX + 1));
|
||||
#endif
|
||||
memset(segcount, 0, sizeof(segcount));
|
||||
|
||||
deallocator.segMan = segMan;
|
||||
deallocator.use_map = find_all_used_references(s);
|
||||
reg_t_hash_map *use_map = find_all_used_references(s);
|
||||
|
||||
for (seg_nr = 1; seg_nr < segMan->_heap.size(); seg_nr++) {
|
||||
if (segMan->_heap[seg_nr] != NULL) {
|
||||
deallocator.mobj = segMan->_heap[seg_nr];
|
||||
#ifdef DEBUG_GC
|
||||
deallocator.segnames[deallocator.mobj->getType()] = deallocator.mobj->type; // FIXME: add a segment "name"
|
||||
#endif
|
||||
const Common::Array<reg_t> tmp = deallocator.mobj->listAllDeallocatable(seg_nr);
|
||||
SegmentObj *mobj = segMan->_heap[seg_nr];
|
||||
segnames[mobj->getType()] = SegmentObj::getSegmentTypeName(mobj->getType());
|
||||
const Common::Array<reg_t> tmp = mobj->listAllDeallocatable(seg_nr);
|
||||
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
|
||||
{
|
||||
int i;
|
||||
debugC(2, kDebugLevelGC, "[GC] Summary:");
|
||||
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
|
||||
for (int i = 0; i <= SEG_TYPE_MAX; i++)
|
||||
if (segcount[i])
|
||||
debugC(2, kDebugLevelGC, "\t%d\t* %s", segcount[i], segnames[i]);
|
||||
}
|
||||
|
||||
} // End of namespace Sci
|
||||
|
|
|
@ -86,6 +86,50 @@ SegmentObj *SegmentObj::createSegmentObj(SegmentType type) {
|
|||
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
|
||||
// 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) {
|
||||
|
|
|
@ -82,6 +82,7 @@ struct SegmentObj : public Common::Serializable {
|
|||
|
||||
public:
|
||||
static SegmentObj *createSegmentObj(SegmentType type);
|
||||
static const char *getSegmentTypeName(SegmentType type);
|
||||
|
||||
public:
|
||||
SegmentObj(SegmentType type) : _type(type) {}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue