asCThreadLocalData *asCThreadManager::GetLocalData() { if( threadManager == 0 ) return 0; #ifndef AS_NO_THREADS #if defined AS_POSIX_THREADS asCThreadLocalData *tld = (asCThreadLocalData*)pthread_getspecific((pthread_key_t)threadManager->tlsKey); if( tld == 0 ) { tld = asNEW(asCThreadLocalData)(); pthread_setspecific((pthread_key_t)threadManager->tlsKey, tld); } #elif defined AS_WINDOWS_THREADS #if defined(_MSC_VER) && (WINAPI_FAMILY & WINAPI_FAMILY_PHONE_APP) if( tld == 0 ) tld = asNEW(asCThreadLocalData)(); #else asCThreadLocalData *tld = (asCThreadLocalData*)TlsGetValue((DWORD)threadManager->tlsKey); if( tld == 0 ) { tld = asNEW(asCThreadLocalData)(); TlsSetValue((DWORD)threadManager->tlsKey, tld); } #endif #endif return tld; #else if( threadManager->tld == 0 ) threadManager->tld = asNEW(asCThreadLocalData)(); return threadManager->tld; #endif }
asCThreadLocalData *asCThreadManager::GetLocalData() { if( threadManager == 0 ) return 0; #ifndef AS_NO_THREADS #if defined AS_POSIX_THREADS asPWORD id = (asPWORD)pthread_self(); #elif defined AS_WINDOWS_THREADS asPWORD id = (asPWORD)GetCurrentThreadId(); #endif ENTERCRITICALSECTION(threadManager->criticalSection); asCThreadLocalData *tld = threadManager->GetLocalData(id); if( tld == 0 ) { // Create a new tld tld = asNEW(asCThreadLocalData)(); if( tld ) threadManager->SetLocalData(id, tld); } LEAVECRITICALSECTION(threadManager->criticalSection); return tld; #else if( threadManager->tld == 0 ) threadManager->tld = asNEW(asCThreadLocalData)(); return threadManager->tld; #endif }
asILockableSharedBool *asCScriptObject::GetWeakRefFlag() const { // If the object's refCount has already reached zero then the object is already // about to be destroyed so it's ok to return null if the weakRefFlag doesn't already // exist if( (extra && extra->weakRefFlag) || hasRefCountReachedZero ) return extra->weakRefFlag; // Lock globally so no other thread can attempt // to create a shared bool at the same time. // TODO: runtime optimize: Instead of locking globally, it would be possible to have // a critical section per object type. This would reduce the // chances of two threads lock on the same critical section. asAcquireExclusiveLock(); // Make sure another thread didn't create the // flag while we waited for the lock if( !extra ) extra = asNEW(SExtra); if( !extra->weakRefFlag ) extra->weakRefFlag = asNEW(asCLockableSharedBool); asReleaseExclusiveLock(); return extra->weakRefFlag; }
// internal int asCModule::AddImportedFunction(int id, const char *name, const asCDataType &returnType, asCDataType *params, asETypeModifiers *inOutFlags, int paramCount, const asCString &moduleName) { asASSERT(id >= 0); // Store the function information asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, asFUNC_IMPORTED); func->name = name; func->id = id; func->returnType = returnType; for( int n = 0; n < paramCount; n++ ) { func->parameterTypes.PushLast(params[n]); func->inOutFlags.PushLast(inOutFlags[n]); } func->objectType = 0; sBindInfo *info = asNEW(sBindInfo); info->importedFunctionSignature = func; info->boundFunctionId = -1; info->importFromModule = moduleName; bindInformations.PushLast(info); // Add the info to the array in the engine engine->importedFunctions.PushLast(info); return 0; }
// internal int asCScriptFunction::ParseListPattern(asSListPatternNode *&target, const char *decl, asCScriptNode *listNodes) { asSListPatternNode *node = target; listNodes = listNodes->firstChild; while( listNodes ) { if( listNodes->nodeType == snIdentifier ) { node->next = asNEW(asSListPatternNode)(asLPT_REPEAT); node = node->next; } else if( listNodes->nodeType == snDataType ) { asCDataType dt; asCBuilder builder(engine, 0); asCScriptCode code; code.SetCode("", decl, 0, false); dt = builder.CreateDataTypeFromNode(listNodes, &code, engine->defaultNamespace, false, returnType.GetObjectType()); node->next = asNEW(asSListPatternDataTypeNode)(dt); node = node->next; } else if( listNodes->nodeType == snListPattern ) { node->next = asNEW(asSListPatternNode)(asLPT_START); node = node->next; // Recursively parse the child int r = ParseListPattern(node, decl, listNodes); if( r < 0 ) return r; node->next = asNEW(asSListPatternNode)(asLPT_END); node = node->next; } else { // Unexpected token in the list, the parser shouldn't have allowed asASSERT( false ); return -1; } listNodes = listNodes->next; } target = node; return 0; }
int asCVariableScope::DeclareVariable(const char *name, const asCDataType &type, int stackOffset) { // TODO: optimize: Improve linear search // See if the variable is already declared if( strcmp(name, "") != 0 ) { for( asUINT n = 0; n < variables.GetLength(); n++ ) { if( variables[n]->name == name ) return -1; } } sVariable *var = asNEW(sVariable); var->name = name; var->type = type; var->stackOffset = stackOffset; var->isInitialized = false; var->isPureConstant = false; // Parameters are initialized if( stackOffset <= 0 ) var->isInitialized = true; variables.PushLast(var); return 0; }
// internal int asCModule::AddImportedFunction(int id, const char *name, const asCDataType &returnType, asCDataType *params, asETypeModifiers *inOutFlags, int paramCount, int moduleNameStringID) { asASSERT(id >= 0); // Store the function information asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this); func->funcType = asFUNC_IMPORTED; func->name = name; func->id = id; func->returnType = returnType; for( int n = 0; n < paramCount; n++ ) { func->parameterTypes.PushLast(params[n]); func->inOutFlags.PushLast(inOutFlags[n]); } func->objectType = 0; importedFunctions.PushLast(func); sBindInfo info; info.importedFunction = -1; info.importFrom = moduleNameStringID; bindInformations.PushLast(info); return 0; }
// internal int asCModule::AddScriptFunction(int sectionIdx, int id, const char *name, const asCDataType &returnType, asCDataType *params, asETypeModifiers *inOutFlags, int paramCount, bool isInterface, asCObjectType *objType, bool isConstMethod, bool isGlobalFunction) { asASSERT(id >= 0); // Store the function information asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, isInterface ? asFUNC_INTERFACE : asFUNC_SCRIPT); func->name = name; func->id = id; func->returnType = returnType; func->scriptSectionIdx = sectionIdx; for( int n = 0; n < paramCount; n++ ) { func->parameterTypes.PushLast(params[n]); func->inOutFlags.PushLast(inOutFlags[n]); } func->objectType = objType; func->isReadOnly = isConstMethod; // The script function's refCount was initialized to 1 scriptFunctions.PushLast(func); engine->SetScriptFunction(func); // Compute the signature id if( objType ) func->ComputeSignatureId(); // Add reference if( isGlobalFunction ) { globalFunctions.PushLast(func); func->AddRef(); } return 0; }
// interface int asCModule::Build() { asASSERT( contextCount.get() == 0 ); // Only one thread may build at one time int r = engine->RequestBuild(); if( r < 0 ) return r; engine->PrepareEngine(); if( engine->configFailed ) { engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION); engine->BuildCompleted(); return asINVALID_CONFIGURATION; } InternalReset(); if( !builder ) { engine->BuildCompleted(); return asSUCCESS; } // Store the section names for( size_t n = 0; n < builder->scripts.GetLength(); n++ ) { asCString *sectionName = asNEW(asCString)(builder->scripts[n]->name); scriptSections.PushLast(sectionName); } // Compile the script r = builder->Build(); asDELETE(builder,asCBuilder); builder = 0; if( r < 0 ) { // Reset module again InternalReset(); isBuildWithoutErrors = false; engine->BuildCompleted(); return r; } isBuildWithoutErrors = true; JITCompile(); engine->PrepareEngine(); engine->BuildCompleted(); // Initialize global variables if( r >= 0 && engine->ep.initGlobalVarsAfterBuild ) r = ResetGlobalVars(); return r; }
// internal int asCScriptFunction::RegisterListPattern(const char *decl, asCScriptNode *listNodes) { if( listNodes == 0 ) return asINVALID_ARG; // Build the representation of the list pattern from the script nodes asSListPatternNode *node; listPattern = asNEW(asSListPatternNode)(asLPT_START); node = listPattern; // Recursively parse the child int r = ParseListPattern(node, decl, listNodes); node->next = asNEW(asSListPatternNode)(asLPT_END); return r; }
// interface int asCModule::AddScriptSection(const char *name, const char *code, size_t codeLength, int lineOffset) { if( !builder ) builder = asNEW(asCBuilder)(engine, this); builder->AddCode(name, code, (int)codeLength, lineOffset, (int)engine->GetScriptSectionNameIndex(name ? name : ""), engine->ep.copyScriptSections); return asSUCCESS; }
// internal void asCScriptFunction::AddVariable(asCString &name, asCDataType &type, int stackOffset) { asSScriptVariable *var = asNEW(asSScriptVariable); var->name = name; var->type = type; var->stackOffset = stackOffset; var->declaredAtProgramPos = 0; variables.PushLast(var); }
void asCScriptFunction::AllocateScriptFunctionData() { if( scriptData ) return; scriptData = asNEW(ScriptFunctionData); scriptData->stackNeeded = 0; scriptData->variableSpace = 0; scriptData->scriptSectionIdx = -1; scriptData->jitFunction = 0; }
asCGarbageCollector::asSMapNode_t *asCGarbageCollector::GetNode(void *obj, asSIntTypePair it) { asSMapNode_t *node; if( freeNodes.GetLength() ) node = freeNodes.PopLast(); else node = asNEW(asSMapNode_t); node->Init(obj, it); return node; }
// interface int asCModule::AddScriptSection(const char *name, const char *code, size_t codeLength, int lineOffset) { if( IsUsed() ) return asMODULE_IS_IN_USE; if( !builder ) builder = asNEW(asCBuilder)(engine, this); builder->AddCode(name, code, (int)codeLength, lineOffset, (int)builder->scripts.GetLength(), engine->ep.copyScriptSections); return asSUCCESS; }
// internal int asCModule::AddFuncDef(const char *name) { asCScriptFunction *func = asNEW(asCScriptFunction)(engine, 0, asFUNC_FUNCDEF); func->name = name; funcDefs.PushLast(func); engine->funcDefs.PushLast(func); func->id = engine->GetNextScriptFunctionId(); engine->SetScriptFunction(func); return (int)funcDefs.GetLength()-1; }
asCGarbageCollector::asSMapNode_t *asCGarbageCollector::GetNode(void *obj, asSIntTypePair it) { // This function will only be called within the critical section gcCollecting asASSERT(isProcessing); asSMapNode_t *node; if( freeNodes.GetLength() ) node = freeNodes.PopLast(); else node = asNEW(asSMapNode_t); node->Init(obj, it); return node; }
void asCOutputBuffer::Callback(asSMessageInfo *msg) { message_t *msgInfo = asNEW(message_t); if( msgInfo == 0 ) return; msgInfo->section = msg->section; msgInfo->row = msg->row; msgInfo->col = msg->col; msgInfo->type = msg->type; msgInfo->msg = msg->message; messages.PushLast(msgInfo); }
// internal void asCScriptFunction::AddVariable(asCString &name, asCDataType &type, int stackOffset) { asASSERT( scriptData ); asSScriptVariable *var = asNEW(asSScriptVariable); if( var == 0 ) { // Out of memory return; } var->name = name; var->type = type; var->stackOffset = stackOffset; var->declaredAtProgramPos = 0; scriptData->variables.PushLast(var); }
// internal asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &name, const asCDataType &dt, bool isPrivate) { asASSERT( flags & asOBJ_SCRIPT_OBJECT ); asASSERT( dt.CanBeInstanciated() ); asASSERT( !IsInterface() ); // Store the properties in the object type descriptor asCObjectProperty *prop = asNEW(asCObjectProperty); if( prop == 0 ) { // Out of memory return 0; } prop->name = name; prop->type = dt; prop->isPrivate = isPrivate; int propSize; if( dt.IsObject() ) { propSize = dt.GetSizeOnStackDWords()*4; if( !dt.IsObjectHandle() ) prop->type.MakeReference(true); } else propSize = dt.GetSizeInMemoryBytes(); // Add extra bytes so that the property will be properly aligned if( propSize == 2 && (size & 1) ) size += 1; if( propSize > 2 && (size & 3) ) size += 4 - (size & 3); prop->byteOffset = size; size += propSize; properties.PushLast(prop); // Make sure the struct holds a reference to the config group where the object is registered asCConfigGroup *group = engine->FindConfigGroupForObjectType(prop->type.GetObjectType()); if( group != 0 ) group->AddRef(); // Add reference to object types asCObjectType *type = prop->type.GetObjectType(); if( type ) type->AddRef(); return prop; }
asCScriptFunction *CreateDelegate(asCScriptFunction *func, void *obj) { if( func == 0 || obj == 0 ) { // TODO: delegate: Should set script exception return 0; } // Create an instance of a asCScriptFunction with the type asFUNC_DELEGATE // The delegate shouldn't have a function id and is not added to the engine->scriptFunctions asCScriptFunction *delegate = asNEW(asCScriptFunction)(static_cast<asCScriptEngine*>(func->GetEngine()), 0, asFUNC_DELEGATE); if( delegate ) delegate->MakeDelegate(func, obj); return delegate; }
// internal asCGlobalProperty *asCModule::AllocateGlobalProperty(const char *name, const asCDataType &dt) { asCGlobalProperty *prop = asNEW(asCGlobalProperty); prop->index = (int)scriptGlobals.GetLength(); prop->name = name; prop->type = dt; scriptGlobals.PushLast(prop); // Allocate the memory for this property if( dt.GetSizeOnStackDWords() > 2 ) { prop->SetAddressOfValue(asNEWARRAY(asDWORD, dt.GetSizeOnStackDWords())); prop->memoryAllocated = true; } return prop; }
asILockableSharedBool *asCScriptObject::GetWeakRefFlag() const { if( weakRefFlag ) return weakRefFlag; // Lock globally so no other thread can attempt // to create a shared bool at the same time. // TODO: runtime optimize: Instead of locking globally, it would be possible to have // a critical section per object type. This would reduce the // chances of two threads lock on the same critical section. asAcquireExclusiveLock(); // Make sure another thread didn't create the // flag while we waited for the lock if( !weakRefFlag ) weakRefFlag = asNEW(asCLockableSharedBool); asReleaseExclusiveLock(); return weakRefFlag; }
void asCThreadManager::Prepare() { // The critical section cannot be declared globally, as there is no // guarantee for the order in which global variables are initialized // or uninitialized. // For this reason it's not possible to prevent two threads from calling // AddRef at the same time, so there is a chance for a race condition here. // To avoid the race condition when the thread manager is first created, // the application must make sure to call the global asPrepareForMultiThread() // in the main thread before any other thread creates a script engine. if( threadManager == 0 ) threadManager = asNEW(asCThreadManager); else { ENTERCRITICALSECTION(threadManager->criticalSection); threadManager->refCount++; LEAVECRITICALSECTION(threadManager->criticalSection); } }
// internal int asCModule::AddConstantString(const char *str, size_t len) { // The str may contain null chars, so we cannot use strlen, or strcmp, or strcpy asCString *cstr = asNEW(asCString)(str, len); // TODO: optimize: Improve linear search // Has the string been registered before? for( size_t n = 0; n < stringConstants.GetLength(); n++ ) { if( *stringConstants[n] == *cstr ) { asDELETE(cstr,asCString); return (int)n; } } // No match was found, add the string stringConstants.PushLast(cstr); return (int)stringConstants.GetLength() - 1; }
void *asCScriptObject::SetUserData(void *data, asPWORD type) { // Lock globally so no other thread can attempt // to manipulate the extra data at the same time. // TODO: runtime optimize: Instead of locking globally, it would be possible to have // a critical section per object type. This would reduce the // chances of two threads lock on the same critical section. asAcquireExclusiveLock(); // Make sure another thread didn't create the // flag while we waited for the lock if( !extra ) extra = asNEW(SExtra); // It is not intended to store a lot of different types of userdata, // so a more complex structure like a associative map would just have // more overhead than a simple array. for( asUINT n = 0; n < extra->userData.GetLength(); n += 2 ) { if( extra->userData[n] == type ) { void *oldData = reinterpret_cast<void*>(extra->userData[n+1]); extra->userData[n+1] = reinterpret_cast<asPWORD>(data); asReleaseExclusiveLock(); return oldData; } } extra->userData.PushLast(type); extra->userData.PushLast(reinterpret_cast<asPWORD>(data)); asReleaseExclusiveLock(); return 0; }
int asCThreadManager::Prepare(asIThreadManager *externalThreadMgr) { // Don't allow an external thread manager if there // is already a thread manager defined if( externalThreadMgr && threadManager ) return asINVALID_ARG; // The critical section cannot be declared globally, as there is no // guarantee for the order in which global variables are initialized // or uninitialized. // For this reason it's not possible to prevent two threads from calling // AddRef at the same time, so there is a chance for a race condition here. // To avoid the race condition when the thread manager is first created, // the application must make sure to call the global asPrepareForMultiThread() // in the main thread before any other thread creates a script engine. if( threadManager == 0 && externalThreadMgr == 0 ) threadManager = asNEW(asCThreadManager); else { // If an application uses different dlls each dll will get it's own memory // space for global variables. If multiple dlls then uses AngelScript's // global thread support functions it is then best to share the thread // manager to make sure all dlls use the same critical section. if( externalThreadMgr ) threadManager = reinterpret_cast<asCThreadManager*>(externalThreadMgr); ENTERCRITICALSECTION(threadManager->criticalSection); threadManager->refCount++; LEAVECRITICALSECTION(threadManager->criticalSection); } // Success return 0; }
asCScriptFunction *asCRestore::ReadFunction(bool addToModule, bool addToEngine) { char c; READ_NUM(c); if( c == '\0' ) { // There is no function, so return a null pointer return 0; } if( c == 'r' ) { // This is a reference to a previously saved function int index; READ_NUM(index); return savedFunctions[index]; } // Load the new function asCScriptFunction *func = asNEW(asCScriptFunction)(engine,module,-1); savedFunctions.PushLast(func); int i, count; asCDataType dt; int num; ReadFunctionSignature(func); if( func->funcType == asFUNC_SCRIPT ) engine->gc.AddScriptObjectToGC(func, &engine->functionBehaviours); func->id = engine->GetNextScriptFunctionId(); READ_NUM(count); func->byteCode.Allocate(count, 0); ReadByteCode(func->byteCode.AddressOf(), count); func->byteCode.SetLength(count); READ_NUM(count); func->objVariablePos.Allocate(count, 0); func->objVariableTypes.Allocate(count, 0); for( i = 0; i < count; ++i ) { func->objVariableTypes.PushLast(ReadObjectType()); READ_NUM(num); func->objVariablePos.PushLast(num); } READ_NUM(func->stackNeeded); int length; READ_NUM(length); func->lineNumbers.SetLength(length); for( i = 0; i < length; ++i ) READ_NUM(func->lineNumbers[i]); READ_NUM(func->vfTableIdx); if( addToModule ) { // The refCount is already 1 module->scriptFunctions.PushLast(func); } if( addToEngine ) engine->SetScriptFunction(func); if( func->objectType ) func->ComputeSignatureId(); ReadGlobalVarPointers(func); return func; }
int asCRestore::Restore() { // Before starting the load, make sure that // any existing resources have been freed module->InternalReset(); unsigned long i, count; asCScriptFunction* func; // Read enums READ_NUM(count); module->enumTypes.Allocate(count, 0); for( i = 0; i < count; i++ ) { asCObjectType *ot = asNEW(asCObjectType)(engine); ReadObjectTypeDeclaration(ot, false); engine->classTypes.PushLast(ot); module->enumTypes.PushLast(ot); ot->AddRef(); ReadObjectTypeDeclaration(ot, true); } // structTypes[] // First restore the structure names, then the properties READ_NUM(count); module->classTypes.Allocate(count, 0); for( i = 0; i < count; ++i ) { asCObjectType *ot = asNEW(asCObjectType)(engine); ReadObjectTypeDeclaration(ot, false); engine->classTypes.PushLast(ot); module->classTypes.PushLast(ot); ot->AddRef(); // Add script classes to the GC if( (ot->GetFlags() & asOBJ_SCRIPT_OBJECT) && ot->GetSize() > 0 ) engine->gc.AddScriptObjectToGC(ot, &engine->objectTypeBehaviours); } // Read interface methods for( i = 0; i < module->classTypes.GetLength(); i++ ) { if( module->classTypes[i]->IsInterface() ) ReadObjectTypeDeclaration(module->classTypes[i], true); } module->ResolveInterfaceIds(); // Read class methods, properties, and behaviours for( i = 0; i < module->classTypes.GetLength(); ++i ) { if( !module->classTypes[i]->IsInterface() ) ReadObjectTypeDeclaration(module->classTypes[i], true); } // Read typedefs READ_NUM(count); module->typeDefs.Allocate(count, 0); for( i = 0; i < count; i++ ) { asCObjectType *ot = asNEW(asCObjectType)(engine); ReadObjectTypeDeclaration(ot, false); engine->classTypes.PushLast(ot); module->typeDefs.PushLast(ot); ot->AddRef(); ReadObjectTypeDeclaration(ot, true); } // scriptGlobals[] READ_NUM(count); module->scriptGlobals.Allocate(count, 0); for( i = 0; i < count; ++i ) { ReadGlobalProperty(); } // scriptFunctions[] READ_NUM(count); for( i = 0; i < count; ++i ) { func = ReadFunction(); } // globalFunctions[] READ_NUM(count); for( i = 0; i < count; ++i ) { func = ReadFunction(false, false); module->globalFunctions.PushLast(func); func->AddRef(); } // bindInformations[] READ_NUM(count); module->bindInformations.SetLength(count); for(i=0;i<count;++i) { sBindInfo *info = asNEW(sBindInfo); info->importedFunctionSignature = ReadFunction(false, false); info->importedFunctionSignature->id = int(FUNC_IMPORTED + engine->importedFunctions.GetLength()); engine->importedFunctions.PushLast(info); ReadString(&info->importFromModule); info->boundFunctionId = -1; module->bindInformations[i] = info; } // usedTypes[] READ_NUM(count); usedTypes.Allocate(count, 0); for( i = 0; i < count; ++i ) { asCObjectType *ot = ReadObjectType(); usedTypes.PushLast(ot); } // usedTypeIds[] ReadUsedTypeIds(); // usedFunctions[] ReadUsedFunctions(); // usedGlobalProperties[] ReadUsedGlobalProps(); // usedStringConstants[] ReadUsedStringConstants(); for( i = 0; i < module->scriptFunctions.GetLength(); i++ ) TranslateFunction(module->scriptFunctions[i]); for( i = 0; i < module->scriptGlobals.GetLength(); i++ ) if( module->scriptGlobals[i]->initFunc ) TranslateFunction(module->scriptGlobals[i]->initFunc); // Init system functions properly engine->PrepareEngine(); // Add references for all functions for( i = 0; i < module->scriptFunctions.GetLength(); i++ ) module->scriptFunctions[i]->AddReferences(); for( i = 0; i < module->scriptGlobals.GetLength(); i++ ) if( module->scriptGlobals[i]->initFunc ) module->scriptGlobals[i]->initFunc->AddReferences(); module->CallInit(); return 0; }
// internal asCObjectProperty *asCObjectType::AddPropertyToClass(const asCString &name, const asCDataType &dt, bool isPrivate) { asASSERT( flags & asOBJ_SCRIPT_OBJECT ); asASSERT( dt.CanBeInstantiated() ); asASSERT( !IsInterface() ); // Store the properties in the object type descriptor asCObjectProperty *prop = asNEW(asCObjectProperty); if( prop == 0 ) { // Out of memory return 0; } prop->name = name; prop->type = dt; prop->isPrivate = isPrivate; int propSize; if( dt.IsObject() ) { // Non-POD value types can't be allocated inline, // because there is a risk that the script might // try to access the content without knowing that // it hasn't been initialized yet. if( dt.GetObjectType()->flags & asOBJ_POD ) propSize = dt.GetSizeInMemoryBytes(); else { propSize = dt.GetSizeOnStackDWords()*4; if( !dt.IsObjectHandle() ) prop->type.MakeReference(true); } } else propSize = dt.GetSizeInMemoryBytes(); // Add extra bytes so that the property will be properly aligned #ifndef WIP_16BYTE_ALIGN if( propSize == 2 && (size & 1) ) size += 1; if( propSize > 2 && (size & 3) ) size += 4 - (size & 3); #else asUINT alignment = dt.GetAlignment(); const asUINT propSizeAlignmentDifference = size & (alignment-1); if( propSizeAlignmentDifference != 0 ) { size += (alignment - propSizeAlignmentDifference); } asASSERT((size % alignment) == 0); #endif prop->byteOffset = size; size += propSize; properties.PushLast(prop); // Make sure the struct holds a reference to the config group where the object is registered asCConfigGroup *group = engine->FindConfigGroupForObjectType(prop->type.GetObjectType()); if( group != 0 ) group->AddRef(); // Add reference to object types asCObjectType *type = prop->type.GetObjectType(); if( type ) type->AddRef(); return prop; }