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
master
Dennis Schridde 2008-03-27 18:38:25 +00:00
parent 88fc127503
commit f888cc5b69
7 changed files with 160 additions and 185 deletions

View File

@ -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; i<psCode->psArrayInfo[arrayNum].dimensions; i++)
for(i=0; i<psCode->psArrayInfo[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])
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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