From f888cc5b69012ee488ceacfa06a4c53827e92cdd Mon Sep 17 00:00:00 2001 From: Dennis Schridde Date: Thu, 27 Mar 2008 18:38:25 +0000 Subject: [PATCH] Revert 4344-4347, 4355, 4357, 4358, 4362: They caused too much slowdown in the scripting engine git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@4379 4a71c877-e1ca-e34f-864e-861f7616d084 --- lib/script/event.c | 60 +++++++++------ lib/script/interp.c | 84 +-------------------- lib/script/interp.h | 13 +--- lib/script/script.c | 15 +++- lib/script/script_parser.y | 13 ++-- lib/script/stack.c | 151 ++++++++++++++++++++++--------------- lib/script/stack.h | 9 ++- 7 files changed, 160 insertions(+), 185 deletions(-) diff --git a/lib/script/event.c b/lib/script/event.c index da81eaa15..605ee249c 100644 --- a/lib/script/event.c +++ b/lib/script/event.c @@ -348,9 +348,10 @@ BOOL eventNewContext(SCRIPT_CODE *psCode, CONTEXT_RELEASE release, SCRIPT_CONTEXT **ppsContext) { SCRIPT_CONTEXT *psContext; - SDWORD val, storeIndex, arrayNum, arraySize = 1; + SDWORD val, storeIndex, arrayNum, arraySize; + UDWORD i, j; + INTERP_TYPE type; VAL_CHUNK *psNewChunk, *psNextChunk; - unsigned int i; ASSERT(psCode != NULL, "eventNewContext: Invalid code pointer"); @@ -368,13 +369,12 @@ BOOL eventNewContext(SCRIPT_CODE *psCode, CONTEXT_RELEASE release, psContext->release = release; psContext->psGlobals = NULL; psContext->id = -1; // only used by the save game - val = psCode->numGlobals + psCode->arraySize - 1; arrayNum = psCode->numArrays - 1; - + arraySize = 1; if (psCode->numArrays > 0) { - for(i = 0; ipsArrayInfo[arrayNum].dimensions; i++) + for(i=0; ipsArrayInfo[arrayNum].dimensions; i++) { arraySize *= psCode->psArrayInfo[arrayNum].elements[i]; } @@ -383,39 +383,55 @@ BOOL eventNewContext(SCRIPT_CODE *psCode, CONTEXT_RELEASE release, //prepare local variables (initialize, store type) //------------------------------- - for(i = 0; i < psCode->numEvents; i++) + psCode->ppsLocalVarVal = (INTERP_VAL **)malloc(sizeof(INTERP_VAL*) * psCode->numEvents); //allocate space for array of local var arrays for each event + + debug(LOG_SCRIPT,"allocated space for %d events", psCode->numEvents); + + for(i=0;i < psCode->numEvents; i++) { if(psCode->numLocalVars[i] > 0) //this event has any local vars declared { - unsigned int j; + psCode->ppsLocalVarVal[i] = (INTERP_VAL*)malloc(sizeof(INTERP_VAL) * psCode->numLocalVars[i]); //allocate space for local vars array (for the current event) debug(LOG_SCRIPT,"Event %d has %d local variables", i, psCode->numLocalVars[i]); - for(j = 0; j < psCode->numLocalVars[i]; j++) + for(j=0; j < psCode->numLocalVars[i]; j++) { - INTERP_TYPE type = psCode->ppsLocalVars[i][j].type; + type = psCode->ppsLocalVars[i][j]; - if (!interpInitValue(type, &psCode->ppsLocalVars[i][j])) - { - debug(LOG_ERROR, "eventNewContext: failed to init local value"); - return false; + //debug(LOG_SCRIPT,"var %d's type: %d", i, type); + + /* initialize Strings, integers, floats etc + memset to 0, the only special case is strings */ + memset (&(psCode->ppsLocalVarVal[i][j]), 0, sizeof(INTERP_VAL)); + if (type == VAL_STRING) { + psCode->ppsLocalVarVal[i][j].v.sval = (char*)malloc(MAXSTRLEN); + strcpy(psCode->ppsLocalVarVal[i][j].v.sval,"\0"); } //Initialize objects if (asCreateFuncs != NULL && type < numFuncs && asCreateFuncs[type]) { - if (!asCreateFuncs[type](&(psCode->ppsLocalVars[i][j]))) + if (!asCreateFuncs[type](&(psCode->ppsLocalVarVal[i][j]) )) { debug(LOG_ERROR,"eventNewContext: asCreateFuncs failed for local var"); return false; } } + + psCode->ppsLocalVarVal[i][j].type = type; //store (copy) var type (data used during parsing -> data used during interpreting) + + //debug(LOG_SCRIPT, "i=%d, j=%d, value=%d",i,j,psCode->ppsLocalVarVal[i][j].v.ival); } + + //debug(LOG_SCRIPT,"------"); + } else //this event has no local vars { - psCode->ppsLocalVars[i] = NULL; + psCode->ppsLocalVarVal[i] = NULL; } + } while (val >= 0) @@ -436,8 +452,6 @@ BOOL eventNewContext(SCRIPT_CODE *psCode, CONTEXT_RELEASE release, storeIndex = val % CONTEXT_VALS; while (storeIndex >= 0) { - INTERP_TYPE type; - if (val >= psCode->numGlobals) { type = psCode->psArrayInfo[arrayNum].type; @@ -448,12 +462,16 @@ BOOL eventNewContext(SCRIPT_CODE *psCode, CONTEXT_RELEASE release, } // initialize Strings, integers etc - if (!interpInitValue(type, &psNewChunk->asVals[storeIndex])) - { - debug(LOG_ERROR, "eventNewContext: failed to init global value"); - return false; + // memset to 0 + memset(&(psNewChunk->asVals[storeIndex]), 0, sizeof(INTERP_VAL)); + if (type == VAL_STRING) { + psNewChunk->asVals[storeIndex].v.sval = (char*)malloc(MAXSTRLEN); + strcpy(psNewChunk->asVals[storeIndex].v.sval,"\0"); } + // set type + psNewChunk->asVals[storeIndex].type = type; + //initialize objects if (asCreateFuncs != NULL && type < numFuncs && asCreateFuncs[type]) { diff --git a/lib/script/interp.c b/lib/script/interp.c index 75d67b202..1c2439644 100644 --- a/lib/script/interp.c +++ b/lib/script/interp.c @@ -968,83 +968,6 @@ void scriptSetTypeEquiv(TYPE_EQUIV *psTypeTab) } -BOOL interpInitValue(INTERP_TYPE type, INTERP_VAL *value) -{ - memset(value, 0, sizeof(*value)); - - value->type = type; - switch (type) - { - case VAL_STRING: - value->v.sval = malloc(MAXSTRLEN); - if (value->v.sval == NULL) - { - debug(LOG_ERROR, "interpInitValue(string): Out of memory"); - return false; - } - value->v.sval[0] = '\0'; - break; - default: - break; - } - - return true; -} - - -void interpCleanValue(INTERP_VAL *value) -{ - switch (value->type) - { - case VAL_STRING: - free(value->v.sval); - value->v.sval = NULL; - break; - default: - break; - } -} - - -BOOL interpCopyValue(INTERP_VAL *to, INTERP_VAL *from, BOOL deep) -{ - /* Check whether we can do a direct copy */ - if (interpCheckEquiv(to->type, from->type)) - { - if (deep && to->type == VAL_STRING) - { - return (strlcpy(to->v.sval, from->v.sval, MAXSTRLEN) != 0); - } - return (memcpy(&(to->v), &(from->v), sizeof(to->v)) != NULL); - } - - /* Or have to do an implicit conversion */ - switch (to->type) - { - case VAL_STRING: - switch (from->type) - { - case VAL_BOOL: - return (snprintf(to->v.sval, MAXSTRLEN, "%d", from->v.bval) != 0); - case VAL_INT: - return (snprintf(to->v.sval, MAXSTRLEN, "%d", from->v.ival) != 0); - case VAL_FLOAT: - return (snprintf(to->v.sval, MAXSTRLEN, "%f", from->v.fval) != 0); - default: - break; - } - break; - default: - break; - } - - ASSERT( false, - "interpCopyValue: type mismatch (expected %s, got %s)", - scriptTypeToString(to->type), scriptTypeToString(from->type) ); - return false; -} - - /* Check if two types are equivalent * Means: Their data can be copied without conversion. * I.e. strings are NOT equivalent to anything but strings, even though they can be converted @@ -1240,14 +1163,15 @@ static inline void createVarEnvironment(SCRIPT_CONTEXT *psContext, UDWORD eventI varEnvironment[callDepth] = (INTERP_VAL *)malloc(sizeof(INTERP_VAL) * numEventVars); // create environment - memcpy(varEnvironment[callDepth], psContext->psCode->ppsLocalVars[eventIndex], sizeof(INTERP_VAL) * numEventVars); + memcpy(varEnvironment[callDepth], psContext->psCode->ppsLocalVarVal[eventIndex], sizeof(INTERP_VAL) * numEventVars); // allocate new space for strings to preserve original ones for (i = 0; i < numEventVars; i++) { - if (!interpInitValue(varEnvironment[callDepth][i].type, &varEnvironment[callDepth][i])) + if (varEnvironment[callDepth][i].type == VAL_STRING) { - debug(LOG_ERROR, "createVarEnvironment: failed to init local var"); + varEnvironment[callDepth][i].v.sval = (char*)malloc(MAXSTRLEN); + strcpy( varEnvironment[callDepth][i].v.sval, "" ); //initialize } } } diff --git a/lib/script/interp.h b/lib/script/interp.h index d9439f898..229885c6a 100644 --- a/lib/script/interp.h +++ b/lib/script/interp.h @@ -163,9 +163,6 @@ typedef enum _op_code #define ARRAY_DIMENSION_SHIFT 20 #define ARRAY_DIMENSION_MASK 0x00f00000 -#define VAR_COPY_DEEP true -#define VAR_COPY_FLAT false - /* The possible storage types for a variable */ typedef enum _storage_type { @@ -248,11 +245,13 @@ typedef struct _script_code UDWORD arraySize; // the number of elements in all the defined arrays INTERP_TYPE *pGlobals; // Types of the global variables - UDWORD *numLocalVars; //number of local vars each event has - INTERP_VAL **ppsLocalVars; //storage for local vars + INTERP_TYPE **ppsLocalVars; //storage for local vars (type) + UDWORD *numLocalVars; //number of local vars each event has + INTERP_VAL **ppsLocalVarVal; //Values of the local vars used during interpreting process UDWORD *numParams; //number of arguments this event has + VAR_DEBUG *psVarDebug; // The names and storage types of variables ARRAY_DATA *psArrayInfo; // The sizes of the program arrays ARRAY_DEBUG *psArrayDebug; // Debug info for the arrays @@ -285,10 +284,6 @@ extern BOOL interpProcessorActive(void); /* Output script call stack trace */ extern void scrOutputCallTrace(void); -extern BOOL interpCopyValue(INTERP_VAL *to, INTERP_VAL *from, BOOL deep); -extern BOOL interpInitValue(INTERP_TYPE type, INTERP_VAL *value); -extern void interpCleanValue(INTERP_VAL *value); - #endif diff --git a/lib/script/script.c b/lib/script/script.c index e1d920eec..ff4855ddb 100644 --- a/lib/script/script.c +++ b/lib/script/script.c @@ -81,10 +81,18 @@ void scriptFreeCode(SCRIPT_CODE *psCode) //free strings for event i for(j=0; j < psCode->numLocalVars[i]; j++) { - interpCleanValue(&psCode->ppsLocalVars[i][j]); + + if(psCode->ppsLocalVarVal[i][j].type == VAL_STRING) //if a string + { + if(psCode->ppsLocalVarVal[i][j].v.sval != NULL) //doublecheck.. + { + free(psCode->ppsLocalVarVal[i][j].v.sval); //free string + } + } } - free(psCode->ppsLocalVars[i]); // free pointer to event i local vars + free(psCode->ppsLocalVars[i]); + free(psCode->ppsLocalVarVal[i]); //free pointer to event i local vars } } @@ -152,6 +160,9 @@ void scriptFreeCode(SCRIPT_CODE *psCode) if(psCode->ppsLocalVars != NULL) free(psCode->ppsLocalVars); + if(psCode->ppsLocalVarVal != NULL) + free(psCode->ppsLocalVarVal); + psCode->numEvents = 0; free(psCode); diff --git a/lib/script/script_parser.y b/lib/script/script_parser.y index 7c5789c13..7784fe2a9 100644 --- a/lib/script/script_parser.y +++ b/lib/script/script_parser.y @@ -1992,14 +1992,11 @@ script: header var_list ALLOC_PROG(psFinalProg, size, psCurrBlock->pCode, numVars, numArrays, numTriggers, numEvents); - debug(LOG_SCRIPT, "allocated space for %d events", numEvents); - //store local vars - psFinalProg->numLocalVars = (UDWORD *)malloc(sizeof(UDWORD) * numEvents); //how many local vars each event has - //allocate array for holding an array of local vars for each event - psFinalProg->ppsLocalVars = (INTERP_VAL **)malloc(sizeof(INTERP_VAL*) * numEvents); - + psFinalProg->ppsLocalVars = (INTERP_TYPE **)malloc(sizeof(INTERP_TYPE*) * numEvents); + psFinalProg->ppsLocalVarVal = NULL; + psFinalProg->numLocalVars = (UDWORD *)malloc(sizeof(UDWORD) * numEvents); //how many local vars each event has psFinalProg->numParams = (UDWORD *)malloc(sizeof(UDWORD) * numEvents); //how many arguments each event has for(psEvent = psEvents, i = 0; psEvent; psEvent = psEvent->psNext, i++) @@ -2012,11 +2009,11 @@ script: header var_list if(numEventLocalVars[i] > 0) { unsigned int j; - INTERP_VAL * pCurEvLocalVars = (INTERP_VAL*)malloc(sizeof(INTERP_VAL) * numEventLocalVars[i]); + INTERP_TYPE * pCurEvLocalVars = (INTERP_TYPE*)malloc(sizeof(INTERP_TYPE) * numEventLocalVars[i]); for(psCurr = psLocalVarsB[i], j = 0; psCurr != NULL; psCurr = psCurr->psNext, j++) { - interpInitValue(psCurr->type, &pCurEvLocalVars[numEventLocalVars[i] - j - 1]); + pCurEvLocalVars[numEventLocalVars[i] - j - 1] = psCurr->type; //save type, order is reversed } psFinalProg->ppsLocalVars[i] = pCurEvLocalVars; diff --git a/lib/script/stack.c b/lib/script/stack.c index a45402f7c..c4ef80f6d 100644 --- a/lib/script/stack.c +++ b/lib/script/stack.c @@ -48,20 +48,20 @@ typedef struct _stack_chunk INTERP_VAL *aVals; UDWORD size; - struct _stack_chunk *psNext, *psPrev; + struct _stack_chunk *psNext, *psPrev; } STACK_CHUNK; /* The first chunk of the stack */ -static STACK_CHUNK *psStackBase = NULL; +static STACK_CHUNK *psStackBase=NULL; /* The current stack chunk */ -static STACK_CHUNK *psCurrChunk = NULL; +static STACK_CHUNK *psCurrChunk=NULL; /* The current free entry on the current stack chunk */ -static UDWORD currEntry = 0; +static UDWORD currEntry=0; -/* Get rid of the top value(s) without returning it */ -static inline BOOL stackReduce(unsigned int numItems); +/* Get rid of the top value without returning it */ +static inline BOOL stackRemoveTop(void); /* Check if the stack is empty */ @@ -112,13 +112,35 @@ static BOOL stackNewChunk(UDWORD size) /* Push a value onto the stack */ -BOOL stackPush(INTERP_VAL *psVal) +BOOL stackPush(INTERP_VAL *psVal) { /* Store the value in the stack - psCurrChunk/currEntry always point to valid space */ - interpInitValue(psVal->type, &psCurrChunk->aVals[currEntry]); - interpCopyValue(&psCurrChunk->aVals[currEntry], psVal, VAR_COPY_DEEP); + /* String support: Copy the string, otherwise the stack will operate directly on the + original string (like & opcode will actually store the result in the first + variable which would point to the original string) */ + if(psVal->type == VAL_STRING) //pushing string + { + /* strings should already have memory allocated */ + if(psCurrChunk->aVals[currEntry].type != VAL_STRING) //needs to have memory allocated for string + psCurrChunk->aVals[currEntry].v.sval = (char*)malloc(MAXSTRLEN); + + strcpy(psCurrChunk->aVals[currEntry].v.sval, psVal->v.sval); //copy string to stack + psCurrChunk->aVals[currEntry].type = VAL_STRING; + } + else /* pushing non-string */ + { + /* free stack var allocated string memory, if stack var used to be of type VAL_STRING */ + if(psCurrChunk->aVals[currEntry].type == VAL_STRING) + { + free(psCurrChunk->aVals[currEntry].v.sval); //don't need it anymore + psCurrChunk->aVals[currEntry].v.sval = NULL; + } + + /* copy type/data as union */ + memcpy(&(psCurrChunk->aVals[currEntry]), psVal, sizeof(INTERP_VAL)); + } /* Now update psCurrChunk and currEntry */ currEntry++; @@ -137,8 +159,9 @@ BOOL stackPush(INTERP_VAL *psVal) } + /* Pop a value off the stack */ -BOOL stackPop(INTERP_VAL *psVal) +BOOL stackPop(INTERP_VAL *psVal) { if (stackEmpty()) { @@ -148,20 +171,25 @@ BOOL stackPop(INTERP_VAL *psVal) } /* move the stack pointer down one */ - if (!stackReduce(1)) + if (currEntry == 0) { - return false; + /* have to move onto the previous chunk. */ + psCurrChunk = psCurrChunk->psPrev; + currEntry = psCurrChunk->size -1; + } + else + { + currEntry--; } /* copy the entire value off the stack */ - memcpy(psVal, &psCurrChunk->aVals[currEntry], sizeof(*psVal)); + memcpy(psVal, &(psCurrChunk->aVals[currEntry]), sizeof(INTERP_VAL)); return true; } - /* Return pointer to the top value without poping it */ -BOOL stackPeekTop(INTERP_VAL **ppsVal) +BOOL stackPeekTop(INTERP_VAL **ppsVal) { if ((psCurrChunk->psPrev == NULL) && (currEntry == 0)) { @@ -191,9 +219,9 @@ BOOL stackPeekTop(INTERP_VAL **ppsVal) /* Pop a value off the stack, checking that the type matches what is passed in */ -BOOL stackPopType(INTERP_VAL *psVal) +BOOL stackPopType(INTERP_VAL *psVal) { - INTERP_VAL *psTop; + INTERP_VAL *psTop; if ((psCurrChunk->psPrev == NULL) && (currEntry == 0)) { @@ -453,6 +481,8 @@ BOOL stackPushResult(INTERP_TYPE type, INTERP_VAL *result) */ BOOL stackPeek(INTERP_VAL *psVal, UDWORD index) { + STACK_CHUNK *psCurr; + if (index < currEntry) { /* Looking at entry on current chunk */ @@ -461,8 +491,6 @@ BOOL stackPeek(INTERP_VAL *psVal, UDWORD index) } else { - STACK_CHUNK *psCurr; - /* Have to work down the previous chunks to find the entry */ index -= currEntry; @@ -474,8 +502,10 @@ BOOL stackPeek(INTERP_VAL *psVal, UDWORD index) memcpy(psVal, &(psCurr->aVals[psCurr->size - 1 - index]), sizeof(INTERP_VAL)); return true; } - - index -= psCurr->size; + else + { + index -= psCurr->size; + } } } @@ -806,7 +836,7 @@ BOOL stackUnaryOp(OPCODE opcode) psVal->v.ival++; /* Just get rid of the variable pointer, since already increased it */ - if (!stackReduce(1)) + if (!stackRemoveTop()) { debug( LOG_ERROR, "stackUnaryOpcode: OP_INC: could not pop" ); return false; @@ -831,7 +861,7 @@ BOOL stackUnaryOp(OPCODE opcode) psVal->v.ival--; /* Just get rid of the variable pointer, since already decreased it */ - if (!stackReduce(1)) + if (!stackRemoveTop()) { debug( LOG_ERROR, "stackUnaryOpcode: OP_DEC: could not pop" ); return false; @@ -880,7 +910,6 @@ BOOL stackUnaryOp(OPCODE opcode) return true; } - BOOL stackCastTop(INTERP_TYPE neededType) { INTERP_VAL *pTop; @@ -976,12 +1005,14 @@ BOOL stackInitialise(void) } + /* Shutdown the stack */ void stackShutDown(void) { - STACK_CHUNK *psCurr, *psNext; + STACK_CHUNK *psCurr, *psNext; + UDWORD i; - if (!stackEmpty()) + if ((psCurrChunk != psStackBase) && (currEntry != 0)) { debug( LOG_NEVER, "stackShutDown: stack is not empty on shutdown" ); } @@ -989,56 +1020,52 @@ void stackShutDown(void) for(psCurr = psStackBase; psCurr != NULL; psCurr = psNext) { psNext = psCurr->psNext; + + /* Free strings */ + for(i=0; i< psCurr->size; i++) //go through all values on this chunk + { + if(psCurr->aVals[i].type == VAL_STRING) + { + if(psCurr->aVals[i].v.sval != NULL) //FIXME: seems to be causing problems sometimes + { + debug(LOG_WZ, "freeing '%s' ", psCurr->aVals[i].v.sval); + free(psCurr->aVals[i].v.sval); + psCurr->aVals[i].v.sval = NULL; + } + else + { + debug(LOG_SCRIPT, "stackShutDown: VAL_STRING with null pointer"); + } + } + } + free(psCurr->aVals); free(psCurr); } } - -/* Get rid of the top value(s) without returning it */ -static inline BOOL stackReduce(unsigned int numItems) +/* Get rid of the top value without returning it */ +static inline BOOL stackRemoveTop(void) { - if (stackEmpty()) + if ((psCurrChunk->psPrev == NULL) && (currEntry == 0)) { - debug(LOG_ERROR, "stackReduce: stack empty"); - ASSERT( false, "stackReduce: stack empty" ); + debug(LOG_ERROR, "stackRemoveTop: stack empty"); + ASSERT( false, "stackRemoveTop: stack empty" ); return false; } - // Find the position of the first item, and set - // the stack top to it - if (numItems <= currEntry) + /* move the stack pointer down one */ + if (currEntry == 0) { - // items are all on current chunk - currEntry = currEntry - numItems; + /* have to move onto the previous chunk. */ + psCurrChunk = psCurrChunk->psPrev; + currEntry = psCurrChunk->size -1; } else { - // Have to work down the previous chunks to find the first item - unsigned int items = numItems - currEntry; - STACK_CHUNK *psCurr; - - for(psCurr = psCurrChunk->psPrev; psCurr != NULL; psCurr = psCurr->psPrev) - { - if (items <= psCurr->size) - { - // found the first item - currEntry = psCurr->size - items; - psCurrChunk = psCurr; - break; - } - - items -= psCurr->size; - } - - if (!psCurr) - { - debug( LOG_ERROR, "stackReduce: not enough parameters on stack" ); - ASSERT( false, "stackReduce: not enough parameters on stack" ); - return false; - } + currEntry--; } - + return true; } @@ -1046,7 +1073,7 @@ static inline BOOL stackReduce(unsigned int numItems) /* Reset the stack to an empty state */ void stackReset(void) { - ASSERT(stackEmpty(), + ASSERT( ((psCurrChunk == psStackBase) && (currEntry == 0)), "stackReset: stack is not empty" ); psCurrChunk = psStackBase; diff --git a/lib/script/stack.h b/lib/script/stack.h index 6e2ea37c5..60adbf7b1 100644 --- a/lib/script/stack.h +++ b/lib/script/stack.h @@ -37,13 +37,16 @@ extern BOOL stackInitialise(void); extern void stackShutDown(void); /* Push a value onto the stack */ -extern BOOL stackPush(INTERP_VAL *psVal); +extern BOOL stackPush(INTERP_VAL *psVal); /* Pop a value off the stack */ -extern BOOL stackPop(INTERP_VAL *psVal); +extern BOOL stackPop(INTERP_VAL *psVal); + +/* Return pointer to the top value without poping it */ +extern BOOL stackPeekTop(INTERP_VAL **ppsVal); /* Pop a value off the stack, checking that the type matches what is passed in */ -extern BOOL stackPopType(INTERP_VAL *psVal); +extern BOOL stackPopType(INTERP_VAL *psVal); /* Look at a value on the stack without removing it. * index is how far down the stack to look.