// internal void asCScriptFunction::ReleaseAllHandles(asIScriptEngine *) { // Release paramaters if( byteCode.GetLength() ) { if( returnType.IsObject() ) { returnType.GetObjectType()->Release(); returnType = asCDataType::CreatePrimitive(ttVoid, false); } for( asUINT p = 0; p < parameterTypes.GetLength(); p++ ) if( parameterTypes[p].IsObject() ) { parameterTypes[p].GetObjectType()->Release(); parameterTypes[p] = asCDataType::CreatePrimitive(ttInt, false); } for( asUINT n = 0; n < objVariableTypes.GetLength(); n++ ) objVariableTypes[n]->Release(); objVariableTypes.SetLength(0); } // Release all script functions for( asUINT n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] ) { switch( *(asBYTE*)&byteCode[n] ) { // Object types case asBC_OBJTYPE: case asBC_FREE: case asBC_REFCPY: { asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]); if( objType ) { objType->Release(); *(void**)&byteCode[n+1] = 0; } } break; case asBC_ALLOC: { asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]); if( objType ) { objType->Release(); * (void**)&byteCode[n+1] = 0; } int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE); if( func ) { engine->scriptFunctions[func]->Release(); byteCode[n+AS_PTR_SIZE+1] = 0; } } break; case asBC_CALL: case asBC_CALLINTF: { int func = asBC_INTARG(&byteCode[n]); if( func ) { engine->scriptFunctions[func]->Release(); byteCode[n+1] = 0; } } break; // Function pointers case asBC_FuncPtr: { asCScriptFunction *func = (asCScriptFunction*)(size_t)asBC_PTRARG(&byteCode[n]); if( func ) { func->Release(); *(size_t*)&byteCode[n+1] = 0; } } break; // The global variables are not released here. It is enough that the global // variable itself release the function to break the circle } } }
// internal void asCScriptFunction::EnumReferences(asIScriptEngine *) { // Notify the GC of all object types used if( returnType.IsObject() ) engine->GCEnumCallback(returnType.GetObjectType()); for( asUINT p = 0; p < parameterTypes.GetLength(); p++ ) if( parameterTypes[p].IsObject() ) engine->GCEnumCallback(parameterTypes[p].GetObjectType()); for( asUINT t = 0; t < objVariableTypes.GetLength(); t++ ) engine->GCEnumCallback(objVariableTypes[t]); // Notify the GC of all script functions that is accessed for( asUINT n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] ) { switch( *(asBYTE*)&byteCode[n] ) { case asBC_OBJTYPE: case asBC_FREE: case asBC_REFCPY: { asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]); engine->GCEnumCallback(objType); } break; case asBC_ALLOC: { asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]); engine->GCEnumCallback(objType); int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE); if( func ) engine->GCEnumCallback(engine->scriptFunctions[func]); } break; case asBC_CALL: case asBC_CALLINTF: { int func = asBC_INTARG(&byteCode[n]); if( func ) engine->GCEnumCallback(engine->scriptFunctions[func]); } break; // Function pointers case asBC_FuncPtr: { asCScriptFunction *func = (asCScriptFunction*)(size_t)asBC_PTRARG(&byteCode[n]); if( func ) engine->GCEnumCallback(func); } break; // Global variables case asBC_PGA: case asBC_LDG: case asBC_PshG4: case asBC_LdGRdR4: case asBC_CpyGtoV4: case asBC_CpyVtoG4: case asBC_SetG4: // Need to enumerate the reference for each global variable { // TODO: optimize: Keep an array of accessed global properties void *gvarPtr = (void*)(size_t)asBC_PTRARG(&byteCode[n]); asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr); engine->GCEnumCallback(prop); } break; } } }
// internal void asCScriptFunction::ReleaseReferences() { asUINT n; asCArray<void*> ptrs; // Only count references if there is any bytecode if( byteCode.GetLength() ) { if( returnType.IsObject() ) returnType.GetObjectType()->Release(); for( asUINT p = 0; p < parameterTypes.GetLength(); p++ ) if( parameterTypes[p].IsObject() ) parameterTypes[p].GetObjectType()->Release(); for( asUINT n = 0; n < objVariableTypes.GetLength(); n++ ) if( objVariableTypes[n] ) objVariableTypes[n]->Release(); } // Go through the byte code and release references to all resources used by the function for( n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] ) { switch( *(asBYTE*)&byteCode[n] ) { // Object types case asBC_OBJTYPE: case asBC_FREE: case asBC_REFCPY: { asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]); if( objType ) objType->Release(); } break; // Object type and function case asBC_ALLOC: { asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]); if( objType ) objType->Release(); int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE); if( func ) engine->scriptFunctions[func]->Release(); } break; // Global variables case asBC_PGA: case asBC_LDG: case asBC_PshG4: case asBC_LdGRdR4: case asBC_CpyGtoV4: case asBC_CpyVtoG4: case asBC_SetG4: // Need to increase the reference for each global variable { void *gvarPtr = (void*)(size_t)asBC_PTRARG(&byteCode[n]); if( !gvarPtr ) break; asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr); if( !prop ) break; // Only release the properties once if( !ptrs.Exists(gvarPtr) ) { prop->Release(); ptrs.PushLast(gvarPtr); } asCConfigGroup *group = engine->FindConfigGroupForGlobalVar(prop->id); if( group != 0 ) group->Release(); } break; // System functions case asBC_CALLSYS: { int funcId = asBC_INTARG(&byteCode[n]); asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId); if( group != 0 ) group->Release(); if( funcId ) engine->scriptFunctions[funcId]->Release(); } break; // Functions case asBC_CALL: case asBC_CALLINTF: { int func = asBC_INTARG(&byteCode[n]); if( func ) engine->scriptFunctions[func]->Release(); } break; // Function pointers case asBC_FuncPtr: { asCScriptFunction *func = (asCScriptFunction*)(size_t)asBC_PTRARG(&byteCode[n]); if( func ) func->Release(); } break; } } // Release the jit compiled function if( jitFunction ) engine->jitCompiler->ReleaseJITFunction(jitFunction); jitFunction = 0; }
// internal void asCScriptFunction::AddReferences() { asUINT n; // This array will be used to make sure we only add the reference to the same resource once // This is especially important for global variables, as it expects the initialization function // to hold only one reference to the variable. However, if the variable is initialized through // the default constructor followed by the assignment operator we will have two references to // the variable in the function. asCArray<void*> ptrs; // Only count references if there is any bytecode if( byteCode.GetLength() ) { if( returnType.IsObject() ) returnType.GetObjectType()->AddRef(); for( asUINT p = 0; p < parameterTypes.GetLength(); p++ ) if( parameterTypes[p].IsObject() ) parameterTypes[p].GetObjectType()->AddRef(); for( asUINT n = 0; n < objVariableTypes.GetLength(); n++ ) objVariableTypes[n]->AddRef(); } // Go through the byte code and add references to all resources used by the function for( n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] ) { switch( *(asBYTE*)&byteCode[n] ) { // Object types case asBC_OBJTYPE: case asBC_FREE: case asBC_REFCPY: { asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]); objType->AddRef(); } break; // Object type and function case asBC_ALLOC: { asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]); objType->AddRef(); int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE); if( func ) engine->scriptFunctions[func]->AddRef(); } break; // Global variables case asBC_PGA: case asBC_LDG: case asBC_PshG4: case asBC_LdGRdR4: case asBC_CpyGtoV4: case asBC_CpyVtoG4: case asBC_SetG4: // Need to increase the reference for each global variable { void *gvarPtr = (void*)(size_t)asBC_PTRARG(&byteCode[n]); if( !gvarPtr ) break; asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr); if( !prop ) break; // Only addref the properties once if( !ptrs.Exists(gvarPtr) ) { prop->AddRef(); ptrs.PushLast(gvarPtr); } asCConfigGroup *group = engine->FindConfigGroupForGlobalVar(prop->id); if( group != 0 ) group->AddRef(); } break; // System functions case asBC_CALLSYS: { int funcId = asBC_INTARG(&byteCode[n]); asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId); if( group != 0 ) group->AddRef(); engine->scriptFunctions[funcId]->AddRef(); } break; // Functions case asBC_CALL: case asBC_CALLINTF: { int func = asBC_INTARG(&byteCode[n]); engine->scriptFunctions[func]->AddRef(); } break; // Function pointers case asBC_FuncPtr: { asCScriptFunction *func = (asCScriptFunction*)(size_t)asBC_PTRARG(&byteCode[n]); func->AddRef(); } break; } } }
// internal void asCScriptFunction::ReleaseReferences() { asUINT n; asCArray<void*> ptrs; // Only count references if there is any bytecode if( byteCode.GetLength() ) { if( returnType.IsObject() ) returnType.GetObjectType()->Release(); for( asUINT p = 0; p < parameterTypes.GetLength(); p++ ) if( parameterTypes[p].IsObject() ) parameterTypes[p].GetObjectType()->Release(); for( asUINT n = 0; n < objVariableTypes.GetLength(); n++ ) if( objVariableTypes[n] ) objVariableTypes[n]->Release(); } // Go through the byte code and release references to all resources used by the function for( n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] ) { switch( *(asBYTE*)&byteCode[n] ) { // Object types case asBC_OBJTYPE: case asBC_FREE: case asBC_REFCPY: case asBC_RefCpyV: { asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&byteCode[n]); if( objType ) objType->Release(); } break; // Object type and function case asBC_ALLOC: { asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&byteCode[n]); if( objType ) objType->Release(); int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE); if( func ) { asCScriptFunction *fptr = engine->scriptFunctions[func]; if( fptr ) fptr->Release(); // The engine may have been forced to destroy the function internals early // and this may will make it impossible to find the function by id anymore. // This should only happen if the engine is released while the application // is still keeping functions alive. // TODO: Fix this possible memory leak } } break; // Global variables case asBC_PGA: case asBC_PshGPtr: case asBC_LDG: case asBC_PshG4: case asBC_LdGRdR4: case asBC_CpyGtoV4: case asBC_CpyVtoG4: case asBC_SetG4: // Need to increase the reference for each global variable { void *gvarPtr = (void*)asBC_PTRARG(&byteCode[n]); if( !gvarPtr ) break; asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr); if( !prop ) break; // Only release the properties once if( !ptrs.Exists(gvarPtr) ) { prop->Release(); ptrs.PushLast(gvarPtr); } asCConfigGroup *group = engine->FindConfigGroupForGlobalVar(prop->id); if( group != 0 ) group->Release(); } break; // System functions case asBC_CALLSYS: { int funcId = asBC_INTARG(&byteCode[n]); asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId); if( group != 0 ) group->Release(); if( funcId ) engine->scriptFunctions[funcId]->Release(); } break; // Functions case asBC_CALL: case asBC_CALLINTF: { int func = asBC_INTARG(&byteCode[n]); if( func ) { asCScriptFunction *fptr = engine->scriptFunctions[func]; if( fptr ) fptr->Release(); // The engine may have been forced to destroy the function internals early // and this may will make it impossible to find the function by id anymore. // This should only happen if the engine is released while the application // is still keeping functions alive. // TODO: Fix this possible memory leak } } break; // Function pointers case asBC_FuncPtr: { asCScriptFunction *func = (asCScriptFunction*)asBC_PTRARG(&byteCode[n]); if( func ) func->Release(); } break; } } // Release the jit compiled function if( jitFunction ) engine->jitCompiler->ReleaseJITFunction(jitFunction); jitFunction = 0; // Delegate if( objForDelegate ) engine->ReleaseScriptObject(objForDelegate, funcForDelegate->GetObjectType()); objForDelegate = 0; if( funcForDelegate ) funcForDelegate->Release(); funcForDelegate = 0; }
// internal void asCScriptFunction::ReleaseAllHandles(asIScriptEngine *) { // Release paramaters if( scriptData && scriptData->byteCode.GetLength() ) { if( returnType.IsObject() ) { returnType.GetObjectType()->Release(); returnType = asCDataType::CreatePrimitive(ttVoid, false); } for( asUINT p = 0; p < parameterTypes.GetLength(); p++ ) if( parameterTypes[p].IsObject() ) { parameterTypes[p].GetObjectType()->Release(); parameterTypes[p] = asCDataType::CreatePrimitive(ttInt, false); } for( asUINT n = 0; n < scriptData->objVariableTypes.GetLength(); n++ ) if( scriptData->objVariableTypes[n] ) // Null handle is also stored, but it doesn't have an object type scriptData->objVariableTypes[n]->Release(); scriptData->objVariableTypes.SetLength(0); // Release all script functions asCArray<asDWORD> &bc = scriptData->byteCode; for( asUINT n = 0; n < bc.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&bc[n]].type] ) { switch( *(asBYTE*)&bc[n] ) { // Object types case asBC_OBJTYPE: case asBC_FREE: case asBC_REFCPY: case asBC_RefCpyV: { asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]); if( objType ) { objType->Release(); *(asPWORD*)&bc[n+1] = 0; } } break; case asBC_ALLOC: { asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]); if( objType ) { objType->Release(); *(asPWORD*)&bc[n+1] = 0; } int func = asBC_INTARG(&bc[n]+AS_PTR_SIZE); if( func ) { engine->scriptFunctions[func]->Release(); bc[n+AS_PTR_SIZE+1] = 0; } } break; case asBC_CALL: case asBC_CALLINTF: { int func = asBC_INTARG(&bc[n]); if( func ) { engine->scriptFunctions[func]->Release(); bc[n+1] = 0; } } break; // Function pointers case asBC_FuncPtr: { asCScriptFunction *func = (asCScriptFunction*)asBC_PTRARG(&bc[n]); if( func ) { func->Release(); *(asPWORD*)&bc[n+1] = 0; } } break; // The global variables are not released here. It is enough that the global // variable itself release the function to break the circle } } } // Delegate if( objForDelegate ) engine->ReleaseScriptObject(objForDelegate, funcForDelegate->GetObjectType()); objForDelegate = 0; if( funcForDelegate ) funcForDelegate->Release(); funcForDelegate = 0; }