mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 13:50:13 +00:00
SCI: Converted "segment interfaces" into classes
svn-id: r38782
This commit is contained in:
parent
7d21acd18b
commit
ac409a2ab7
@ -100,7 +100,7 @@ static void free_worklist(worklist_t *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, SegInterface **interfaces, int interfaces_nr) {
|
||||
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) {
|
||||
@ -109,7 +109,7 @@ static reg_t_hash_map * normalise_hashmap_ptrs(reg_t_hash_map *nonnormal_map, Se
|
||||
interfce = (reg.segment < interfaces_nr) ? interfaces[reg.segment] : NULL;
|
||||
|
||||
if (interfce) {
|
||||
reg = interfce->find_canonic_address(interfce, reg);
|
||||
reg = interfce->findCanonicAddress(reg);
|
||||
normal_map->setVal(reg, true);
|
||||
}
|
||||
}
|
||||
@ -181,8 +181,8 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
|
||||
// Init: Explicitly loaded scripts
|
||||
for (i = 1; i < sm->heap_size; i++)
|
||||
if (interfaces[i]
|
||||
&& interfaces[i]->type_id == MEM_OBJ_SCRIPT) {
|
||||
script_t *script = &(interfaces[i]->mobj->data.script);
|
||||
&& interfaces[i]->getType() == MEM_OBJ_SCRIPT) {
|
||||
script_t *script = &(interfaces[i]->getMobj()->data.script);
|
||||
|
||||
if (script->lockers) { // Explicitly loaded?
|
||||
int obj_nr;
|
||||
@ -209,7 +209,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
|
||||
sciprintf("[GC] Checking "PREG"\n", PRINT_REG(reg));
|
||||
#endif
|
||||
if (reg.segment < sm->heap_size && interfaces[reg.segment])
|
||||
interfaces[reg.segment]->list_all_outgoing_references(interfaces[reg.segment], s, reg,
|
||||
interfaces[reg.segment]->listAllOutgoingReferences(s, reg,
|
||||
&worklist_manager, add_outgoing_refs);
|
||||
}
|
||||
}
|
||||
@ -220,7 +220,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
|
||||
// Cleanup
|
||||
for (i = 1; i < sm->heap_size; i++)
|
||||
if (interfaces[i])
|
||||
interfaces[i]->deallocate_self(interfaces[i]);
|
||||
delete interfaces[i];
|
||||
|
||||
free(interfaces);
|
||||
delete nonnormal_map;
|
||||
@ -243,7 +243,7 @@ void free_unless_used(void *pre_use_map, reg_t addr) {
|
||||
|
||||
if (!use_map->contains(addr)) {
|
||||
// Not found -> we can free it
|
||||
deallocator->interfce->free_at_address(deallocator->interfce, addr);
|
||||
deallocator->interfce->freeAtAddress(addr);
|
||||
#ifdef DEBUG_GC
|
||||
sciprintf("[GC] Deallocating "PREG"\n", PRINT_REG(addr));
|
||||
deallocator->segcount[deallocator->interfce->type_id]++;
|
||||
@ -271,8 +271,8 @@ void run_gc(EngineState *s) {
|
||||
#ifdef DEBUG_GC
|
||||
deallocator.segnames[deallocator.interfce->type_id] = deallocator.interfce->type;
|
||||
#endif
|
||||
deallocator.interfce->list_all_deallocatable(deallocator.interfce, &deallocator, free_unless_used);
|
||||
deallocator.interfce->deallocate_self(deallocator.interfce);
|
||||
deallocator.interfce->listAllDeallocatable(&deallocator, free_unless_used);
|
||||
delete deallocator.interfce;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2807,9 +2807,9 @@ static int c_gc_show_reachable(EngineState *s) {
|
||||
GET_SEG_INTERFACE(addr.segment);
|
||||
|
||||
sciprintf("Reachable from "PREG":\n", PRINT_REG(addr));
|
||||
seg_interface->list_all_outgoing_references(seg_interface, s, addr, NULL, _print_address);
|
||||
seg_interface->listAllOutgoingReferences(s, addr, NULL, _print_address);
|
||||
|
||||
seg_interface->deallocate_self(seg_interface);
|
||||
delete seg_interface;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2820,9 +2820,9 @@ static int c_gc_show_freeable(EngineState *s) {
|
||||
GET_SEG_INTERFACE(addr.segment);
|
||||
|
||||
sciprintf("Freeable in segment %04x:\n", addr.segment);
|
||||
seg_interface->list_all_deallocatable(seg_interface, NULL, _print_address);
|
||||
seg_interface->listAllDeallocatable(NULL, _print_address);
|
||||
|
||||
seg_interface->deallocate_self(seg_interface);
|
||||
delete seg_interface;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2832,10 +2832,10 @@ static int c_gc_normalise(EngineState *s) {
|
||||
|
||||
GET_SEG_INTERFACE(addr.segment);
|
||||
|
||||
addr = seg_interface->find_canonic_address(seg_interface, addr);
|
||||
addr = seg_interface->findCanonicAddress(addr);
|
||||
sciprintf(" "PREG"\n", PRINT_REG(addr));
|
||||
|
||||
seg_interface->deallocate_self(seg_interface);
|
||||
delete seg_interface;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1423,44 +1423,58 @@ void SegManager::dbgPrint(const char* msg, void *i) {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ------------------- Segment interface ------------------
|
||||
|
||||
static void free_at_address_stub(SegInterface *self, reg_t sub_addr) {
|
||||
//sciprintf(" Request to free "PREG"\n", PRINT_REG(sub_addr));
|
||||
// STUB
|
||||
SegInterface::SegInterface(SegManager *segmgr, mem_obj_t *mobj, seg_id_t segId, memObjType typeId) :
|
||||
_segmgr(segmgr), _mobj(mobj), _segId(segId), _typeId(typeId) {
|
||||
VERIFY(_mobj->type == _typeId, "Invalid mem_obj_t type");
|
||||
}
|
||||
|
||||
static reg_t find_canonic_address_base(SegInterface *self, reg_t addr) {
|
||||
reg_t SegInterface::findCanonicAddress(reg_t addr) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
void SegInterface::freeAtAddress(reg_t sub_addr) {
|
||||
}
|
||||
|
||||
void SegInterface::listAllDeallocatable(void *param, void (*note)(void *param, reg_t addr)) {
|
||||
}
|
||||
|
||||
void SegInterface::listAllOutgoingReferences(EngineState *s, reg_t object, void *param, void (*note)(void *param, reg_t addr)) {
|
||||
}
|
||||
|
||||
|
||||
//-------------------- base --------------------
|
||||
class SegInterfaceBase : public SegInterface {
|
||||
protected:
|
||||
SegInterfaceBase(SegManager *segmgr, mem_obj_t *mobj, seg_id_t segId, memObjType typeId) :
|
||||
SegInterface(segmgr, mobj, segId, typeId) {}
|
||||
public:
|
||||
reg_t findCanonicAddress(reg_t addr);
|
||||
void listAllDeallocatable(void *param, void (*note)(void *param, reg_t addr));
|
||||
};
|
||||
|
||||
reg_t SegInterfaceBase::findCanonicAddress(reg_t addr) {
|
||||
addr.offset = 0;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static reg_t find_canonic_address_id(SegInterface *self, reg_t addr) {
|
||||
return addr;
|
||||
void SegInterfaceBase::listAllDeallocatable(void *param, void (*note)(void *param, reg_t addr)) {
|
||||
(*note)(param, make_reg(_segId, 0));
|
||||
}
|
||||
|
||||
static void free_at_address_nop(SegInterface *self, reg_t sub_addr) {
|
||||
}
|
||||
|
||||
static void list_all_deallocatable_nop(SegInterface *self, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
}
|
||||
//-------------------- script --------------------
|
||||
class SegInterfaceScript : public SegInterfaceBase {
|
||||
public:
|
||||
SegInterfaceScript(SegManager *segmgr, mem_obj_t *mobj, seg_id_t segId) :
|
||||
SegInterfaceBase(segmgr, mobj, segId, MEM_OBJ_SCRIPT) {}
|
||||
void freeAtAddress(reg_t addr);
|
||||
void listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, void (*note)(void *param, reg_t addr));
|
||||
};
|
||||
|
||||
static void list_all_deallocatable_base(SegInterface *self, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
(*note)(param, make_reg(self->seg_id, 0));
|
||||
}
|
||||
|
||||
static void list_all_outgoing_references_nop(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
}
|
||||
|
||||
static void deallocate_self(SegInterface *self) {
|
||||
free(self);
|
||||
}
|
||||
|
||||
static void free_at_address_script(SegInterface *self, reg_t addr) {
|
||||
script_t *script;
|
||||
VERIFY(self->mobj->type == MEM_OBJ_SCRIPT, "Trying to free a non-script!");
|
||||
script = &(self->mobj->data.script);
|
||||
void SegInterfaceScript::freeAtAddress(reg_t addr) {
|
||||
script_t *script = &(_mobj->data.script);
|
||||
/*
|
||||
sciprintf("[GC] Freeing script "PREG"\n", PRINT_REG(addr));
|
||||
if (script->locals_segment)
|
||||
@ -1468,11 +1482,11 @@ static void free_at_address_script(SegInterface *self, reg_t addr) {
|
||||
*/
|
||||
|
||||
if (script->marked_as_deleted)
|
||||
self->segmgr->deallocateScript(script->nr);
|
||||
_segmgr->deallocateScript(script->nr);
|
||||
}
|
||||
|
||||
static void list_all_outgoing_references_script(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
script_t *script = &(self->mobj->data.script);
|
||||
void SegInterfaceScript::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, void (*note)(void *param, reg_t addr)) {
|
||||
script_t *script = &(_mobj->data.script);
|
||||
|
||||
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);
|
||||
@ -1495,41 +1509,36 @@ static void list_all_outgoing_references_script(SegInterface *self, EngineState
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------- script --------------------
|
||||
static SegInterface seg_interface_script = {
|
||||
/* segmgr = */ NULL,
|
||||
/* mobj = */ NULL,
|
||||
/* seg_id = */ 0,
|
||||
/* type_id = */ MEM_OBJ_SCRIPT,
|
||||
/* type = */ "script",
|
||||
/* find_canonic_address = */ find_canonic_address_base,
|
||||
/* free_at_address = */ free_at_address_script,
|
||||
/* list_all_deallocatable = */ list_all_deallocatable_base,
|
||||
/* list_all_outgoing_references = */ list_all_outgoing_references_script,
|
||||
/* deallocate_self = */ deallocate_self
|
||||
};
|
||||
|
||||
|
||||
#define LIST_ALL_DEALLOCATABLE(kind, kind_field) \
|
||||
mem_obj_t *mobj = self->mobj; \
|
||||
kind##_table_t * table = &(mobj->data.kind_field); \
|
||||
kind##_table_t * table = &(_mobj->data.kind_field); \
|
||||
int i; \
|
||||
\
|
||||
for (i = 0; i < table->max_entry; i++) \
|
||||
if (ENTRY_IS_VALID(table, i)) \
|
||||
(*note) (param, make_reg(self->seg_id, i));
|
||||
(*note) (param, make_reg(_segId, i));
|
||||
|
||||
static void list_all_deallocatable_clones(SegInterface *self, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
|
||||
//-------------------- clones --------------------
|
||||
class SegInterfaceClones : public SegInterface {
|
||||
public:
|
||||
SegInterfaceClones(SegManager *segmgr, mem_obj_t *mobj, seg_id_t segId) :
|
||||
SegInterface(segmgr, mobj, segId, MEM_OBJ_CLONES) {}
|
||||
void freeAtAddress(reg_t addr);
|
||||
void listAllDeallocatable(void *param, void (*note)(void *param, reg_t addr));
|
||||
void listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, void (*note)(void *param, reg_t addr));
|
||||
};
|
||||
|
||||
void SegInterfaceClones::listAllDeallocatable(void *param, void (*note)(void *param, reg_t addr)) {
|
||||
LIST_ALL_DEALLOCATABLE(clone, clones);
|
||||
}
|
||||
|
||||
static void list_all_outgoing_references_clones(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
mem_obj_t *mobj = self->mobj;
|
||||
clone_table_t *clone_table = &(mobj->data.clones);
|
||||
void SegInterfaceClones::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, void (*note)(void *param, reg_t addr)) {
|
||||
clone_table_t *clone_table = &(_mobj->data.clones);
|
||||
clone_t *clone;
|
||||
int i;
|
||||
|
||||
assert(addr.segment == self->seg_id);
|
||||
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));
|
||||
@ -1548,12 +1557,12 @@ static void list_all_outgoing_references_clones(SegInterface *self, EngineState
|
||||
//sciprintf("[GC] Reporting clone-pos "PREG"\n", PRINT_REG(clone->pos));
|
||||
}
|
||||
|
||||
void free_at_address_clones(SegInterface *self, reg_t addr) {
|
||||
void SegInterfaceClones::freeAtAddress(reg_t addr) {
|
||||
object_t *victim_obj;
|
||||
|
||||
assert(addr.segment == self->seg_id);
|
||||
assert(addr.segment == _segId);
|
||||
|
||||
victim_obj = &(self->mobj->data.clones.table[addr.offset].entry);
|
||||
victim_obj = &(_mobj->data.clones.table[addr.offset].entry);
|
||||
|
||||
#ifdef GC_DEBUG
|
||||
if (!(victim_obj->flags & OBJECT_FLAG_FREED))
|
||||
@ -1569,100 +1578,97 @@ void free_at_address_clones(SegInterface *self, reg_t addr) {
|
||||
*/
|
||||
free(victim_obj->variables);
|
||||
victim_obj->variables = NULL;
|
||||
self->segmgr->free_clone(addr);
|
||||
_segmgr->free_clone(addr);
|
||||
}
|
||||
|
||||
//-------------------- clones --------------------
|
||||
static SegInterface seg_interface_clones = {
|
||||
/* segmgr = */ NULL,
|
||||
/* mobj = */ NULL,
|
||||
/* seg_id = */ 0,
|
||||
/* type_id = */ MEM_OBJ_CLONES,
|
||||
/* type = */ "clones",
|
||||
/* find_canonic_address = */ find_canonic_address_id,
|
||||
/* free_at_address = */ free_at_address_clones,
|
||||
/* list_all_deallocatable = */ list_all_deallocatable_clones,
|
||||
/* list_all_outgoing_references = */ list_all_outgoing_references_clones,
|
||||
/* deallocate_self = */ deallocate_self
|
||||
|
||||
//-------------------- locals --------------------
|
||||
class SegInterfaceLocals : public SegInterface {
|
||||
public:
|
||||
SegInterfaceLocals(SegManager *segmgr, mem_obj_t *mobj, seg_id_t segId) :
|
||||
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, void (*note)(void *param, reg_t addr));
|
||||
};
|
||||
|
||||
static reg_t find_canonic_address_locals(SegInterface *self, reg_t addr) {
|
||||
local_variables_t *locals = &(self->mobj->data.locals);
|
||||
reg_t SegInterfaceLocals::findCanonicAddress(reg_t addr) {
|
||||
local_variables_t *locals = &(_mobj->data.locals);
|
||||
// Reference the owning script
|
||||
seg_id_t owner_seg = self->segmgr->segGet(locals->script_id);
|
||||
seg_id_t owner_seg = _segmgr->segGet(locals->script_id);
|
||||
|
||||
assert(owner_seg >= 0);
|
||||
|
||||
return make_reg(owner_seg, 0);
|
||||
}
|
||||
|
||||
static void list_all_outgoing_references_locals(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
local_variables_t *locals = &(self->mobj->data.locals);
|
||||
void SegInterfaceLocals::freeAtAddress(reg_t sub_addr) {
|
||||
//sciprintf(" Request to free "PREG"\n", PRINT_REG(sub_addr));
|
||||
// STUB
|
||||
}
|
||||
|
||||
void SegInterfaceLocals::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
local_variables_t *locals = &(_mobj->data.locals);
|
||||
int i;
|
||||
|
||||
assert(addr.segment == self->seg_id);
|
||||
assert(addr.segment == _segId);
|
||||
|
||||
for (i = 0; i < locals->nr; i++)
|
||||
(*note)(param, locals->locals[i]);
|
||||
}
|
||||
|
||||
//-------------------- locals --------------------
|
||||
static SegInterface seg_interface_locals = {
|
||||
/* segmgr = */ NULL,
|
||||
/* mobj = */ NULL,
|
||||
/* seg_id = */ 0,
|
||||
/* type_id = */ MEM_OBJ_LOCALS,
|
||||
/* type = */ "locals",
|
||||
/* find_canonic_address = */ find_canonic_address_locals,
|
||||
/* free_at_address = */ free_at_address_stub,
|
||||
/* list_all_deallocatable = */ list_all_deallocatable_nop,
|
||||
/* list_all_outgoing_references = */ list_all_outgoing_references_locals,
|
||||
/* deallocate_self = */ deallocate_self
|
||||
|
||||
//-------------------- stack --------------------
|
||||
class SegInterfaceStack : public SegInterface {
|
||||
public:
|
||||
SegInterfaceStack(SegManager *segmgr, mem_obj_t *mobj, seg_id_t segId) :
|
||||
SegInterface(segmgr, mobj, segId, MEM_OBJ_STACK) {}
|
||||
reg_t findCanonicAddress(reg_t addr);
|
||||
void listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, void (*note)(void *param, reg_t addr));
|
||||
};
|
||||
|
||||
static void list_all_outgoing_references_stack(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
reg_t SegInterfaceStack::findCanonicAddress(reg_t addr) {
|
||||
addr.offset = 0;
|
||||
return addr;
|
||||
}
|
||||
|
||||
void SegInterfaceStack::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
int i;
|
||||
fprintf(stderr, "Emitting %d stack entries\n", self->mobj->data.stack.nr);
|
||||
for (i = 0; i < self->mobj->data.stack.nr; i++)
|
||||
(*note)(param, self->mobj->data.stack.entries[i]);
|
||||
fprintf(stderr, "Emitting %d stack entries\n", _mobj->data.stack.nr);
|
||||
for (i = 0; i < _mobj->data.stack.nr; i++)
|
||||
(*note)(param, _mobj->data.stack.entries[i]);
|
||||
fprintf(stderr, "DONE");
|
||||
}
|
||||
|
||||
//-------------------- stack --------------------
|
||||
|
||||
static SegInterface seg_interface_stack = {
|
||||
/* segmgr = */ NULL,
|
||||
/* mobj = */ NULL,
|
||||
/* seg_id = */ 0,
|
||||
/* type_id = */ MEM_OBJ_STACK,
|
||||
/* type = */ "stack",
|
||||
/* find_canonic_address = */ find_canonic_address_base,
|
||||
/* free_at_address = */ free_at_address_nop,
|
||||
/* list_all_deallocatable = */ list_all_deallocatable_nop,
|
||||
/* list_all_outgoing_references = */ list_all_outgoing_references_stack,
|
||||
/* deallocate_self = */ deallocate_self
|
||||
};
|
||||
|
||||
//-------------------- system strings --------------------
|
||||
static SegInterface seg_interface_sys_strings = {
|
||||
/* segmgr = */ NULL,
|
||||
/* mobj = */ NULL,
|
||||
/* seg_id = */ 0,
|
||||
/* type_id = */ MEM_OBJ_SYS_STRINGS,
|
||||
/* type = */ "system strings",
|
||||
/* find_canonic_address = */ find_canonic_address_id,
|
||||
/* free_at_address = */ free_at_address_nop,
|
||||
/* list_all_deallocatable = */ list_all_deallocatable_nop,
|
||||
/* list_all_outgoing_references = */ list_all_outgoing_references_nop,
|
||||
/* deallocate_self = */ deallocate_self
|
||||
class SegInterfaceSysStrings : public SegInterface {
|
||||
public:
|
||||
SegInterfaceSysStrings(SegManager *segmgr, mem_obj_t *mobj, seg_id_t segId) :
|
||||
SegInterface(segmgr, mobj, segId, MEM_OBJ_SYS_STRINGS) {}
|
||||
};
|
||||
|
||||
static void list_all_deallocatable_list(SegInterface *self, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
|
||||
//-------------------- lists --------------------
|
||||
class SegInterfaceLists : public SegInterface {
|
||||
public:
|
||||
SegInterfaceLists(SegManager *segmgr, mem_obj_t *mobj, seg_id_t segId) :
|
||||
SegInterface(segmgr, mobj, segId, MEM_OBJ_LISTS) {}
|
||||
void freeAtAddress(reg_t addr);
|
||||
void listAllDeallocatable(void *param, void (*note)(void *param, reg_t addr));
|
||||
void listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, void (*note)(void *param, reg_t addr));
|
||||
};
|
||||
|
||||
void SegInterfaceLists::freeAtAddress(reg_t sub_addr) {
|
||||
_segmgr->free_list(sub_addr);
|
||||
}
|
||||
|
||||
void SegInterfaceLists::listAllDeallocatable(void *param, void (*note)(void*param, reg_t addr)) {
|
||||
LIST_ALL_DEALLOCATABLE(list, lists);
|
||||
}
|
||||
|
||||
static void list_all_outgoing_references_list(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
list_table_t *table = &(self->mobj->data.lists);
|
||||
void SegInterfaceLists::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
list_table_t *table = &(_mobj->data.lists);
|
||||
list_t *list = &(table->table[addr.offset].entry);
|
||||
|
||||
if (!ENTRY_IS_VALID(table, addr.offset)) {
|
||||
@ -1676,30 +1682,27 @@ static void list_all_outgoing_references_list(SegInterface *self, EngineState *s
|
||||
// let's be conservative here.
|
||||
}
|
||||
|
||||
static void free_at_address_lists(SegInterface *self, reg_t sub_addr) {
|
||||
self->segmgr->free_list(sub_addr);
|
||||
}
|
||||
|
||||
//-------------------- lists --------------------
|
||||
static SegInterface seg_interface_lists = {
|
||||
/* segmgr = */ NULL,
|
||||
/* mobj = */ NULL,
|
||||
/* seg_id = */ 0,
|
||||
/* type_id = */ MEM_OBJ_LISTS,
|
||||
/* type = */ "lists",
|
||||
/* find_canonic_address = */ find_canonic_address_id,
|
||||
/* free_at_address = */ free_at_address_lists,
|
||||
/* list_all_deallocatable = */ list_all_deallocatable_list,
|
||||
/* list_all_outgoing_references = */ list_all_outgoing_references_list,
|
||||
/* deallocate_self = */ deallocate_self
|
||||
//-------------------- nodes --------------------
|
||||
class SegInterfaceNodes : public SegInterface {
|
||||
public:
|
||||
SegInterfaceNodes(SegManager *segmgr, mem_obj_t *mobj, seg_id_t segId) :
|
||||
SegInterface(segmgr, mobj, segId, MEM_OBJ_NODES) {}
|
||||
void freeAtAddress(reg_t addr);
|
||||
void listAllDeallocatable(void *param, void (*note)(void *param, reg_t addr));
|
||||
void listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, void (*note)(void *param, reg_t addr));
|
||||
};
|
||||
|
||||
static void list_all_deallocatable_nodes(SegInterface *self, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
void SegInterfaceNodes::freeAtAddress(reg_t sub_addr) {
|
||||
_segmgr->free_node(sub_addr);
|
||||
}
|
||||
|
||||
void SegInterfaceNodes::listAllDeallocatable(void *param, void (*note)(void*param, reg_t addr)) {
|
||||
LIST_ALL_DEALLOCATABLE(node, nodes);
|
||||
}
|
||||
|
||||
static void list_all_outgoing_references_nodes(SegInterface *self, EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
node_table_t *table = &(self->mobj->data.nodes);
|
||||
void SegInterfaceNodes::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
node_table_t *table = &(_mobj->data.nodes);
|
||||
node_t *node = &(table->table[addr.offset].entry);
|
||||
|
||||
if (!ENTRY_IS_VALID(table, addr.offset)) {
|
||||
@ -1715,102 +1718,89 @@ static void list_all_outgoing_references_nodes(SegInterface *self, EngineState *
|
||||
note(param, node->value);
|
||||
}
|
||||
|
||||
static void free_at_address_nodes(SegInterface *self, reg_t sub_addr) {
|
||||
self->segmgr->free_node(sub_addr);
|
||||
}
|
||||
|
||||
//-------------------- nodes --------------------
|
||||
static SegInterface seg_interface_nodes = {
|
||||
/* segmgr = */ NULL,
|
||||
/* mobj = */ NULL,
|
||||
/* seg_id = */ 0,
|
||||
/* type_id = */ MEM_OBJ_NODES,
|
||||
/* type = */ "nodes",
|
||||
/* find_canonic_address = */ find_canonic_address_id,
|
||||
/* free_at_address = */ free_at_address_nodes,
|
||||
/* list_all_deallocatable = */ list_all_deallocatable_nodes,
|
||||
/* list_all_outgoing_references = */ list_all_outgoing_references_nodes,
|
||||
/* deallocate_self = */ deallocate_self
|
||||
//-------------------- hunk --------------------
|
||||
class SegInterfaceHunk : public SegInterface {
|
||||
public:
|
||||
SegInterfaceHunk(SegManager *segmgr, mem_obj_t *mobj, seg_id_t segId) :
|
||||
SegInterface(segmgr, mobj, segId, MEM_OBJ_HUNK) {}
|
||||
void freeAtAddress(reg_t addr);
|
||||
void listAllDeallocatable(void *param, void (*note)(void *param, reg_t addr));
|
||||
};
|
||||
|
||||
static void list_all_deallocatable_hunk(SegInterface *self, void *param, void (*note)(void*param, reg_t addr)) {
|
||||
void SegInterfaceHunk::freeAtAddress(reg_t sub_addr) {
|
||||
//sciprintf(" Request to free "PREG"\n", PRINT_REG(sub_addr));
|
||||
// STUB
|
||||
}
|
||||
|
||||
void SegInterfaceHunk::listAllDeallocatable(void *param, void (*note)(void*param, reg_t addr)) {
|
||||
LIST_ALL_DEALLOCATABLE(hunk, hunks);
|
||||
}
|
||||
|
||||
//-------------------- hunk --------------------
|
||||
static SegInterface seg_interface_hunk = {
|
||||
/* segmgr = */ NULL,
|
||||
/* mobj = */ NULL,
|
||||
/* seg_id = */ 0,
|
||||
/* type_id = */ MEM_OBJ_HUNK,
|
||||
/* type = */ "hunk",
|
||||
/* find_canonic_address = */ find_canonic_address_id,
|
||||
/* free_at_address = */ free_at_address_stub,
|
||||
/* list_all_deallocatable = */ list_all_deallocatable_hunk,
|
||||
/* list_all_outgoing_references = */ list_all_outgoing_references_nop,
|
||||
/* deallocate_self = */ deallocate_self
|
||||
};
|
||||
|
||||
//-------------------- dynamic memory --------------------
|
||||
static SegInterface seg_interface_dynmem = {
|
||||
/* segmgr = */ NULL,
|
||||
/* mobj = */ NULL,
|
||||
/* seg_id = */ 0,
|
||||
/* type_id = */ MEM_OBJ_DYNMEM,
|
||||
/* type = */ "dynamic memory",
|
||||
/* find_canonic_address = */ find_canonic_address_base,
|
||||
/* free_at_address = */ free_at_address_stub,
|
||||
/* list_all_deallocatable = */ list_all_deallocatable_base,
|
||||
/* list_all_outgoing_references = */ list_all_outgoing_references_nop,
|
||||
/* deallocate_self = */ deallocate_self
|
||||
class SegInterfaceDynMem : public SegInterfaceBase {
|
||||
public:
|
||||
SegInterfaceDynMem(SegManager *segmgr, mem_obj_t *mobj, seg_id_t segId) :
|
||||
SegInterfaceBase(segmgr, mobj, segId, MEM_OBJ_DYNMEM) {}
|
||||
void freeAtAddress(reg_t addr);
|
||||
};
|
||||
|
||||
void SegInterfaceDynMem::freeAtAddress(reg_t sub_addr) {
|
||||
//sciprintf(" Request to free "PREG"\n", PRINT_REG(sub_addr));
|
||||
// STUB
|
||||
}
|
||||
|
||||
|
||||
//-------------------- reserved --------------------
|
||||
static SegInterface seg_interface_reserved = {
|
||||
/* segmgr = */ NULL,
|
||||
/* mobj = */ NULL,
|
||||
/* seg_id = */ 0,
|
||||
/* type_id = */ MEM_OBJ_RESERVED,
|
||||
/* type = */ "reserved",
|
||||
/* find_canonic_address = */ find_canonic_address_id,
|
||||
/* free_at_address = */ free_at_address_nop,
|
||||
/* list_all_deallocatable = */ list_all_deallocatable_nop,
|
||||
/* list_all_outgoing_references = */ list_all_outgoing_references_nop,
|
||||
/* deallocate_self = */ deallocate_self
|
||||
class SegInterfaceReserved : public SegInterface {
|
||||
public:
|
||||
SegInterfaceReserved(SegManager *segmgr, mem_obj_t *mobj, seg_id_t segId) :
|
||||
SegInterface(segmgr, mobj, segId, MEM_OBJ_RESERVED) {}
|
||||
};
|
||||
|
||||
static SegInterface* seg_interfaces[MEM_OBJ_MAX] = {
|
||||
&seg_interface_script,
|
||||
&seg_interface_clones,
|
||||
&seg_interface_locals,
|
||||
&seg_interface_stack,
|
||||
&seg_interface_sys_strings,
|
||||
&seg_interface_lists,
|
||||
&seg_interface_nodes,
|
||||
&seg_interface_hunk,
|
||||
&seg_interface_dynmem,
|
||||
&seg_interface_reserved
|
||||
};
|
||||
|
||||
SegInterface *SegManager::getSegInterface(seg_id_t segid) {
|
||||
mem_obj_t *mobj;
|
||||
SegInterface *retval;
|
||||
|
||||
if (!check(segid))
|
||||
return NULL; // Invalid segment
|
||||
|
||||
mobj = heap[segid];
|
||||
retval = (SegInterface *)sci_malloc(sizeof(SegInterface));
|
||||
memcpy(retval, seg_interfaces[mobj->type - 1], sizeof(SegInterface));
|
||||
|
||||
if (mobj->type != retval->type_id) {
|
||||
SegInterface *retval = NULL;
|
||||
mem_obj_t *mobj = heap[segid];
|
||||
switch (mobj->type) {
|
||||
case MEM_OBJ_SCRIPT:
|
||||
retval = new SegInterfaceScript(this, mobj, segid);
|
||||
break;
|
||||
case MEM_OBJ_CLONES:
|
||||
retval = new SegInterfaceClones(this, mobj, segid);
|
||||
break;
|
||||
case MEM_OBJ_LOCALS:
|
||||
retval = new SegInterfaceLocals(this, mobj, segid);
|
||||
break;
|
||||
case MEM_OBJ_STACK:
|
||||
retval = new SegInterfaceStack(this, mobj, segid);
|
||||
break;
|
||||
case MEM_OBJ_SYS_STRINGS:
|
||||
retval = new SegInterfaceSysStrings(this, mobj, segid);
|
||||
break;
|
||||
case MEM_OBJ_LISTS:
|
||||
retval = new SegInterfaceLists(this, mobj, segid);
|
||||
break;
|
||||
case MEM_OBJ_NODES:
|
||||
retval = new SegInterfaceNodes(this, mobj, segid);
|
||||
break;
|
||||
case MEM_OBJ_HUNK:
|
||||
retval = new SegInterfaceHunk(this, mobj, segid);
|
||||
break;
|
||||
case MEM_OBJ_DYNMEM:
|
||||
retval = new SegInterfaceDynMem(this, mobj, segid);
|
||||
break;
|
||||
case MEM_OBJ_RESERVED:
|
||||
retval = new SegInterfaceReserved(this, mobj, segid);
|
||||
break;
|
||||
default:
|
||||
error("Improper segment interface for %d", mobj->type);
|
||||
}
|
||||
|
||||
retval->segmgr = this;
|
||||
retval->mobj = mobj;
|
||||
retval->seg_id = segid;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ enum idFlag {
|
||||
(((mgr).heap[index] && ((mgr).heap[index]->type == MEM_OBJ_SCRIPT || (mgr).heap[index]->type == MEM_OBJ_CLONES))? (mgr).heap[index] \
|
||||
: NULL): NULL
|
||||
|
||||
struct SegInterface;
|
||||
class SegInterface;
|
||||
|
||||
class SegManager {
|
||||
public:
|
||||
@ -340,6 +340,7 @@ public:
|
||||
// Parameters: (reg_t) addr: Offset of the hunk entry to delete
|
||||
void free_hunk_entry(reg_t addr);
|
||||
|
||||
|
||||
// 9. Dynamic Memory
|
||||
|
||||
// Allocate some dynamic memory
|
||||
@ -385,7 +386,7 @@ public:
|
||||
// Retrieves the segment interface to the specified segment
|
||||
// Parameters: (seg_id_t) segid: ID of the segment to look up
|
||||
// Returns : (SegInterface *): An interface to the specified segment ID, or NULL on error
|
||||
// The returned interface 'si' must be freed after use by calling 'si->dealloc_self(si)';
|
||||
// The returned interface must be deleted after use
|
||||
SegInterface *getSegInterface(seg_id_t segid);
|
||||
|
||||
|
||||
@ -450,38 +451,50 @@ private:
|
||||
|
||||
// 11. Segment interface, primarily for GC
|
||||
|
||||
struct SegInterface {
|
||||
SegManager *segmgr;
|
||||
mem_obj_t *mobj;
|
||||
seg_id_t seg_id;
|
||||
memObjType type_id; // Segment type
|
||||
const char *type; // String description of the segment type
|
||||
class SegInterface {
|
||||
protected:
|
||||
SegInterface(SegManager *segmgr, mem_obj_t *mobj, seg_id_t segId, memObjType typeId);
|
||||
|
||||
public:
|
||||
// Deallocates the segment interface
|
||||
virtual ~SegInterface() {}
|
||||
|
||||
reg_t (*find_canonic_address)(SegInterface *self, reg_t sub_addr);
|
||||
// Finds the canonic address associated with sub_reg
|
||||
// Parameters: (reg_t) sub_addr: The base address whose canonic address is to be found
|
||||
// For each valid address a, there exists a canonic address c(a) such that c(a) = c(c(a)).
|
||||
// This address "governs" a in the sense that deallocating c(a) will deallocate a.
|
||||
virtual reg_t findCanonicAddress(reg_t sub_addr);
|
||||
|
||||
void (*free_at_address)(SegInterface *self, reg_t sub_addr);
|
||||
// Deallocates all memory associated with the specified address
|
||||
// Parameters: (reg_t) sub_addr: The address (within the given segment) to deallocate
|
||||
|
||||
void (*list_all_deallocatable)(SegInterface *self, void *param, void (*note)(void *param, reg_t addr));
|
||||
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, void (*note)(void *param, reg_t addr));
|
||||
|
||||
void (*list_all_outgoing_references)(SegInterface *self, EngineState *s, reg_t object, void *param, void (*note)(void *param, reg_t addr));
|
||||
// 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
|
||||
|
||||
void (*deallocate_self)(SegInterface *self);
|
||||
// Deallocates the segment interface
|
||||
virtual void listAllOutgoingReferences(EngineState *s, reg_t object, void *param, void (*note)(void *param, reg_t addr));
|
||||
|
||||
// Get the memory object
|
||||
mem_obj_t *getMobj() { return _mobj; }
|
||||
|
||||
// Get the segment type
|
||||
memObjType getType() { return _typeId; }
|
||||
|
||||
protected:
|
||||
SegManager *_segmgr;
|
||||
mem_obj_t *_mobj;
|
||||
seg_id_t _segId;
|
||||
|
||||
private:
|
||||
memObjType _typeId; // Segment type
|
||||
};
|
||||
|
||||
} // End of namespace Sci
|
||||
|
Loading…
Reference in New Issue
Block a user