// 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;
        }
    }
}
예제 #5
0
// 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;
}
예제 #6
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;
}