mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-04 17:29:11 +00:00
SCI: Started to merge SegInterface into MemObject
svn-id: r40373
This commit is contained in:
parent
76a48947de
commit
d8738b9090
@ -150,8 +150,8 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
|
||||
#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, &wm, add_outgoing_refs);
|
||||
if (reg.segment < sm->_heap.size() && sm->_heap[reg.segment])
|
||||
sm->_heap[reg.segment]->listAllOutgoingReferences(s, reg, &wm, add_outgoing_refs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,7 +210,7 @@ void run_gc(EngineState *s) {
|
||||
#ifdef DEBUG_GC
|
||||
deallocator.segnames[deallocator.interfce->getType()] = deallocator.interfce->type;
|
||||
#endif
|
||||
deallocator.interfce->listAllDeallocatable(&deallocator, free_unless_used);
|
||||
sm->_heap[seg_nr]->listAllDeallocatable(seg_nr, &deallocator, free_unless_used);
|
||||
delete deallocator.interfce;
|
||||
}
|
||||
}
|
||||
|
@ -2802,12 +2802,14 @@ static void _print_address(void * _, reg_t addr) {
|
||||
static int c_gc_show_reachable(EngineState *s) {
|
||||
reg_t addr = cmd_params[0].reg;
|
||||
|
||||
GET_SEG_INTERFACE(addr.segment);
|
||||
MemObject *mobj = GET_SEGMENT_ANY(*s->seg_manager, addr.segment);
|
||||
if (!mobj) {
|
||||
sciprintf("Unknown segment : %x\n", addr.segment);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sciprintf("Reachable from "PREG":\n", PRINT_REG(addr));
|
||||
seg_interface->listAllOutgoingReferences(s, addr, NULL, _print_address);
|
||||
|
||||
delete seg_interface;
|
||||
mobj->listAllOutgoingReferences(s, addr, NULL, _print_address);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2815,12 +2817,14 @@ static int c_gc_show_reachable(EngineState *s) {
|
||||
static int c_gc_show_freeable(EngineState *s) {
|
||||
reg_t addr = cmd_params[0].reg;
|
||||
|
||||
GET_SEG_INTERFACE(addr.segment);
|
||||
MemObject *mobj = GET_SEGMENT_ANY(*s->seg_manager, addr.segment);
|
||||
if (!mobj) {
|
||||
sciprintf("Unknown segment : %x\n", addr.segment);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sciprintf("Freeable in segment %04x:\n", addr.segment);
|
||||
seg_interface->listAllDeallocatable(NULL, _print_address);
|
||||
|
||||
delete seg_interface;
|
||||
mobj->listAllDeallocatable(addr.segment, NULL, _print_address);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1195,12 +1195,6 @@ reg_t SegInterface::findCanonicAddress(reg_t addr) {
|
||||
void SegInterface::freeAtAddress(reg_t sub_addr) {
|
||||
}
|
||||
|
||||
void SegInterface::listAllDeallocatable(void *param, NoteCallback note) {
|
||||
}
|
||||
|
||||
void SegInterface::listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note) {
|
||||
}
|
||||
|
||||
|
||||
//-------------------- base --------------------
|
||||
class SegInterfaceBase : public SegInterface {
|
||||
@ -1209,7 +1203,6 @@ protected:
|
||||
SegInterface(segmgr, mobj, segId, typeId) {}
|
||||
public:
|
||||
reg_t findCanonicAddress(reg_t addr);
|
||||
void listAllDeallocatable(void *param, NoteCallback note);
|
||||
};
|
||||
|
||||
reg_t SegInterfaceBase::findCanonicAddress(reg_t addr) {
|
||||
@ -1217,8 +1210,12 @@ reg_t SegInterfaceBase::findCanonicAddress(reg_t addr) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
void SegInterfaceBase::listAllDeallocatable(void *param, NoteCallback note) {
|
||||
(*note)(param, make_reg(_segId, 0));
|
||||
void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
|
||||
(*note)(param, make_reg(segId, 0));
|
||||
}
|
||||
|
||||
void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
|
||||
(*note)(param, make_reg(segId, 0));
|
||||
}
|
||||
|
||||
|
||||
@ -1228,7 +1225,6 @@ public:
|
||||
SegInterfaceScript(SegManager *segmgr, MemObject *mobj, SegmentId segId) :
|
||||
SegInterfaceBase(segmgr, mobj, segId, MEM_OBJ_SCRIPT) {}
|
||||
void freeAtAddress(reg_t addr);
|
||||
void listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note);
|
||||
};
|
||||
|
||||
void SegInterfaceScript::freeAtAddress(reg_t addr) {
|
||||
@ -1243,8 +1239,8 @@ void SegInterfaceScript::freeAtAddress(reg_t addr) {
|
||||
_segmgr->deallocateScript(script->nr);
|
||||
}
|
||||
|
||||
void SegInterfaceScript::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
||||
Script *script = (Script *)_mobj;
|
||||
void Script::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
||||
Script *script = this;
|
||||
|
||||
if (addr.offset <= script->buf_size && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(script->buf + addr.offset)) {
|
||||
int idx = RAW_GET_CLASS_INDEX(script, addr);
|
||||
@ -1274,25 +1270,21 @@ public:
|
||||
SegInterfaceClones(SegManager *segmgr, MemObject *mobj, SegmentId segId) :
|
||||
SegInterface(segmgr, mobj, segId, MEM_OBJ_CLONES) {}
|
||||
void freeAtAddress(reg_t addr);
|
||||
void listAllDeallocatable(void *param, NoteCallback note);
|
||||
void listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note);
|
||||
};
|
||||
|
||||
void SegInterfaceClones::listAllDeallocatable(void *param, NoteCallback note) {
|
||||
CloneTable *table = (CloneTable *)_mobj;
|
||||
for (int i = 0; i < table->max_entry; i++)
|
||||
if (ENTRY_IS_VALID(table, i))
|
||||
(*note)(param, make_reg(_segId, i));
|
||||
|
||||
|
||||
template<typename T, int INITIAL, int INCREMENT>
|
||||
void Table<T, INITIAL, INCREMENT>::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
|
||||
for (int i = 0; i < max_entry; i++)
|
||||
if (isValidEntry(i))
|
||||
(*note)(param, make_reg(segId, i));
|
||||
}
|
||||
|
||||
void SegInterfaceClones::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
||||
CloneTable *clone_table = (CloneTable *)_mobj;
|
||||
void CloneTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
||||
CloneTable *clone_table = this;
|
||||
Clone *clone;
|
||||
int i;
|
||||
|
||||
assert(addr.segment == _segId);
|
||||
// assert(addr.segment == _segId);
|
||||
|
||||
if (!(ENTRY_IS_VALID(clone_table, addr.offset))) {
|
||||
fprintf(stderr, "Unexpected request for outgoing references from clone at "PREG"\n", PRINT_REG(addr));
|
||||
@ -1344,7 +1336,6 @@ public:
|
||||
SegInterface(segmgr, mobj, segId, MEM_OBJ_LOCALS) {}
|
||||
reg_t findCanonicAddress(reg_t addr);
|
||||
void freeAtAddress(reg_t addr);
|
||||
void listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note);
|
||||
};
|
||||
|
||||
reg_t SegInterfaceLocals::findCanonicAddress(reg_t addr) {
|
||||
@ -1362,13 +1353,11 @@ void SegInterfaceLocals::freeAtAddress(reg_t sub_addr) {
|
||||
// STUB
|
||||
}
|
||||
|
||||
void SegInterfaceLocals::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
||||
LocalVariables *locals = (LocalVariables *)_mobj;
|
||||
void LocalVariables::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
||||
// assert(addr.segment == _segId);
|
||||
|
||||
assert(addr.segment == _segId);
|
||||
|
||||
for (int i = 0; i < locals->nr; i++)
|
||||
(*note)(param, locals->locals[i]);
|
||||
for (int i = 0; i < nr; i++)
|
||||
(*note)(param, locals[i]);
|
||||
}
|
||||
|
||||
|
||||
@ -1378,7 +1367,6 @@ public:
|
||||
SegInterfaceStack(SegManager *segmgr, MemObject *mobj, SegmentId segId) :
|
||||
SegInterface(segmgr, mobj, segId, MEM_OBJ_STACK) {}
|
||||
reg_t findCanonicAddress(reg_t addr);
|
||||
void listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note);
|
||||
};
|
||||
|
||||
reg_t SegInterfaceStack::findCanonicAddress(reg_t addr) {
|
||||
@ -1386,12 +1374,10 @@ reg_t SegInterfaceStack::findCanonicAddress(reg_t addr) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
void SegInterfaceStack::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
||||
int i;
|
||||
dstack_t &d = *(dstack_t *)_mobj;
|
||||
fprintf(stderr, "Emitting %d stack entries\n", d.nr);
|
||||
for (i = 0; i < d.nr; i++)
|
||||
(*note)(param, d.entries[i]);
|
||||
void dstack_t::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
||||
fprintf(stderr, "Emitting %d stack entries\n", nr);
|
||||
for (int i = 0; i < nr; i++)
|
||||
(*note)(param, entries[i]);
|
||||
fprintf(stderr, "DONE");
|
||||
}
|
||||
|
||||
@ -1417,8 +1403,6 @@ public:
|
||||
SegInterfaceLists(SegManager *segmgr, MemObject *mobj, SegmentId segId) :
|
||||
SegInterface(segmgr, mobj, segId, MEM_OBJ_LISTS) {}
|
||||
void freeAtAddress(reg_t addr);
|
||||
void listAllDeallocatable(void *param, NoteCallback note);
|
||||
void listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note);
|
||||
};
|
||||
|
||||
void SegInterfaceLists::freeAtAddress(reg_t sub_addr) {
|
||||
@ -1426,22 +1410,14 @@ void SegInterfaceLists::freeAtAddress(reg_t sub_addr) {
|
||||
table->freeEntry(sub_addr.offset);
|
||||
}
|
||||
|
||||
void SegInterfaceLists::listAllDeallocatable(void *param, NoteCallback note) {
|
||||
ListTable *table = (ListTable *)_mobj;
|
||||
for (int i = 0; i < table->max_entry; i++)
|
||||
if (ENTRY_IS_VALID(table, i))
|
||||
(*note) (param, make_reg(_segId, i));
|
||||
}
|
||||
|
||||
void SegInterfaceLists::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
||||
ListTable *table = (ListTable *)_mobj;
|
||||
List *list = &(table->table[addr.offset]);
|
||||
|
||||
if (!ENTRY_IS_VALID(table, addr.offset)) {
|
||||
fprintf(stderr, "Invalid list referenced for outgoing references: "PREG"\n", PRINT_REG(addr));
|
||||
void ListTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
||||
if (!isValidEntry(addr.offset)) {
|
||||
warning("Invalid list referenced for outgoing references: "PREG"", PRINT_REG(addr));
|
||||
return;
|
||||
}
|
||||
|
||||
List *list = &(table[addr.offset]);
|
||||
|
||||
note(param, list->first);
|
||||
note(param, list->last);
|
||||
// We could probably get away with just one of them, but
|
||||
@ -1455,8 +1431,6 @@ public:
|
||||
SegInterfaceNodes(SegManager *segmgr, MemObject *mobj, SegmentId segId) :
|
||||
SegInterface(segmgr, mobj, segId, MEM_OBJ_NODES) {}
|
||||
void freeAtAddress(reg_t addr);
|
||||
void listAllDeallocatable(void *param, NoteCallback note);
|
||||
void listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note);
|
||||
};
|
||||
|
||||
void SegInterfaceNodes::freeAtAddress(reg_t sub_addr) {
|
||||
@ -1464,21 +1438,12 @@ void SegInterfaceNodes::freeAtAddress(reg_t sub_addr) {
|
||||
table->freeEntry(sub_addr.offset);
|
||||
}
|
||||
|
||||
void SegInterfaceNodes::listAllDeallocatable(void *param, NoteCallback note) {
|
||||
NodeTable *table = (NodeTable *)_mobj;
|
||||
for (int i = 0; i < table->max_entry; i++)
|
||||
if (ENTRY_IS_VALID(table, i))
|
||||
(*note) (param, make_reg(_segId, i));
|
||||
}
|
||||
|
||||
void SegInterfaceNodes::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
||||
NodeTable *table = (NodeTable *)_mobj;
|
||||
Node *node = &(table->table[addr.offset]);
|
||||
|
||||
if (!ENTRY_IS_VALID(table, addr.offset)) {
|
||||
fprintf(stderr, "Invalid node referenced for outgoing references: "PREG"\n", PRINT_REG(addr));
|
||||
void NodeTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
||||
if (!isValidEntry(addr.offset)) {
|
||||
warning("Invalid node referenced for outgoing references: "PREG"", PRINT_REG(addr));
|
||||
return;
|
||||
}
|
||||
Node *node = &(table[addr.offset]);
|
||||
|
||||
// We need all four here. Can't just stick with 'pred' OR 'succ' because node operations allow us
|
||||
// to walk around from any given node
|
||||
@ -1495,7 +1460,6 @@ public:
|
||||
SegInterfaceHunk(SegManager *segmgr, MemObject *mobj, SegmentId segId) :
|
||||
SegInterface(segmgr, mobj, segId, MEM_OBJ_HUNK) {}
|
||||
void freeAtAddress(reg_t addr);
|
||||
void listAllDeallocatable(void *param, NoteCallback note);
|
||||
};
|
||||
|
||||
void SegInterfaceHunk::freeAtAddress(reg_t sub_addr) {
|
||||
@ -1503,14 +1467,6 @@ void SegInterfaceHunk::freeAtAddress(reg_t sub_addr) {
|
||||
// STUB
|
||||
}
|
||||
|
||||
void SegInterfaceHunk::listAllDeallocatable(void *param, NoteCallback note) {
|
||||
HunkTable *table = (HunkTable *)_mobj;
|
||||
for (int i = 0; i < table->max_entry; i++)
|
||||
if (ENTRY_IS_VALID(table, i))
|
||||
(*note) (param, make_reg(_segId, i));
|
||||
}
|
||||
|
||||
|
||||
//-------------------- dynamic memory --------------------
|
||||
class SegInterfaceDynMem : public SegInterfaceBase {
|
||||
public:
|
||||
|
@ -462,19 +462,6 @@ public:
|
||||
// Parameters: (reg_t) sub_addr: The address (within the given segment) to deallocate
|
||||
virtual void freeAtAddress(reg_t sub_addr);
|
||||
|
||||
// Iterates over and reports all addresses within the current segment
|
||||
// Parameters: note : (voidptr * addr) -> (): Invoked for each address on which free_at_address()
|
||||
// makes sense
|
||||
// (void *) param: Parameter passed to 'note'
|
||||
virtual void listAllDeallocatable(void *param, NoteCallback note);
|
||||
|
||||
// Iterates over all references reachable from the specified object
|
||||
// Parameters: (reg_t) object: The object (within the current segment) to analyse
|
||||
// (void *) param: Parameter passed to 'note'
|
||||
// note : (voidptr * addr) -> (): Invoked for each outgoing reference within the object
|
||||
// Note: This function may also choose to report numbers (segment 0) as adresses
|
||||
virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
|
||||
|
||||
// Get the memory object
|
||||
MemObject *getMobj() { return _mobj; }
|
||||
|
||||
|
@ -56,6 +56,8 @@ struct MemObject /* : public Common::Serializable */ {
|
||||
MemObjectType _type;
|
||||
int _segmgrId; /**< Internal value used by the seg_manager's hash map */
|
||||
|
||||
typedef void (*NoteCallback)(void *param, reg_t addr); // FIXME: Bad choice of name
|
||||
|
||||
public:
|
||||
static MemObject *createMemObject(MemObjectType type);
|
||||
|
||||
@ -72,6 +74,19 @@ public:
|
||||
|
||||
inline MemObjectType getType() const { return _type; }
|
||||
inline int getSegMgrId() const { return _segmgrId; }
|
||||
|
||||
// Iterates over and reports all addresses within the current segment
|
||||
// Parameters: note : (voidptr * addr) -> (): Invoked for each address on which free_at_address()
|
||||
// makes sense
|
||||
// (void *) param: Parameter passed to 'note'
|
||||
virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {}
|
||||
|
||||
// Iterates over all references reachable from the specified object
|
||||
// Parameters: (reg_t) object: The object (within the current segment) to analyse
|
||||
// (void *) param: Parameter passed to 'note'
|
||||
// note : (voidptr * addr) -> (): Invoked for each outgoing reference within the object
|
||||
// Note: This function may also choose to report numbers (segment 0) as adresses
|
||||
virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note) {}
|
||||
};
|
||||
|
||||
|
||||
@ -230,6 +245,7 @@ public:
|
||||
}
|
||||
|
||||
virtual byte *dereference(reg_t pointer, int *size);
|
||||
virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
|
||||
|
||||
// virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
||||
};
|
||||
@ -343,11 +359,13 @@ public:
|
||||
freeScript();
|
||||
}
|
||||
|
||||
void freeScript();
|
||||
|
||||
virtual byte *dereference(reg_t pointer, int *size);
|
||||
virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
|
||||
virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
|
||||
|
||||
// virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
||||
|
||||
void freeScript();
|
||||
};
|
||||
|
||||
/** Data stack */
|
||||
@ -366,6 +384,7 @@ public:
|
||||
}
|
||||
|
||||
virtual byte *dereference(reg_t pointer, int *size);
|
||||
virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
|
||||
|
||||
// virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
||||
};
|
||||
@ -467,6 +486,8 @@ public:
|
||||
entries_used--;
|
||||
}
|
||||
|
||||
virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
|
||||
|
||||
// virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
||||
};
|
||||
|
||||
@ -481,16 +502,20 @@ struct CloneTable : public Table<Clone, 16, 4> {
|
||||
|
||||
free(table[idx].variables); // Free the dynamically allocated memory part
|
||||
}
|
||||
|
||||
virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
|
||||
};
|
||||
|
||||
|
||||
/* NodeTable */
|
||||
struct NodeTable : public Table<Node, 32, 16> {
|
||||
virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
|
||||
};
|
||||
|
||||
|
||||
/* ListTable */
|
||||
struct ListTable : public Table<List, 8, 4> {
|
||||
virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, NoteCallback note);
|
||||
};
|
||||
|
||||
|
||||
@ -520,6 +545,7 @@ public:
|
||||
}
|
||||
|
||||
virtual byte *dereference(reg_t pointer, int *size);
|
||||
virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
|
||||
|
||||
// virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user