|
|
@@ -386,6 +386,10 @@ int asCReader::ReadInner()
|
|
|
func = ReadFunction(isNew, false, false);
|
|
|
if( func )
|
|
|
{
|
|
|
+ // All the global functions were already loaded while loading the scriptFunctions, here
|
|
|
+ // we're just re-reading the refernces to know which goes into the globalFunctions array
|
|
|
+ asASSERT( !isNew );
|
|
|
+
|
|
|
module->globalFunctions.Put(func);
|
|
|
func->AddRef();
|
|
|
}
|
|
|
@@ -486,6 +490,12 @@ int asCReader::ReadInner()
|
|
|
engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
|
|
|
Error(TXT_INVALID_BYTECODE_d);
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // If the callback said this template instance won't be garbage collected then remove the flag
|
|
|
+ if( dontGarbageCollect )
|
|
|
+ usedTypes[i]->flags &= ~asOBJ_GC;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
engine->deferValidationOfTemplateTypes = false;
|
|
|
@@ -544,6 +554,12 @@ void asCReader::ReadUsedFunctions()
|
|
|
asUINT count;
|
|
|
count = ReadEncodedUInt();
|
|
|
usedFunctions.SetLength(count);
|
|
|
+ if( usedFunctions.GetLength() != count )
|
|
|
+ {
|
|
|
+ // Out of memory
|
|
|
+ error = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
memset(usedFunctions.AddressOf(), 0, sizeof(asCScriptFunction *)*count);
|
|
|
|
|
|
for( asUINT n = 0; n < usedFunctions.GetLength(); n++ )
|
|
|
@@ -652,6 +668,12 @@ void asCReader::ReadFunctionSignature(asCScriptFunction *func)
|
|
|
}
|
|
|
|
|
|
func->inOutFlags.SetLength(func->parameterTypes.GetLength());
|
|
|
+ if( func->inOutFlags.GetLength() != func->parameterTypes.GetLength() )
|
|
|
+ {
|
|
|
+ // Out of memory
|
|
|
+ error = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
memset(func->inOutFlags.AddressOf(), 0, sizeof(asETypeModifiers)*func->inOutFlags.GetLength());
|
|
|
count = ReadEncodedUInt();
|
|
|
if( count > func->parameterTypes.GetLength() )
|
|
|
@@ -679,6 +701,12 @@ void asCReader::ReadFunctionSignature(asCScriptFunction *func)
|
|
|
if( count )
|
|
|
{
|
|
|
func->defaultArgs.SetLength(func->parameterTypes.GetLength());
|
|
|
+ if( func->defaultArgs.GetLength() != func->parameterTypes.GetLength() )
|
|
|
+ {
|
|
|
+ // Out of memory
|
|
|
+ error = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
memset(func->defaultArgs.AddressOf(), 0, sizeof(asCString*)*func->defaultArgs.GetLength());
|
|
|
for( i = 0; i < count; i++ )
|
|
|
{
|
|
|
@@ -740,7 +768,7 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
|
|
|
|
|
|
// Load the new function
|
|
|
isNew = true;
|
|
|
- asCScriptFunction *func = asNEW(asCScriptFunction)(engine,module,asFUNC_DUMMY);
|
|
|
+ asCScriptFunction *func = asNEW(asCScriptFunction)(engine,0,asFUNC_DUMMY);
|
|
|
if( func == 0 )
|
|
|
{
|
|
|
// Out of memory
|
|
|
@@ -763,6 +791,13 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
|
|
|
if( func->funcType == asFUNC_SCRIPT )
|
|
|
{
|
|
|
func->AllocateScriptFunctionData();
|
|
|
+ if( func->scriptData == 0 )
|
|
|
+ {
|
|
|
+ // Out of memory
|
|
|
+ error = true;
|
|
|
+ asDELETE(func, asCScriptFunction);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
if( addToGC && !addToModule )
|
|
|
engine->gc.AddScriptObjectToGC(func, &engine->functionBehaviours);
|
|
|
@@ -801,12 +836,26 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
|
|
|
{
|
|
|
length = ReadEncodedUInt();
|
|
|
func->scriptData->lineNumbers.SetLength(length);
|
|
|
+ if( int(func->scriptData->lineNumbers.GetLength()) != length )
|
|
|
+ {
|
|
|
+ // Out of memory
|
|
|
+ error = true;
|
|
|
+ asDELETE(func, asCScriptFunction);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
for( i = 0; i < length; ++i )
|
|
|
func->scriptData->lineNumbers[i] = ReadEncodedUInt();
|
|
|
|
|
|
// Read the array of script sections
|
|
|
length = ReadEncodedUInt();
|
|
|
func->scriptData->sectionIdxs.SetLength(length);
|
|
|
+ if( int(func->scriptData->sectionIdxs.GetLength()) != length )
|
|
|
+ {
|
|
|
+ // Out of memory
|
|
|
+ error = true;
|
|
|
+ asDELETE(func, asCScriptFunction);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
for( i = 0; i < length; ++i )
|
|
|
{
|
|
|
if( (i & 1) == 0 )
|
|
|
@@ -820,8 +869,6 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- ReadData(&func->isShared, 1);
|
|
|
-
|
|
|
// Read the variable information
|
|
|
if( !noDebugInfo )
|
|
|
{
|
|
|
@@ -846,7 +893,10 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- ReadData(&func->dontCleanUpOnException, 1);
|
|
|
+ char bits;
|
|
|
+ ReadData(&bits, 1);
|
|
|
+ func->isShared = bits & 1 ? true : false;
|
|
|
+ func->dontCleanUpOnException = bits & 2 ? true : false;
|
|
|
|
|
|
// Read script section name
|
|
|
if( !noDebugInfo )
|
|
|
@@ -856,6 +906,21 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
|
|
|
func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(name.AddressOf());
|
|
|
func->scriptData->declaredAt = ReadEncodedUInt();
|
|
|
}
|
|
|
+
|
|
|
+ // Read parameter names
|
|
|
+ if( !noDebugInfo )
|
|
|
+ {
|
|
|
+ asUINT count = asUINT(ReadEncodedUInt64());
|
|
|
+ if( count > func->parameterTypes.GetLength() )
|
|
|
+ {
|
|
|
+ error = true;
|
|
|
+ asDELETE(func, asCScriptFunction);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ func->parameterNames.SetLength(count);
|
|
|
+ for( asUINT n = 0; n < count; n++ )
|
|
|
+ ReadString(&func->parameterNames[n]);
|
|
|
+ }
|
|
|
}
|
|
|
else if( func->funcType == asFUNC_VIRTUAL || func->funcType == asFUNC_INTERFACE )
|
|
|
{
|
|
|
@@ -866,6 +931,7 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
|
|
|
{
|
|
|
// The refCount is already 1
|
|
|
module->scriptFunctions.PushLast(func);
|
|
|
+ func->module = module;
|
|
|
}
|
|
|
if( addToEngine )
|
|
|
{
|
|
|
@@ -1449,21 +1515,17 @@ void asCReader::ReadGlobalProperty()
|
|
|
asCGlobalProperty *prop = module->AllocateGlobalProperty(name.AddressOf(), type, nameSpace);
|
|
|
|
|
|
// Read the initialization function
|
|
|
- bool f;
|
|
|
- ReadData(&f, 1);
|
|
|
- if( f )
|
|
|
+ bool isNew;
|
|
|
+ // Do not add the function to the GC at this time. It will
|
|
|
+ // only be added to the GC when the module releases the property
|
|
|
+ asCScriptFunction *func = ReadFunction(isNew, false, true, false);
|
|
|
+ if( func )
|
|
|
{
|
|
|
- bool isNew;
|
|
|
- // Do not add the function to the GC at this time. It will
|
|
|
- // only be added to the GC when the module releases the property
|
|
|
- asCScriptFunction *func = ReadFunction(isNew, false, true, false);
|
|
|
- if( func )
|
|
|
- {
|
|
|
- prop->SetInitFunc(func);
|
|
|
- func->Release();
|
|
|
- }
|
|
|
- else
|
|
|
- Error(TXT_INVALID_BYTECODE_d);
|
|
|
+ // Make sure the function knows it is owned by the module
|
|
|
+ func->module = module;
|
|
|
+
|
|
|
+ prop->SetInitFunc(func);
|
|
|
+ func->Release();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1484,36 +1546,36 @@ void asCReader::ReadObjectProperty(asCObjectType *ot)
|
|
|
|
|
|
void asCReader::ReadDataType(asCDataType *dt)
|
|
|
{
|
|
|
- eTokenType tokenType;
|
|
|
-
|
|
|
- tokenType = (eTokenType)ReadEncodedUInt();
|
|
|
- if( tokenType == 0 )
|
|
|
+ // Check if this is a previously used type
|
|
|
+ asUINT n = ReadEncodedUInt();
|
|
|
+ if( n != 0 )
|
|
|
{
|
|
|
// Get the datatype from the cache
|
|
|
- asUINT n = ReadEncodedUInt();
|
|
|
- *dt = savedDataTypes[n];
|
|
|
+ *dt = savedDataTypes[n-1];
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ // Read the type definition
|
|
|
+ eTokenType tokenType = (eTokenType)ReadEncodedUInt();
|
|
|
+
|
|
|
// Reserve a spot in the savedDataTypes
|
|
|
size_t saveSlot = savedDataTypes.GetLength();
|
|
|
savedDataTypes.PushLast(asCDataType());
|
|
|
|
|
|
// Read the datatype for the first time
|
|
|
asCObjectType *objType = 0;
|
|
|
- bool isObjectHandle = false;
|
|
|
- bool isReadOnly = false;
|
|
|
- bool isHandleToConst = false;
|
|
|
- bool isReference = false;
|
|
|
-
|
|
|
if( tokenType == ttIdentifier )
|
|
|
- {
|
|
|
objType = ReadObjectType();
|
|
|
- ReadData(&isObjectHandle, 1);
|
|
|
- ReadData(&isHandleToConst, 1);
|
|
|
- }
|
|
|
- ReadData(&isReference, 1);
|
|
|
- ReadData(&isReadOnly, 1);
|
|
|
+
|
|
|
+ struct
|
|
|
+ {
|
|
|
+ char isObjectHandle :1;
|
|
|
+ char isHandleToConst:1;
|
|
|
+ char isReference :1;
|
|
|
+ char isReadOnly :1;
|
|
|
+ } bits = {0};
|
|
|
+ asASSERT( sizeof(bits) == 1 );
|
|
|
+ ReadData(&bits, 1);
|
|
|
|
|
|
asCScriptFunction *funcDef = 0;
|
|
|
if( tokenType == ttIdentifier && objType && objType->name == "_builtin_function_" )
|
|
|
@@ -1555,16 +1617,16 @@ void asCReader::ReadDataType(asCDataType *dt)
|
|
|
*dt = asCDataType::CreateObject(objType, false);
|
|
|
else
|
|
|
*dt = asCDataType::CreatePrimitive(tokenType, false);
|
|
|
- if( isObjectHandle )
|
|
|
+ if( bits.isObjectHandle )
|
|
|
{
|
|
|
- dt->MakeReadOnly(isHandleToConst);
|
|
|
+ dt->MakeReadOnly(bits.isHandleToConst ? true : false);
|
|
|
|
|
|
// Here we must allow a scoped type to be a handle
|
|
|
// e.g. if the datatype is for a system function
|
|
|
dt->MakeHandle(true, true);
|
|
|
}
|
|
|
- dt->MakeReadOnly(isReadOnly);
|
|
|
- dt->MakeReference(isReference);
|
|
|
+ dt->MakeReadOnly(bits.isReadOnly ? true : false);
|
|
|
+ dt->MakeReference(bits.isReference ? true : false);
|
|
|
|
|
|
// Update the previously saved slot
|
|
|
savedDataTypes[saveSlot] = *dt;
|
|
|
@@ -2080,9 +2142,10 @@ void asCReader::TranslateFunction(asCScriptFunction *func)
|
|
|
// Pre-compute the size of each instruction in order to translate jump offsets
|
|
|
asUINT n;
|
|
|
asDWORD *bc = func->scriptData->byteCode.AddressOf();
|
|
|
- asCArray<asUINT> bcSizes(func->scriptData->byteCode.GetLength());
|
|
|
- asCArray<asUINT> instructionNbrToPos(func->scriptData->byteCode.GetLength());
|
|
|
- for( n = 0; n < func->scriptData->byteCode.GetLength(); )
|
|
|
+ asUINT bcLength = (asUINT)func->scriptData->byteCode.GetLength();
|
|
|
+ asCArray<asUINT> bcSizes(bcLength);
|
|
|
+ asCArray<asUINT> instructionNbrToPos(bcLength);
|
|
|
+ for( n = 0; n < bcLength; )
|
|
|
{
|
|
|
int c = *(asBYTE*)&bc[n];
|
|
|
asUINT size = asBCTypeSize[asBCInfo[c].type];
|
|
|
@@ -2097,7 +2160,7 @@ void asCReader::TranslateFunction(asCScriptFunction *func)
|
|
|
}
|
|
|
|
|
|
asUINT bcNum = 0;
|
|
|
- for( n = 0; n < func->scriptData->byteCode.GetLength(); bcNum++ )
|
|
|
+ for( n = 0; n < bcLength; bcNum++ )
|
|
|
{
|
|
|
int c = *(asBYTE*)&bc[n];
|
|
|
if( c == asBC_REFCPY ||
|
|
|
@@ -2137,7 +2200,7 @@ void asCReader::TranslateFunction(asCScriptFunction *func)
|
|
|
{
|
|
|
// List patterns have a different way of adjusting the offsets
|
|
|
SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
|
|
|
- *(((short*)&bc[n])+2) = (short)listAdj->AdjustOffset(*(((short*)&bc[n])+2), ot);
|
|
|
+ *(((short*)&bc[n])+2) = (short)listAdj->AdjustOffset(*(((short*)&bc[n])+2));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -2308,7 +2371,7 @@ void asCReader::TranslateFunction(asCScriptFunction *func)
|
|
|
|
|
|
// The adjuster also needs to know the list type so it can know the type of the elements
|
|
|
asCObjectType *ot = func->GetObjectTypeOfLocalVar(asBC_SWORDARG0(&bc[n]));
|
|
|
- listAdjusters.PushLast(asNEW(SListAdjuster)(&bc[n], ot));
|
|
|
+ listAdjusters.PushLast(asNEW(SListAdjuster)(this, &bc[n], ot));
|
|
|
}
|
|
|
else if( c == asBC_FREE )
|
|
|
{
|
|
|
@@ -2319,6 +2382,12 @@ void asCReader::TranslateFunction(asCScriptFunction *func)
|
|
|
asCObjectType *ot = *(asCObjectType**)pot;
|
|
|
if( ot && (ot->flags & asOBJ_LIST_PATTERN) )
|
|
|
{
|
|
|
+ if( listAdjusters.GetLength() == 0 )
|
|
|
+ {
|
|
|
+ Error(TXT_INVALID_BYTECODE_d);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
// Finalize the adjustment of the list buffer that was initiated with asBC_AllocMem
|
|
|
SListAdjuster *list = listAdjusters.PopLast();
|
|
|
list->AdjustAllocMem();
|
|
|
@@ -2329,7 +2398,7 @@ void asCReader::TranslateFunction(asCScriptFunction *func)
|
|
|
{
|
|
|
// Adjust the offset in the list where the size is informed
|
|
|
SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
|
|
|
- bc[n+1] = listAdj->AdjustOffset(bc[n+1], listAdj->patternType);
|
|
|
+ bc[n+1] = listAdj->AdjustOffset(bc[n+1]);
|
|
|
|
|
|
// Inform the list adjuster how many values will be repeated
|
|
|
listAdj->SetRepeatCount(bc[n+2]);
|
|
|
@@ -2338,13 +2407,13 @@ void asCReader::TranslateFunction(asCScriptFunction *func)
|
|
|
{
|
|
|
// Adjust the offset in the list where the size is informed
|
|
|
SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
|
|
|
- bc[n+1] = listAdj->AdjustOffset(bc[n+1], listAdj->patternType);
|
|
|
+ bc[n+1] = listAdj->AdjustOffset(bc[n+1]);
|
|
|
}
|
|
|
else if( c == asBC_SetListType )
|
|
|
{
|
|
|
// Adjust the offset in the list where the typeid is informed
|
|
|
SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
|
|
|
- bc[n+1] = listAdj->AdjustOffset(bc[n+1], listAdj->patternType);
|
|
|
+ bc[n+1] = listAdj->AdjustOffset(bc[n+1]);
|
|
|
|
|
|
// Translate the type id
|
|
|
bc[n+2] = FindTypeId(bc[n+2]);
|
|
|
@@ -2361,7 +2430,7 @@ void asCReader::TranslateFunction(asCScriptFunction *func)
|
|
|
|
|
|
// Adjust all variable positions in the bytecode
|
|
|
bc = func->scriptData->byteCode.AddressOf();
|
|
|
- for( n = 0; n < func->scriptData->byteCode.GetLength(); )
|
|
|
+ for( n = 0; n < bcLength; )
|
|
|
{
|
|
|
int c = *(asBYTE*)&bc[n];
|
|
|
switch( asBCInfo[c].type )
|
|
|
@@ -2430,7 +2499,7 @@ void asCReader::TranslateFunction(asCScriptFunction *func)
|
|
|
// This will also make the AdjustGetOffset() function quicker as it can
|
|
|
// receive the called function directly instead of having to search for it.
|
|
|
bc = func->scriptData->byteCode.AddressOf();
|
|
|
- for( n = 0; n < func->scriptData->byteCode.GetLength(); )
|
|
|
+ for( n = 0; n < bcLength; )
|
|
|
{
|
|
|
int c = *(asBYTE*)&bc[n];
|
|
|
|
|
|
@@ -2461,8 +2530,8 @@ void asCReader::TranslateFunction(asCScriptFunction *func)
|
|
|
CalculateStackNeeded(func);
|
|
|
}
|
|
|
|
|
|
-asCReader::SListAdjuster::SListAdjuster(asDWORD *bc, asCObjectType *listType) :
|
|
|
- allocMemBC(bc), maxOffset(0), patternType(listType), repeatCount(0), lastOffset(-1), nextTypeId(-1)
|
|
|
+asCReader::SListAdjuster::SListAdjuster(asCReader *rd, asDWORD *bc, asCObjectType *listType) :
|
|
|
+ reader(rd), allocMemBC(bc), maxOffset(0), patternType(listType), repeatCount(0), lastOffset(-1), nextOffset(0), nextTypeId(-1)
|
|
|
{
|
|
|
asASSERT( patternType && (patternType->flags & asOBJ_LIST_PATTERN) );
|
|
|
|
|
|
@@ -2472,13 +2541,13 @@ asCReader::SListAdjuster::SListAdjuster(asDWORD *bc, asCObjectType *listType) :
|
|
|
patternNode = node->next;
|
|
|
}
|
|
|
|
|
|
-int asCReader::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatternType)
|
|
|
+int asCReader::SListAdjuster::AdjustOffset(int offset)
|
|
|
{
|
|
|
- // TODO: cleanup: The listPatternType parameter is not needed
|
|
|
- asASSERT( listPatternType == patternType );
|
|
|
- UNUSED_VAR( listPatternType );
|
|
|
-
|
|
|
- asASSERT( offset >= lastOffset );
|
|
|
+ if( offset < lastOffset )
|
|
|
+ {
|
|
|
+ reader->Error(TXT_INVALID_BYTECODE_d);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
// If it is the same offset being accessed again, just return the same adjusted value
|
|
|
if( lastOffset == offset )
|
|
|
@@ -2488,7 +2557,7 @@ int asCReader::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter
|
|
|
lastAdjustedOffset = maxOffset;
|
|
|
|
|
|
// What is being expected at this position?
|
|
|
- if( patternNode->type == asLPT_REPEAT )
|
|
|
+ if( patternNode->type == asLPT_REPEAT || patternNode->type == asLPT_REPEAT_SAME )
|
|
|
{
|
|
|
// Align the offset to 4 bytes boundary
|
|
|
if( maxOffset & 0x3 )
|
|
|
@@ -2499,6 +2568,7 @@ int asCReader::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter
|
|
|
|
|
|
// Don't move the patternNode yet because the caller must make a call to SetRepeatCount too
|
|
|
maxOffset += 4;
|
|
|
+ nextOffset = offset+1;
|
|
|
return lastAdjustedOffset;
|
|
|
}
|
|
|
else if( patternNode->type == asLPT_TYPE )
|
|
|
@@ -2513,7 +2583,7 @@ int asCReader::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter
|
|
|
|
|
|
asCDataType dt = patternType->engine->GetDataTypeFromTypeId(nextTypeId);
|
|
|
asUINT size;
|
|
|
- if( dt.IsObjectHandle() )
|
|
|
+ if( dt.IsObjectHandle() || (dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_REF)) )
|
|
|
size = AS_PTR_SIZE*4;
|
|
|
else
|
|
|
size = dt.GetSizeInMemoryBytes();
|
|
|
@@ -2532,6 +2602,7 @@ int asCReader::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter
|
|
|
nextTypeId = -1;
|
|
|
|
|
|
maxOffset += size;
|
|
|
+ nextOffset = offset+1;
|
|
|
return lastAdjustedOffset;
|
|
|
}
|
|
|
else
|
|
|
@@ -2545,36 +2616,40 @@ int asCReader::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter
|
|
|
|
|
|
// The first adjustment is for the typeId
|
|
|
maxOffset += 4;
|
|
|
-
|
|
|
+ nextOffset = offset+1;
|
|
|
return lastAdjustedOffset;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if( repeatCount > 0 )
|
|
|
- repeatCount--;
|
|
|
-
|
|
|
// Determine the size of the element
|
|
|
asUINT size;
|
|
|
asCDataType dt = reinterpret_cast<asSListPatternDataTypeNode*>(patternNode)->dataType;
|
|
|
- if( dt.IsObjectHandle() )
|
|
|
+ if( dt.IsObjectHandle() || (dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_REF)) )
|
|
|
size = AS_PTR_SIZE*4;
|
|
|
else
|
|
|
size = dt.GetSizeInMemoryBytes();
|
|
|
|
|
|
- // Align the offset to 4 bytes boundary
|
|
|
- if( size >= 4 && (maxOffset & 0x3) )
|
|
|
+ // If values are skipped, the offset needs to be incremented
|
|
|
+ while( nextOffset <= offset )
|
|
|
{
|
|
|
- maxOffset += 4 - (maxOffset & 0x3);
|
|
|
+ if( repeatCount > 0 )
|
|
|
+ repeatCount--;
|
|
|
+
|
|
|
+ // Align the offset to 4 bytes boundary
|
|
|
+ if( size >= 4 && (maxOffset & 0x3) )
|
|
|
+ maxOffset += 4 - (maxOffset & 0x3);
|
|
|
+
|
|
|
lastAdjustedOffset = maxOffset;
|
|
|
+ nextOffset += 1;
|
|
|
+ maxOffset += size;
|
|
|
}
|
|
|
|
|
|
- maxOffset += size;
|
|
|
-
|
|
|
// Only move the patternNode if we're not expecting any more repeated entries
|
|
|
if( repeatCount == 0 )
|
|
|
patternNode = patternNode->next;
|
|
|
|
|
|
+ nextOffset = offset+1;
|
|
|
return lastAdjustedOffset;
|
|
|
}
|
|
|
}
|
|
|
@@ -2589,10 +2664,16 @@ int asCReader::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter
|
|
|
patternNode = patternNode->next;
|
|
|
|
|
|
lastOffset--;
|
|
|
- return AdjustOffset(offset, listPatternType);
|
|
|
+ return AdjustOffset(offset);
|
|
|
}
|
|
|
else if( patternNode->type == asLPT_END )
|
|
|
{
|
|
|
+ if( stack.GetLength() == 0 )
|
|
|
+ {
|
|
|
+ reader->Error(TXT_INVALID_BYTECODE_d);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
SInfo info = stack.PopLast();
|
|
|
repeatCount = info.repeatCount;
|
|
|
if( repeatCount )
|
|
|
@@ -2601,21 +2682,22 @@ int asCReader::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter
|
|
|
patternNode = patternNode->next;
|
|
|
|
|
|
lastOffset--;
|
|
|
- return AdjustOffset(offset, listPatternType);
|
|
|
+ return AdjustOffset(offset);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// Something is wrong with the pattern list declaration
|
|
|
- asASSERT( false );
|
|
|
+ reader->Error(TXT_INVALID_BYTECODE_d);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ UNREACHABLE_RETURN;
|
|
|
}
|
|
|
|
|
|
void asCReader::SListAdjuster::SetRepeatCount(asUINT rc)
|
|
|
{
|
|
|
// Make sure the list is expecting a repeat at this location
|
|
|
- asASSERT( patternNode->type == asLPT_REPEAT );
|
|
|
+ asASSERT( patternNode->type == asLPT_REPEAT || patternNode->type == asLPT_REPEAT_SAME );
|
|
|
|
|
|
// Now move to the next patternNode
|
|
|
patternNode = patternNode->next;
|
|
|
@@ -3392,8 +3474,6 @@ void asCWriter::WriteFunction(asCScriptFunction* func)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- WriteData(&func->isShared, 1);
|
|
|
-
|
|
|
// Write the variable information
|
|
|
if( !stripDebugInfo )
|
|
|
{
|
|
|
@@ -3409,7 +3489,10 @@ void asCWriter::WriteFunction(asCScriptFunction* func)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- WriteData(&func->dontCleanUpOnException, 1);
|
|
|
+ char bits = 0;
|
|
|
+ bits += func->isShared ? 1 : 0;
|
|
|
+ bits += func->dontCleanUpOnException ? 2 : 0;
|
|
|
+ WriteData(&bits,1);
|
|
|
|
|
|
// Store script section name
|
|
|
if( !stripDebugInfo )
|
|
|
@@ -3423,6 +3506,15 @@ void asCWriter::WriteFunction(asCScriptFunction* func)
|
|
|
}
|
|
|
WriteEncodedInt64(func->scriptData->declaredAt);
|
|
|
}
|
|
|
+
|
|
|
+ // Store the parameter names
|
|
|
+ if( !stripDebugInfo )
|
|
|
+ {
|
|
|
+ asUINT count = asUINT(func->parameterNames.GetLength());
|
|
|
+ WriteEncodedInt64(count);
|
|
|
+ for( asUINT n = 0; n < count; n++ )
|
|
|
+ WriteString(&func->parameterNames[n]);
|
|
|
+ }
|
|
|
}
|
|
|
else if( func->funcType == asFUNC_VIRTUAL || func->funcType == asFUNC_INTERFACE )
|
|
|
{
|
|
|
@@ -3487,6 +3579,7 @@ void asCWriter::WriteObjectTypeDeclaration(asCObjectType *ot, int phase)
|
|
|
int size = (asUINT)ot->interfaces.GetLength();
|
|
|
WriteEncodedInt64(size);
|
|
|
asUINT n;
|
|
|
+ asASSERT( ot->interfaces.GetLength() == ot->interfaceVFTOffsets.GetLength() );
|
|
|
for( n = 0; n < ot->interfaces.GetLength(); n++ )
|
|
|
{
|
|
|
WriteObjectType(ot->interfaces[n]);
|
|
|
@@ -3655,18 +3748,7 @@ void asCWriter::WriteGlobalProperty(asCGlobalProperty* prop)
|
|
|
WriteDataType(&prop->type);
|
|
|
|
|
|
// Store the initialization function
|
|
|
- if( prop->GetInitFunc() )
|
|
|
- {
|
|
|
- bool f = true;
|
|
|
- WriteData(&f, 1);
|
|
|
-
|
|
|
- WriteFunction(prop->GetInitFunc());
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- bool f = false;
|
|
|
- WriteData(&f, 1);
|
|
|
- }
|
|
|
+ WriteFunction(prop->GetInitFunc());
|
|
|
}
|
|
|
|
|
|
void asCWriter::WriteObjectProperty(asCObjectProperty* prop)
|
|
|
@@ -3683,31 +3765,36 @@ void asCWriter::WriteDataType(const asCDataType *dt)
|
|
|
{
|
|
|
if( *dt == savedDataTypes[n] )
|
|
|
{
|
|
|
- asUINT c = 0;
|
|
|
- WriteEncodedInt64(c);
|
|
|
- WriteEncodedInt64(n);
|
|
|
+ WriteEncodedInt64(n+1);
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Indicate a new type with a null byte
|
|
|
+ asUINT c = 0;
|
|
|
+ WriteEncodedInt64(c);
|
|
|
+
|
|
|
// Save the new datatype
|
|
|
savedDataTypes.PushLast(*dt);
|
|
|
|
|
|
- bool b;
|
|
|
int t = dt->GetTokenType();
|
|
|
WriteEncodedInt64(t);
|
|
|
if( t == ttIdentifier )
|
|
|
- {
|
|
|
WriteObjectType(dt->GetObjectType());
|
|
|
- b = dt->IsObjectHandle();
|
|
|
- WriteData(&b, 1);
|
|
|
- b = dt->IsHandleToConst();
|
|
|
- WriteData(&b, 1);
|
|
|
- }
|
|
|
- b = dt->IsReference();
|
|
|
- WriteData(&b, 1);
|
|
|
- b = dt->IsReadOnly();
|
|
|
- WriteData(&b, 1);
|
|
|
+
|
|
|
+ struct
|
|
|
+ {
|
|
|
+ char isObjectHandle :1;
|
|
|
+ char isHandleToConst:1;
|
|
|
+ char isReference :1;
|
|
|
+ char isReadOnly :1;
|
|
|
+ } bits = {0};
|
|
|
+
|
|
|
+ bits.isObjectHandle = dt->IsObjectHandle();
|
|
|
+ bits.isHandleToConst = dt->IsHandleToConst();
|
|
|
+ bits.isReference = dt->IsReference();
|
|
|
+ bits.isReadOnly = dt->IsReadOnly();
|
|
|
+ WriteData(&bits, 1);
|
|
|
|
|
|
if( t == ttIdentifier && dt->GetObjectType()->name == "_builtin_function_" )
|
|
|
{
|
|
|
@@ -4476,7 +4563,7 @@ void asCWriter::WriteByteCode(asCScriptFunction *func)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-asCWriter::SListAdjuster::SListAdjuster(asCObjectType *ot) : patternType(ot), repeatCount(0), entries(0), lastOffset(-1), nextTypeId(-1)
|
|
|
+asCWriter::SListAdjuster::SListAdjuster(asCObjectType *ot) : patternType(ot), repeatCount(0), entries(0), lastOffset(-1), nextOffset(0), nextTypeId(-1)
|
|
|
{
|
|
|
asASSERT( ot && (ot->flags & asOBJ_LIST_PATTERN) );
|
|
|
|
|
|
@@ -4498,12 +4585,16 @@ int asCWriter::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter
|
|
|
if( offset == lastOffset )
|
|
|
return entries-1;
|
|
|
|
|
|
+ asASSERT( offset >= nextOffset );
|
|
|
+
|
|
|
+ // Update last offset for next call
|
|
|
lastOffset = offset;
|
|
|
|
|
|
// What is being expected at this position?
|
|
|
- if( patternNode->type == asLPT_REPEAT )
|
|
|
+ if( patternNode->type == asLPT_REPEAT || patternNode->type == asLPT_REPEAT_SAME )
|
|
|
{
|
|
|
// Don't move the patternNode yet because the caller must make a call to SetRepeatCount too
|
|
|
+ nextOffset = offset + 4;
|
|
|
return entries++;
|
|
|
}
|
|
|
else if( patternNode->type == asLPT_TYPE )
|
|
|
@@ -4516,6 +4607,8 @@ int asCWriter::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter
|
|
|
// we can move to the next node
|
|
|
if( nextTypeId != -1 )
|
|
|
{
|
|
|
+ nextOffset = offset + 4;
|
|
|
+
|
|
|
if( repeatCount > 0 )
|
|
|
repeatCount--;
|
|
|
|
|
|
@@ -4529,7 +4622,35 @@ int asCWriter::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter
|
|
|
else
|
|
|
{
|
|
|
if( repeatCount > 0 )
|
|
|
+ {
|
|
|
+ // Was any value skipped?
|
|
|
+ asUINT size;
|
|
|
+ if( dt.IsObjectHandle() || (dt.GetObjectType() && (dt.GetObjectType()->flags & asOBJ_REF)) )
|
|
|
+ size = AS_PTR_SIZE*4;
|
|
|
+ else
|
|
|
+ size = dt.GetSizeInMemoryBytes();
|
|
|
+
|
|
|
+ int count = 0;
|
|
|
+ while( nextOffset <= offset )
|
|
|
+ {
|
|
|
+ count++;
|
|
|
+ nextOffset += size;
|
|
|
+
|
|
|
+ // Align the offset on 4 byte boundaries
|
|
|
+ if( size >= 4 && (nextOffset & 0x3) )
|
|
|
+ nextOffset += 4 - (nextOffset & 0x3);
|
|
|
+ }
|
|
|
+
|
|
|
+ if( --count > 0 )
|
|
|
+ {
|
|
|
+ // Skip these values
|
|
|
+ repeatCount -= count;
|
|
|
+ entries += count;
|
|
|
+ }
|
|
|
+
|
|
|
+ nextOffset = offset + size;
|
|
|
repeatCount--;
|
|
|
+ }
|
|
|
|
|
|
// Only move the patternNode if we're not expecting any more repeated entries
|
|
|
if( repeatCount == 0 )
|
|
|
@@ -4575,7 +4696,7 @@ int asCWriter::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatter
|
|
|
void asCWriter::SListAdjuster::SetRepeatCount(asUINT rc)
|
|
|
{
|
|
|
// Make sure the list is expecting a repeat at this location
|
|
|
- asASSERT( patternNode->type == asLPT_REPEAT );
|
|
|
+ asASSERT( patternNode->type == asLPT_REPEAT || patternNode->type == asLPT_REPEAT_SAME );
|
|
|
|
|
|
// Now move to the next patternNode
|
|
|
patternNode = patternNode->next;
|