// 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::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:
        {
            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;
}
Ejemplo n.º 4
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;
}