SCI: Converted "segment interfaces" into classes

svn-id: r38782
This commit is contained in:
Jordi Vilalta Prat 2009-02-22 12:18:22 +00:00
parent 7d21acd18b
commit ac409a2ab7
4 changed files with 245 additions and 242 deletions

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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