From b0c1cf52e0e4d1e092f9cc25fce9eb86b68b7670 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 18 May 2009 18:15:45 +0000 Subject: SCI: Got rid of EngineState::execution_stack_pos; overally, the resulting code should be even stricter in detecting invalid VM stack access (and some bugs when loading saves might be fixed now...) svn-id: r40694 --- engines/sci/engine/game.cpp | 1 - engines/sci/engine/gc.cpp | 4 +- engines/sci/engine/kernel.cpp | 2 +- engines/sci/engine/kfile.cpp | 2 +- engines/sci/engine/kscripts.cpp | 6 +-- engines/sci/engine/savegame.cpp | 2 +- engines/sci/engine/sciconsole.cpp | 8 +-- engines/sci/engine/scriptdebug.cpp | 24 ++++----- engines/sci/engine/state.cpp | 1 - engines/sci/engine/state.h | 1 - engines/sci/engine/vm.cpp | 93 +++++++++++++++----------------- engines/sci/engine/vm.h | 106 +++++++++++++++++++------------------ 12 files changed, 121 insertions(+), 129 deletions(-) diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 6f55e2655b..6fefa6ab96 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -430,7 +430,6 @@ int script_init_engine(EngineState *s, sci_version_t version) { s->_executionStack.clear(); // Start without any execution stack s->execution_stack_base = -1; // No vm is running yet - s->execution_stack_pos = -1; // Start at execution stack position 0 vocabulary_get_knames(s->resmgr, s->_kernelNames); script_map_kernel(s); diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index 9de5357b38..cf556869ee 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -86,7 +86,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { // Init: Value Stack // We do this one by hand since the stack doesn't know the current execution stack { - ExecStack &xs = s->_executionStack[s->execution_stack_pos]; + ExecStack &xs = s->_executionStack.back(); reg_t *pos; for (pos = s->stack_base; pos < xs.sp; pos++) @@ -97,7 +97,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { #endif // Init: Execution Stack - for (i = 0; (int)i <= s->execution_stack_pos; i++) { + for (i = 0; i < s->_executionStack.size(); i++) { ExecStack &es = s->_executionStack[i]; if (es.type != EXEC_STACK_TYPE_KERNEL) { diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index cb89e04f9f..8cfdf0115c 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -263,7 +263,7 @@ reg_t kRestartGame(EngineState *s, int funct_nr, int argc, reg_t *argv) { old_save_dir = strdup(deref_save_dir); s->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW; s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE; // This appears to help - s->execution_stack_pos = s->execution_stack_base; + s->_executionStack.resize(s->execution_stack_base + 1); script_abort_flag = 1; // Force vm to abort ASAP return NULL_REG; } diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 23c9d90047..a27268798f 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -652,7 +652,7 @@ reg_t kRestoreGame(EngineState *s, int funct_nr, int argc, reg_t *argv) { if (newstate) { s->successor = newstate; script_abort_flag = SCRIPT_ABORT_WITH_REPLAY; // Abort current game - s->execution_stack_pos = s->execution_stack_base; + s->_executionStack.resize(s->execution_stack_base + 1); } else { s->r_acc = make_reg(0, 1); sciprintf("Restoring failed (game_id = '%s').\n", game_id); diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 1598cdcc56..8610478b05 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -92,7 +92,7 @@ int invoke_selector(EngineState *s, reg_t object, int selector_id, int noinvalid // Write "kernel" call to the stack, for debugging: xstack = add_exec_stack_entry(s, NULL_REG, NULL, NULL_REG, k_argc, k_argp - 1, 0, NULL_REG, - s->execution_stack_pos, SCI_XS_CALLEE_LOCALS); + s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); xstack->selector = -42 - kfunct; // Evil debugging hack to identify kernel function xstack->type = EXEC_STACK_TYPE_KERNEL; @@ -104,7 +104,7 @@ int invoke_selector(EngineState *s, reg_t object, int selector_id, int noinvalid run_vm(s, 0); // Start a new vm - --(s->execution_stack_pos); // Get rid of the extra stack entry + s->_executionStack.pop_back(); // Get rid of the extra stack entry return 0; } @@ -269,7 +269,7 @@ reg_t kDisposeScript(EngineState *s, int funct_nr, int argc, reg_t *argv) { int id = s->seg_manager->segGet(script); Script *scr = s->seg_manager->getScriptIfLoaded(id); if (scr) { - if (s->_executionStack[s->execution_stack_pos].addr.pc.segment != id) + if (s->_executionStack.back().addr.pc.segment != id) scr->setLockers(1); } diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 1339b0368a..0bd715719f 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -794,7 +794,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { // Set exec stack base to zero retval->execution_stack_base = 0; - retval->execution_stack_pos = 0; + retval->_executionStack.clear(); // Now copy all current state information // Graphics and input state: diff --git a/engines/sci/engine/sciconsole.cpp b/engines/sci/engine/sciconsole.cpp index 7bbe5f83c4..2a116506c2 100644 --- a/engines/sci/engine/sciconsole.cpp +++ b/engines/sci/engine/sciconsole.cpp @@ -221,10 +221,10 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on rel_offsetting = 1; if (!scumm_strnicmp(str + 1, "PC", 2)) { - *dest = s->_executionStack[s->execution_stack_pos].addr.pc; + *dest = s->_executionStack.back().addr.pc; offsetting = str + 3; } else if (!scumm_strnicmp(str + 1, "P", 1)) { - *dest = s->_executionStack[s->execution_stack_pos].addr.pc; + *dest = s->_executionStack.back().addr.pc; offsetting = str + 2; } else if (!scumm_strnicmp(str + 1, "PREV", 4)) { *dest = s->r_prev; @@ -236,10 +236,10 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on *dest = s->r_acc; offsetting = str + 2; } else if (!scumm_strnicmp(str + 1, "OBJ", 3)) { - *dest = s->_executionStack[s->execution_stack_pos].objp; + *dest = s->_executionStack.back().objp; offsetting = str + 4; } else if (!scumm_strnicmp(str + 1, "O", 1)) { - *dest = s->_executionStack[s->execution_stack_pos].objp; + *dest = s->_executionStack.back().objp; offsetting = str + 2; } else return 1; // No matching register diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 73ccc357b9..171c1435ea 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -692,7 +692,7 @@ int c_debuginfo(EngineState *s) { sciprintf("acc="PREG" prev="PREG" &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), *p_restadjust); - if (!s->_executionStack.empty() && s->execution_stack_pos >= 0) { + if (!s->_executionStack.empty()) { sciprintf("pc="PREG" obj="PREG" fp="PSTK" sp="PSTK"\n", PRINT_REG(*p_pc), PRINT_REG(*p_objp), PRINT_STK(*p_pp), PRINT_STK(*p_sp)); } else sciprintf("\n"); @@ -728,7 +728,7 @@ int c_stepover(EngineState *s, const Common::Array &cmdParams) { if (opnumber == 0x22 /* callb */ || opnumber == 0x23 /* calle */ || opnumber == 0x25 /* send */ || opnumber == 0x2a /* self */ || opnumber == 0x2b /* super */) { _debug_seeking = _DEBUG_SEEK_SO; - _debug_seek_level = s->execution_stack_pos; + _debug_seek_level = s->_executionStack.size()-1; // Store in _debug_seek_special the offset of the next command after send switch (opcode) { case 0x46: // calle W @@ -1103,7 +1103,7 @@ int c_restore_game(EngineState *s, const Common::Array &cmdParams) script_abort_flag = SCRIPT_ABORT_WITH_REPLAY; // Abort current game _debugstate_valid = 0; - s->execution_stack_pos = s->execution_stack_base; + s->_executionStack.resize(s->execution_stack_base + 1); return 0; } else { sciprintf("Restoring gamestate '%s' failed.\n", cmdParams[0].str); @@ -1151,12 +1151,12 @@ int c_stack(EngineState *s, const Common::Array &cmdParams) { return 1; } - if (s->execution_stack_pos < 0) { + if (s->_executionStack.empty()) { sciprintf("No exec stack!"); return 1; } - ExecStack &xs = s->_executionStack[s->execution_stack_pos]; + ExecStack &xs = s->_executionStack.back(); for (int i = cmdParams[0].val ; i > 0; i--) { if ((xs.sp - xs.fp - i) == 0) @@ -1526,15 +1526,13 @@ int c_vmvars(EngineState *s, const Common::Array &cmdParams) { } static int c_backtrace(EngineState *s, const Common::Array &cmdParams) { - int i; - if (!_debugstate_valid) { sciprintf("Not in debug state\n"); return 1; } sciprintf("Call stack (current base: 0x%x):\n", s->execution_stack_base); - for (i = 0; i <= s->execution_stack_pos; i++) { + for (uint i = 0; i < s->_executionStack.size(); i++) { ExecStack &call = s->_executionStack[i]; const char *objname = obj_get_name(s, call.sendp); int paramc, totalparamc; @@ -2121,7 +2119,7 @@ static int c_snk(EngineState *s, const Common::Array &cmdParams) { static int c_sret(EngineState *s, const Common::Array &cmdParams) { _debug_seeking = _DEBUG_SEEK_LEVEL_RET; - _debug_seek_level = s->execution_stack_pos; + _debug_seek_level = s->_executionStack.size()-1; _debugstate_valid = 0; return 0; } @@ -2176,7 +2174,7 @@ static int c_send(EngineState *s, const Common::Array &cmdParams) { stackframe[i] = cmdParams[i].reg; xstack = add_exec_stack_entry(s, fptr, s->_executionStack[0].sp + cmdParams.size(), object, cmdParams.size() - 2, - s->_executionStack[0].sp - 1, 0, object, s->execution_stack_pos, SCI_XS_CALLEE_LOCALS); + s->_executionStack[0].sp - 1, 0, object, s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); xstack->selector = selector_id; xstack->type = selector_type == kSelectorVariable ? EXEC_STACK_TYPE_VARSELECTOR : EXEC_STACK_TYPE_CALL; @@ -2904,13 +2902,13 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * } case _DEBUG_SEEK_LEVEL_RET: { - if ((op != op_ret) || (_debug_seek_level < s->execution_stack_pos)) + if ((op != op_ret) || (_debug_seek_level < (int)s->_executionStack.size()-1)) return; break; } case _DEBUG_SEEK_SO: - if (!REG_EQ(*pc, _debug_seek_reg) || s->execution_stack_pos != _debug_seek_level) + if (!REG_EQ(*pc, _debug_seek_reg) || (int)s->_executionStack.size()-1 != _debug_seek_level) return; break; @@ -2920,7 +2918,7 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * return; if ((op & 0x3) > 1) return; // param or temp - if ((op & 0x3) && s->_executionStack[s->execution_stack_pos].local_segment > 0) + if ((op & 0x3) && s->_executionStack.back().local_segment > 0) return; // locals and not running in script.000 if (paramf1 != _debug_seek_special) return; // CORRECT global? diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 374f997fdb..f60697d83c 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -104,7 +104,6 @@ EngineState::EngineState() : _dirseeker(this) { kernel_opt_flags = 0; - execution_stack_pos = 0; execution_stack_base = 0; _executionStackPosChanged = false; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 5ab90f442a..c178016a6e 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -208,7 +208,6 @@ public: /* VM Information */ Common::Array _executionStack; /**< The execution stack */ - int execution_stack_pos; /**< Position on the execution stack */ /** * When called from kernel functions, the vm is re-started recursively on * the same stack. This variable contains the stack base for the current vm. diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 151e4ff572..a51a49ffb3 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -279,49 +279,43 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP } } - return add_exec_stack_entry(s, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, calling_obj, s->execution_stack_pos, seg); + return add_exec_stack_entry(s, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, calling_obj, s->_executionStack.size()-1, seg); } static void _exec_varselectors(EngineState *s) { // Executes all varselector read/write ops on the TOS // Now check the TOS to execute all varselector entries - if (s->execution_stack_pos >= 0) - while (s->_executionStack[s->execution_stack_pos].type == EXEC_STACK_TYPE_VARSELECTOR) { + if (!s->_executionStack.empty()) + while (s->_executionStack.back().type == EXEC_STACK_TYPE_VARSELECTOR) { // varselector access? - if (s->_executionStack[s->execution_stack_pos].argc) { // write? - reg_t temp = s->_executionStack[s->execution_stack_pos].variables_argp[1]; - *(s->_executionStack[s->execution_stack_pos].addr.varp) = temp; + if (s->_executionStack.back().argc) { // write? + reg_t temp = s->_executionStack.back().variables_argp[1]; + *(s->_executionStack.back().addr.varp) = temp; } else // No, read - s->r_acc = *(s->_executionStack[s->execution_stack_pos].addr.varp); + s->r_acc = *(s->_executionStack.back().addr.varp); - --(s->execution_stack_pos); + s->_executionStack.pop_back(); } } ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPtr sp, int framesize, StackPtr argp) { // send_obj and work_obj are equal for anything but 'super' // Returns a pointer to the TOS exec_stack element -#ifdef VM_DEBUG_SEND - int i; -#endif + assert(s); + reg_t *varp; reg_t funcp; int selector; int argc; - int origin = s->execution_stack_pos; // Origin: Used for debugging + int origin = s->_executionStack.size()-1; // Origin: Used for debugging int print_send_action = 0; // We return a pointer to the new active ExecStack // The selector calls we catch are stored below: Common::Stack sendCalls; - if (NULL == s) { - sciprintf("vm.c: ExecStack(): NULL passed for \"s\"\n"); - return NULL; - } - while (framesize > 0) { selector = validate_arithmetic(*argp++); argc = validate_arithmetic(*argp); @@ -423,7 +417,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt #ifdef VM_DEBUG_SEND sciprintf("Funcselector("); - for (i = 0; i < argc; i++) { + for (int i = 0; i < argc; i++) { sciprintf(PREG, PRINT_REG(argp[i+1])); if (i + 1 < argc) sciprintf(", "); @@ -467,7 +461,9 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt _exec_varselectors(s); - return &(s->_executionStack[s->execution_stack_pos]); + if (s->_executionStack.empty()) + return NULL; + return &(s->_executionStack.back()); } ExecStack *add_exec_stack_varselector(EngineState *s, reg_t objp, int argc, StackPtr argp, Selector selector, reg_t *address, int origin) { @@ -485,36 +481,34 @@ ExecStack *add_exec_stack_entry(EngineState *s, reg_t pc, StackPtr sp, reg_t obj // Returns new TOS element for the execution stack // locals_segment may be -1 if derived from the called object - ++s->execution_stack_pos; - if (s->execution_stack_pos >= (int)s->_executionStack.size()) // Out of stack space? - s->_executionStack.resize(s->execution_stack_pos+1); - //sciprintf("Exec stack: [%d/%d], origin %d, at %p\n", s->execution_stack_pos, s->_executionStack.size(), origin, s->execution_stack); - ExecStack *xstack = &(s->_executionStack[s->execution_stack_pos]); + ExecStack xstack; - xstack->objp = objp; + xstack.objp = objp; if (locals_segment != SCI_XS_CALLEE_LOCALS) - xstack->local_segment = locals_segment; + xstack.local_segment = locals_segment; else - xstack->local_segment = pc.segment; + xstack.local_segment = pc.segment; - xstack->sendp = sendp; - xstack->addr.pc = pc; - xstack->fp = xstack->sp = sp; - xstack->argc = argc; + xstack.sendp = sendp; + xstack.addr.pc = pc; + xstack.fp = xstack.sp = sp; + xstack.argc = argc; - xstack->variables_argp = argp; // Parameters + xstack.variables_argp = argp; // Parameters *argp = make_reg(0, argc); // SCI code relies on the zeroeth argument to equal argc // Additional debug information - xstack->selector = selector; - xstack->origin = origin; + xstack.selector = selector; + xstack.origin = origin; - xstack->type = EXEC_STACK_TYPE_CALL; // Normal call + xstack.type = EXEC_STACK_TYPE_CALL; // Normal call - return xstack; + s->_executionStack.push_back(xstack); + + return &(s->_executionStack.back()); } #ifdef DISABLE_VALIDATONS @@ -585,7 +579,7 @@ void run_vm(EngineState *s, int restoring) { int restadjust = s->r_amp_rest; // &rest adjusts the parameter count by this value // Current execution data: - ExecStack *xs = &(s->_executionStack[s->execution_stack_pos]); + ExecStack *xs = &(s->_executionStack.back()); ExecStack *xs_new = NULL; Object *obj = obj_get(s, xs->objp); Script *local_script = script_locate_by_segment(s, xs->local_segment); @@ -604,7 +598,7 @@ void run_vm(EngineState *s, int restoring) { } if (!restoring) - s->execution_stack_base = s->execution_stack_pos; + s->execution_stack_base = s->_executionStack.size()-1; #ifndef DISABLE_VALIDATIONS // Initialize maximum variable count @@ -640,7 +634,7 @@ void run_vm(EngineState *s, int restoring) { if (s->_executionStackPosChanged) { Script *scr; - xs = &(s->_executionStack[s->execution_stack_pos]); + xs = &(s->_executionStack.back()); s->_executionStackPosChanged = false; scr = script_locate_by_segment(s, xs->addr.pc.segment); @@ -988,7 +982,7 @@ void run_vm(EngineState *s, int restoring) { xs->sp[1].offset += restadjust; xs_new = add_exec_stack_entry(s, make_reg(xs->addr.pc.segment, xs->addr.pc.offset + opparams[0]), xs->sp, xs->objp, (validate_arithmetic(*call_base)) + restadjust, - call_base, NULL_SELECTOR, xs->objp, s->execution_stack_pos, xs->local_segment); + call_base, NULL_SELECTOR, xs->objp, s->_executionStack.size()-1, xs->local_segment); restadjust = 0; // Used up the &rest adjustment xs->sp = call_base; @@ -1026,7 +1020,7 @@ void run_vm(EngineState *s, int restoring) { // Calculate xs again: The kernel function might // have spawned a new VM - xs_new = &(s->_executionStack[s->execution_stack_pos]); + xs_new = &(s->_executionStack.back()); s->_executionStackPosChanged = true; if (!(s->flags & GF_SCI0_OLD)) @@ -1064,12 +1058,12 @@ void run_vm(EngineState *s, int restoring) { do { StackPtr old_sp2 = xs->sp; StackPtr old_fp = xs->fp; - ExecStack *old_xs = &(s->_executionStack[s->execution_stack_pos]); + ExecStack *old_xs = &(s->_executionStack.back()); - if (s->execution_stack_pos == s->execution_stack_base) { // Have we reached the base? + if ((int)s->_executionStack.size()-1 == s->execution_stack_base) { // Have we reached the base? s->execution_stack_base = old_execution_stack_base; // Restore stack base - --(s->execution_stack_pos); + s->_executionStack.pop_back(); s->_executionStackPosChanged = true; s->r_amp_rest = restadjust; // Update &rest @@ -1085,10 +1079,10 @@ void run_vm(EngineState *s, int restoring) { } // Not reached the base, so let's do a soft return - --(s->execution_stack_pos); + s->_executionStack.pop_back(); xs = old_xs - 1; s->_executionStackPosChanged = true; - xs = &(s->_executionStack[s->execution_stack_pos]); + xs = &(s->_executionStack.back()); if (xs->sp == CALL_SP_CARRY // Used in sends to 'carry' the stack pointer || xs->type != EXEC_STACK_TYPE_CALL) { @@ -1452,8 +1446,8 @@ void run_vm(EngineState *s, int restoring) { xs = xs_new; #ifndef DISABLE_VALIDATIONS - if (xs != &(s->_executionStack[s->execution_stack_pos])) { - sciprintf("Error: xs is stale (%d vs %d); last command was %02x\n", (int)(xs - &s->_executionStack[0]), s->execution_stack_pos, opnumber); + if (xs != &(s->_executionStack.back())) { + sciprintf("Error: xs is stale (%d vs %d); last command was %02x\n", (int)(xs - &s->_executionStack[0]), s->_executionStack.size()-1, opnumber); } #endif if (script_error_flag) { @@ -1991,7 +1985,6 @@ static EngineState *_game_run(EngineState *s, int restoring) { if (s->restarting_flags & SCI_GAME_IS_RESTARTING_NOW) { // Restart was requested? successor = NULL; s->_executionStack.clear(); - s->execution_stack_pos = -1; s->_executionStackPosChanged = false; game_exit(s); @@ -2017,7 +2010,7 @@ static EngineState *_game_run(EngineState *s, int restoring) { if (script_abort_flag == SCRIPT_ABORT_WITH_REPLAY) { sciprintf("Restarting with replay()\n"); - s->execution_stack_pos = -1; // Restart with replay + s->_executionStack.clear(); // Restart with replay _init_stack_base_with_selector(s, s->selector_map.replay); diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 5b9c87decb..a6e232472e 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -808,73 +808,77 @@ typedef int kernel_function(struct EngineState *s); extern kernel_function* kfuncs[]; extern int max_instance; -/*inline*/ +/** + * Executes function pubfunct of the specified script. + * Parameters: (EngineState *) s: The state which is to be executed with + * (uint16) script: The script which is called + * (uint16) pubfunct: The exported script function which is to be called + * (StackPtr) sp: Stack pointer position + * (reg_t) calling_obj: The heap address of the object which executed the call + * (uint16) argc: Number of arguments supplied + * (StackPtr) argp: Pointer to the first supplied argument + * Returns : (ExecStack *): A pointer to the new exec stack TOS entry + */ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp); -/* Executes function pubfunct of the specified script. -** Parameters: (EngineState *) s: The state which is to be executed with -** (uint16) script: The script which is called -** (uint16) pubfunct: The exported script function which is to be called -** (StackPtr) sp: Stack pointer position -** (reg_t) calling_obj: The heap address of the object which executed the call -** (uint16) argc: Number of arguments supplied -** (StackPtr) argp: Pointer to the first supplied argument -** Returns : (ExecStack *): A pointer to the new exec stack TOS entry -*/ +/** + * Executes a "send" or related operation to a selector. + * Parameters: (EngineState *) s: The EngineState to operate on + * (reg_t) send_obj: Heap address of the object to send to + * (reg_t) work_obj: Heap address of the object initiating the send + * (StackPtr) sp: Stack pointer position + * (int) framesize: Size of the send as determined by the "send" operation + * (StackPtr) argp: Pointer to the beginning of the heap block containing the + * data to be sent. This area is a succession of one or more + * sequences of [selector_number][argument_counter] and then + * "argument_counter" word entries with the parameter values. + * Returns : (ExecStack *): A pointer to the new execution stack TOS entry + */ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPtr sp, int framesize, StackPtr argp); -/* Executes a "send" or related operation to a selector -** Parameters: (EngineState *) s: The EngineState to operate on -** (reg_t) send_obj: Heap address of the object to send to -** (reg_t) work_obj: Heap address of the object initiating the send -** (StackPtr) sp: Stack pointer position -** (int) framesize: Size of the send as determined by the "send" operation -** (StackPtr) argp: Pointer to the beginning of the heap block containing the -** data to be send. This area is a succession of one or more -** sequences of [selector_number][argument_counter] and then -** "argument_counter" word entries with the parameter values. -** Returns : (ExecStack *): A pointer to the new execution stack TOS entry -*/ #define SCI_XS_CALLEE_LOCALS -1 +/** + * Adds an entry to the top of the execution stack. + * + * @param s The state with which to execute + * @param pc The initial program counter + * @param sp The initial stack pointer + * @param objp Pointer to the beginning of the current object + * @param argc Number of parameters to call with + * @param argp Heap pointer to the first parameter + * @param selector The selector by which it was called or + * NULL_SELECTOR if n.a. For debugging. + * @param sendp Pointer to the object which the message was sent to. + * Equal to objp for anything but super. + * @param origin Number of the execution stack element this entry was created by + * (usually the current TOS number, except for multiple sends). + * @param local_segment The segment to use for local variables, + * or SCI_XS_CALLEE_LOCALS to use obj's segment. + * @return a pointer to the new exec stack TOS entry + */ ExecStack *add_exec_stack_entry(EngineState *s, reg_t pc, StackPtr sp, reg_t objp, int argc, StackPtr argp, Selector selector, reg_t sendp, int origin, SegmentId local_segment); -/* Adds an entry to the top of the execution stack -** Parameters: (EngineState *) s: The state with which to execute -** (reg_t) pc: The initial program counter -** (StackPtr) sp: The initial stack pointer -** (reg_t) objp: Pointer to the beginning of the current object -** (int) argc: Number of parameters to call with -** (StackPtr) argp: Heap pointer to the first parameter -** (Selector) selector: The selector by which it was called or -** NULL_SELECTOR if n.a. For debugging. -** (reg_t) sendp: Pointer to the object which the message was sent to. -** Equal to objp for anything but super. -** (int) origin: Number of the execution stack element this entry was created by -** (usually the current TOS number, except for multiple sends). -** (SegmentId) local_segment: The segment to use for local variables, -** or SCI_XS_CALLEE_LOCALS to use obj's segment. -** Returns : (ExecStack *): A pointer to the new exec stack TOS entry -*/ +/** + * Adds one varselector access to the execution stack. + * Parameters: (EngineState *) s: The EngineState to use + * (reg_t) objp: Pointer to the object owning the selector + * (int) argc: 1 for writing, 0 for reading + * (StackPtr) argp: Pointer to the address of the data to write -2 + * (int) selector: Selector name + * (reg_t *) address: Heap address of the selector + * (int) origin: Stack frame which the access originated from + * Returns : (ExecStack *): Pointer to the new exec-TOS element + * This function is called from send_selector only. + */ ExecStack *add_exec_stack_varselector(EngineState *s, reg_t objp, int argc, StackPtr argp, Selector selector, reg_t *address, int origin); -/* Adds one varselector access to the execution stack -** Parameters: (EngineState *) s: The EngineState to use -** (reg_t) objp: Pointer to the object owning the selector -** (int) argc: 1 for writing, 0 for reading -** (StackPtr) argp: Pointer to the address of the data to write -2 -** (int) selector: Selector name -** (reg_t *) address: Heap address of the selector -** (int) origin: Stack frame which the access originated from -** Returns : (ExecStack *): Pointer to the new exec-TOS element -** This function is called from send_selector only. -*/ void run_vm(EngineState *s, int restoring); -- cgit v1.2.3