SCI: Changed object list in Script instances to use Common:::Array

svn-id: r40431
This commit is contained in:
Max Horn 2009-05-10 19:17:51 +00:00
parent 36818ced2a
commit 019f87fd1b
9 changed files with 82 additions and 134 deletions

View File

@ -118,15 +118,12 @@ reg_t_hash_map *find_all_used_references(EngineState *s) {
Script *script = (Script *)sm->_heap[i];
if (script->lockers) { // Explicitly loaded?
int obj_nr;
// Locals, if present
wm.push(make_reg(script->locals_segment, 0));
// All objects (may be classes, may be indirectly reachable)
for (obj_nr = 0; obj_nr < script->objects_nr; obj_nr++) {
Object *obj = script->objects + obj_nr;
wm.push(obj->pos);
for (uint obj_nr = 0; obj_nr < script->_objects.size(); obj_nr++) {
wm.push(script->_objects[obj_nr].pos);
}
}
}

View File

@ -673,7 +673,7 @@ int determine_reg_type(EngineState *s, reg_t reg, int allow_invalid) {
if (reg.offset <= (*(Script *)mobj).buf_size && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET
&& RAW_IS_OBJECT((*(Script *)mobj).buf + reg.offset)) {
int idx = RAW_GET_CLASS_INDEX((Script *)mobj, reg);
if (idx >= 0 && idx < (*(Script *)mobj).objects_nr)
if (idx >= 0 && (uint)idx < (*(Script *)mobj)._objects.size())
return KSIG_OBJECT;
else
return KSIG_REF;

View File

@ -277,7 +277,8 @@ static void sync_LocalVariables(Common::Serializer &s, LocalVariables &obj) {
sync_reg_t(s, obj.locals[i]);
}
static void sync_Object(Common::Serializer &s, Object &obj) {
template <>
void syncWithSerializer(Common::Serializer &s, Object &obj) {
s.syncAsSint32LE(obj.flags);
sync_reg_t(s, obj.pos);
s.syncAsSint32LE(obj.variables_nr);
@ -290,11 +291,6 @@ static void sync_Object(Common::Serializer &s, Object &obj) {
sync_reg_t(s, obj.variables[i]);
}
template <>
void syncWithSerializer(Common::Serializer &s, Clone &obj) {
sync_Object(s, obj);
}
template <>
void syncWithSerializer(Common::Serializer &s, List &obj) {
sync_reg_t(s, obj.first);
@ -341,13 +337,22 @@ static void sync_Script(Common::Serializer &s, Script &obj) {
s.syncAsSint32LE(obj.exports_nr);
s.syncAsSint32LE(obj.synonyms_nr);
s.syncAsSint32LE(obj.lockers);
s.syncAsSint32LE(obj.objects_allocated);
s.syncAsSint32LE(obj.objects_nr);
if (!obj.objects && obj.objects_allocated)
obj.objects = (Object *)sci_calloc(obj.objects_allocated, sizeof(Object));
for (int i = 0; i < obj.objects_allocated; ++i)
sync_Object(s, obj.objects[i]);
#if 1
uint len = obj._objects.size();
s.syncAsUint32LE(len); // Used to be obj.objects_allocated
s.skip(4); // Used to be obj.objects_nr
// Resize the array if loading.
if (s.isLoading())
obj._objects.resize(len);
Common::Array<Object>::iterator i;
for (i = obj._objects.begin(); i != obj._objects.end(); ++i) {
syncWithSerializer<Object>(s, *i);
}
#else
s.skip(4); // Used to be obj.objects_allocated
syncArray<Object>(s, obj._objects);
#endif
s.syncAsSint32LE(obj.locals_offset);
s.syncAsSint32LE(obj.locals_segment);
@ -585,14 +590,13 @@ static void load_script(EngineState *s, SegmentId seg) {
// FIXME: The following should likely become a SegManager method
static void reconstruct_scripts(EngineState *s, SegManager *self) {
uint i;
uint i, j;
MemObject *mobj;
for (i = 0; i < self->_heap.size(); i++) {
if (self->_heap[i]) {
mobj = self->_heap[i];
switch (mobj->getType()) {
case MEM_OBJ_SCRIPT: {
int j;
Script *scr = (Script *)mobj;
load_script(s, i);
@ -606,10 +610,10 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) {
if (!self->isSci1_1)
scr->export_table += 3;
for (j = 0; j < scr->objects_nr; j++) {
byte *data = scr->buf + scr->objects[j].pos.offset;
scr->objects[j].base = scr->buf;
scr->objects[j].base_obj = data;
for (j = 0; j < scr->_objects.size(); j++) {
byte *data = scr->buf + scr->_objects[j].pos.offset;
scr->_objects[j].base = scr->buf;
scr->_objects[j].base_obj = data;
}
break;
}
@ -624,34 +628,33 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) {
mobj = self->_heap[i];
switch (mobj->getType()) {
case MEM_OBJ_SCRIPT: {
int j;
Script *scr = (Script *)mobj;
for (j = 0; j < scr->objects_nr; j++) {
byte *data = scr->buf + scr->objects[j].pos.offset;
for (j = 0; j < scr->_objects.size(); j++) {
byte *data = scr->buf + scr->_objects[j].pos.offset;
if (self->isSci1_1) {
uint16 *funct_area = (uint16 *) (scr->buf + READ_LE_UINT16( data + 6 ));
uint16 *prop_area = (uint16 *) (scr->buf + READ_LE_UINT16( data + 4 ));
scr->objects[j].base_method = funct_area;
scr->objects[j].base_vars = prop_area;
scr->_objects[j].base_method = funct_area;
scr->_objects[j].base_vars = prop_area;
} else {
int funct_area = READ_LE_UINT16( data + SCRIPT_FUNCTAREAPTR_OFFSET );
Object *base_obj;
base_obj = obj_get(s, scr->objects[j].variables[SCRIPT_SPECIES_SELECTOR]);
base_obj = obj_get(s, scr->_objects[j].variables[SCRIPT_SPECIES_SELECTOR]);
if (!base_obj) {
sciprintf("Object without a base class: Script %d, index %d (reg address "PREG"\n",
scr->nr, j, PRINT_REG(scr->objects[j].variables[SCRIPT_SPECIES_SELECTOR]));
scr->nr, j, PRINT_REG(scr->_objects[j].variables[SCRIPT_SPECIES_SELECTOR]));
continue;
}
scr->objects[j].variable_names_nr = base_obj->variables_nr;
scr->objects[j].base_obj = base_obj->base_obj;
scr->_objects[j].variable_names_nr = base_obj->variables_nr;
scr->_objects[j].base_obj = base_obj->base_obj;
scr->objects[j].base_method = (uint16 *) (data + funct_area);
scr->objects[j].base_vars = (uint16 *) (data + scr->objects[j].variable_names_nr * 2 + SCRIPT_SELECTOR_OFFSET);
scr->_objects[j].base_method = (uint16 *)(data + funct_area);
scr->_objects[j].base_vars = (uint16 *)(data + scr->_objects[j].variable_names_nr * 2 + SCRIPT_SELECTOR_OFFSET);
}
}
break;

View File

@ -312,7 +312,7 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on
if (mobj) {
if (mobj->getType() == MEM_OBJ_SCRIPT)
max_index = (*(Script *)mobj).objects_nr;
max_index = (*(Script *)mobj)._objects.size();
else if (mobj->getType() == MEM_OBJ_CLONES)
max_index = (*(CloneTable *)mobj).max_entry;
}
@ -325,7 +325,7 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on
objpos.segment = i;
if (mobj->getType() == MEM_OBJ_SCRIPT) {
obj = (*(Script *)mobj).objects + idx;
obj = &(*(Script *)mobj)._objects[idx];
objpos.offset = obj->pos.offset;
} else if (mobj->getType() == MEM_OBJ_CLONES) {
obj = &((*(CloneTable *)mobj).table[idx]);

View File

@ -388,7 +388,6 @@ static void _c_single_seg_info(EngineState *s, MemObject *mobj) {
switch (mobj->getType()) {
case MEM_OBJ_SCRIPT: {
int i;
Script *scr = (Script *)mobj;
sciprintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->nr, scr->lockers, (uint)scr->buf_size, (uint)scr->buf_size);
if (scr->export_table)
@ -403,10 +402,10 @@ static void _c_single_seg_info(EngineState *s, MemObject *mobj) {
else
sciprintf(" Locals : none\n");
sciprintf(" Objects: %4d\n", scr->objects_nr);
for (i = 0; i < scr->objects_nr; i++) {
sciprintf(" Objects: %4d\n", scr->_objects.size());
for (uint i = 0; i < scr->_objects.size(); i++) {
sciprintf(" ");
print_obj_head(s, scr->objects + i);
print_obj_head(s, &scr->_objects[i]);
}
}
break;

View File

@ -189,10 +189,6 @@ int SegManager::initialiseScript(Script &scr, EngineState *s, int script_nr) {
}
// Initialize objects
scr.objects = NULL;
scr.objects_allocated = 0;
scr.objects_nr = 0; // No objects recorded yet
scr.locals_offset = 0;
scr.locals_block = NULL;
@ -370,19 +366,10 @@ void Script::freeScript() {
buf = NULL;
buf_size = 0;
if (objects) {
for (int i = 0; i < objects_nr; i++) {
Object *object = &objects[i];
if (object->variables) {
free(object->variables);
object->variables = NULL;
object->variables_nr = 0;
}
}
free(objects);
objects = NULL;
objects_nr = 0;
for (uint i = 0; i < _objects.size(); i++) {
free(_objects[i].variables);
}
_objects.clear();
delete obj_indices;
obj_indices = 0;
@ -578,17 +565,18 @@ void SegManager::scriptRelocate(reg_t block) {
continue; // FIXME: A hack pending investigation
if (!relocateLocal(scr, block.segment, pos)) {
int k, done = 0;
bool done = false;
uint k;
for (k = 0; !done && k < scr->objects_nr; k++) {
if (relocateObject(scr->objects + k, block.segment, pos))
done = 1;
for (k = 0; !done && k < scr->_objects.size(); k++) {
if (relocateObject(&scr->_objects[k], block.segment, pos))
done = true;
}
for (k = 0; !done && k < scr->code_blocks_nr; k++) {
for (k = 0; !done && (int)k < scr->code_blocks_nr; k++) {
if (pos >= scr->code[k].pos.offset &&
pos < scr->code[k].pos.offset + scr->code[k].size)
done = 1;
done = true;
}
if (!done) {
@ -598,8 +586,8 @@ void SegManager::scriptRelocate(reg_t block) {
sciprintf("- locals: %d at %04x\n", scr->locals_block->nr, scr->locals_offset);
else
sciprintf("- No locals\n");
for (k = 0; k < scr->objects_nr; k++)
sciprintf("- obj#%d at %04x w/ %d vars\n", k, scr->objects[k].pos.offset, scr->objects[k].variables_nr);
for (k = 0; k < scr->_objects.size(); k++)
sciprintf("- obj#%d at %04x w/ %d vars\n", k, scr->_objects[k].pos.offset, scr->_objects[k].variables_nr);
// SQ3 script 71 has broken relocation entries.
// Since this is mainstream, we can't break out as we used to do.
sciprintf("Trying to continue anyway...\n");
@ -624,11 +612,12 @@ void SegManager::heapRelocate(EngineState *s, reg_t block) {
int pos = READ_LE_UINT16(scr->heap_start + block.offset + 2 + (i * 2)) + scr->script_size;
if (!relocateLocal(scr, block.segment, pos)) {
int k, done = 0;
bool done = false;
uint k;
for (k = 0; !done && k < scr->objects_nr; k++) {
if (relocateObject(scr->objects + k, block.segment, pos))
done = 1;
for (k = 0; !done && k < scr->_objects.size(); k++) {
if (relocateObject(&scr->_objects[k], block.segment, pos))
done = true;
}
if (!done) {
@ -638,8 +627,8 @@ void SegManager::heapRelocate(EngineState *s, reg_t block) {
sciprintf("- locals: %d at %04x\n", scr->locals_block->nr, scr->locals_offset);
else
sciprintf("- No locals\n");
for (k = 0; k < scr->objects_nr; k++)
sciprintf("- obj#%d at %04x w/ %d vars\n", k, scr->objects[k].pos.offset, scr->objects[k].variables_nr);
for (k = 0; k < scr->_objects.size(); k++)
sciprintf("- obj#%d at %04x w/ %d vars\n", k, scr->_objects[k].pos.offset, scr->_objects[k].variables_nr);
sciprintf("Triggering breakpoint...\n");
BREAKPOINT();
}
@ -661,20 +650,13 @@ Object *SegManager::scriptObjInit0(EngineState *s, reg_t obj_pos) {
VERIFY(base < scr->buf_size, "Attempt to initialize object beyond end of script\n");
if (!scr->objects) {
scr->objects_allocated = DEFAULT_OBJECTS;
scr->objects = (Object *)sci_malloc(sizeof(Object) * scr->objects_allocated);
}
if (scr->objects_nr == scr->objects_allocated) {
scr->objects_allocated += DEFAULT_OBJECTS_INCREMENT;
scr->objects = (Object *)sci_realloc(scr->objects, sizeof(Object) * scr->objects_allocated);
}
temp = make_reg(obj_pos.segment, base);
id = scr->obj_indices->checkKey(base, true);
scr->objects_nr++;
obj = scr->objects + id;
id = scr->obj_indices->checkKey(base, true);
if ((uint)id == scr->_objects.size())
scr->_objects.push_back(Object());
obj = &scr->_objects[id];
VERIFY(base + SCRIPT_FUNCTAREAPTR_OFFSET < scr->buf_size, "Function area pointer stored beyond end of script\n");
@ -724,19 +706,11 @@ Object *SegManager::scriptObjInit11(EngineState *s, reg_t obj_pos) {
VERIFY(base < (uint16)scr->buf_size, "Attempt to initialize object beyond end of script\n");
if (!scr->objects) {
scr->objects_allocated = DEFAULT_OBJECTS;
scr->objects = (Object *)sci_malloc(sizeof(Object) * scr->objects_allocated);
}
if (scr->objects_nr == scr->objects_allocated) {
scr->objects_allocated += DEFAULT_OBJECTS_INCREMENT;
scr->objects = (Object *)sci_realloc(scr->objects, sizeof(Object) * scr->objects_allocated);
}
id = scr->obj_indices->checkKey(obj_pos.offset, true);
scr->objects_nr++;
if ((uint)id == scr->_objects.size())
scr->_objects.push_back(Object());
obj = scr->objects + id;
obj = &scr->_objects[id];
VERIFY(base + SCRIPT_FUNCTAREAPTR_OFFSET < (uint16)scr->buf_size, "Function area pointer stored beyond end of script\n");
@ -912,20 +886,6 @@ void SegManager::scriptInitialiseObjectsSci11(EngineState *s, int seg) {
}
}
void SegManager::scriptFreeUnusedObjects(SegmentId seg) {
Script *scr = getScript(seg, SEG_ID);
if (scr->objects_allocated > scr->objects_nr) {
if (scr->objects_nr)
scr->objects = (Object *)sci_realloc(scr->objects, sizeof(Object) * scr->objects_nr);
else {
if (scr->objects_allocated)
free(scr->objects);
scr->objects = NULL;
}
scr->objects_allocated = scr->objects_nr;
}
}
/*
static char *SegManager::dynprintf(char *msg, ...) {
va_list argp;
@ -1208,18 +1168,16 @@ void Script::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param,
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);
if (idx >= 0 && idx < script->objects_nr) {
Object *obj = script->objects + idx;
int i;
if (idx >= 0 && (uint)idx < script->_objects.size()) {
// Note all local variables, if we have a local variable environment
if (script->locals_segment)
(*note)(param, make_reg(script->locals_segment, 0));
for (i = 0; i < obj->variables_nr; i++)
(*note)(param, obj->variables[i]);
Object &obj = script->_objects[idx];
for (int i = 0; i < obj.variables_nr; i++)
(*note)(param, obj.variables[i]);
} else {
fprintf(stderr, "Request for outgoing script-object reference at "PREG" yielded invalid index %d\n", PRINT_REG(addr), idx);
warning("Request for outgoing script-object reference at "PREG" yielded invalid index %d", PRINT_REG(addr), idx);
}
} else {
/* fprintf(stderr, "Unexpected request for outgoing script-object references at "PREG"\n", PRINT_REG(addr));*/

View File

@ -186,12 +186,6 @@ public:
// objects have been instantiated, or a run-time error will occur.
void scriptRelocate(reg_t block);
// Deallocates all unused but allocated entries for objects
// Parameters: (SegmentId) segid: segment of the script to prune in this way
// These entries are created during script instantiation; deallocating them
// frees up some additional memory.
void scriptFreeUnusedObjects(SegmentId segid);
// Sets the script-relative offset of the exports table
// Parameters: (int) offset: The script-relative exports table offset
// (int) id: ID of the script or script segment to write to

View File

@ -1876,8 +1876,6 @@ int script_instantiate_sci0(EngineState *s, int script_nr) {
if (relocation >= 0)
s->seg_manager->scriptRelocate(make_reg(reg.segment, relocation));
s->seg_manager->scriptFreeUnusedObjects(reg.segment);
return reg.segment; // instantiation successful
}
@ -2094,8 +2092,8 @@ Object *obj_get(EngineState *s, reg_t offset) {
if (offset.offset <= (*(Script *)memobj).buf_size && offset.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET
&& RAW_IS_OBJECT((*(Script *)memobj).buf + offset.offset)) {
idx = RAW_GET_CLASS_INDEX((Script *)memobj, offset);
if (idx >= 0 && idx < (*(Script *)memobj).objects_nr)
obj = (*(Script *)memobj).objects + idx;
if (idx >= 0 && (uint)idx < (*(Script *)memobj)._objects.size())
obj = &(*(Script *)memobj)._objects[idx];
}
}
}

View File

@ -277,6 +277,8 @@ struct Object {
uint16 *base_method; /**< Pointer to the method selector area for this object */
uint16 *base_vars; /**< Pointer to the varselector area for this object */
reg_t *variables;
Object() { memset(this, 0, sizeof(*this)); }
};
struct CodeBlock {
@ -323,11 +325,12 @@ struct Script : public MemObject {
int synonyms_nr; /**< Number of entries in the synonyms block */
int lockers; /**< Number of classes and objects that require this script */
Object *objects; /**< Table for objects, contains property variables */
/* Indexed by the value stored at SCRIPT_LOCALVARPTR_OFFSET,
** see VM_OBJECT_[GS]ET_INDEX() */
int objects_nr; /**< Number of objects and classes */
int objects_allocated; /**< Number of allocated objects */
/**
* Table for objects, contains property variables.
* Indexed by the value stored at SCRIPT_LOCALVARPTR_OFFSET,
* see VM_OBJECT_[GS]ET_INDEX()
*/
Common::Array<Object> _objects;
int locals_offset;
int locals_segment; /**< The local variable segment */
@ -353,10 +356,6 @@ public:
obj_indices = NULL;
objects = NULL;
objects_allocated = 0;
objects_nr = 0;
locals_offset = 0;
locals_segment = 0;
locals_block = NULL;