PageRenderTime 143ms CodeModel.GetById 55ms app.highlight 82ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/visualizations/Vortex/angelscript/angelscript/source/as_scriptfunction.cpp

http://github.com/xbmc/xbmc
C++ | 885 lines | 636 code | 127 blank | 122 comment | 149 complexity | 4ad8794e91a39be120ac319811658427 MD5 | raw file
  1/*
  2   AngelCode Scripting Library
  3   Copyright (c) 2003-2009 Andreas Jonsson
  4
  5   This software is provided 'as-is', without any express or implied 
  6   warranty. In no event will the authors be held liable for any 
  7   damages arising from the use of this software.
  8
  9   Permission is granted to anyone to use this software for any 
 10   purpose, including commercial applications, and to alter it and 
 11   redistribute it freely, subject to the following restrictions:
 12
 13   1. The origin of this software must not be misrepresented; you 
 14      must not claim that you wrote the original software. If you use
 15      this software in a product, an acknowledgment in the product 
 16      documentation would be appreciated but is not required.
 17
 18   2. Altered source versions must be plainly marked as such, and 
 19      must not be misrepresented as being the original software.
 20
 21   3. This notice may not be removed or altered from any source 
 22      distribution.
 23
 24   The original version of this library can be located at:
 25   http://www.angelcode.com/angelscript/
 26
 27   Andreas Jonsson
 28   andreas@angelcode.com
 29*/
 30
 31
 32//
 33// as_scriptfunction.cpp
 34//
 35// A container for a compiled script function
 36//
 37
 38
 39
 40#include "as_config.h"
 41#include "as_scriptfunction.h"
 42#include "as_tokendef.h"
 43#include "as_scriptengine.h"
 44#include "as_callfunc.h"
 45#include "as_bytecode.h"
 46#include "as_texts.h"
 47
 48BEGIN_AS_NAMESPACE
 49
 50#ifdef AS_MAX_PORTABILITY
 51
 52static void ScriptFunction_AddRef_Generic(asIScriptGeneric *gen)
 53{
 54	asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
 55	self->AddRef();
 56}
 57
 58static void ScriptFunction_Release_Generic(asIScriptGeneric *gen)
 59{
 60	asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
 61	self->Release();
 62}
 63
 64static void ScriptFunction_GetRefCount_Generic(asIScriptGeneric *gen)
 65{
 66	asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
 67	*(int*)gen->GetAddressOfReturnLocation() = self->GetRefCount();
 68}
 69
 70static void ScriptFunction_SetFlag_Generic(asIScriptGeneric *gen)
 71{
 72	asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
 73	self->SetFlag();
 74}
 75
 76static void ScriptFunction_GetFlag_Generic(asIScriptGeneric *gen)
 77{
 78	asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
 79	*(bool*)gen->GetAddressOfReturnLocation() = self->GetFlag();
 80}
 81
 82static void ScriptFunction_EnumReferences_Generic(asIScriptGeneric *gen)
 83{
 84	asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
 85	asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
 86	self->EnumReferences(engine);
 87}
 88
 89static void ScriptFunction_ReleaseAllHandles_Generic(asIScriptGeneric *gen)
 90{
 91	asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
 92	asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
 93	self->ReleaseAllHandles(engine);
 94}
 95
 96#endif
 97
 98
 99void RegisterScriptFunction(asCScriptEngine *engine)
100{
101	// Register the gc behaviours for the script functions
102	int r;
103	engine->functionBehaviours.engine = engine;
104	engine->functionBehaviours.flags = asOBJ_REF | asOBJ_GC;
105	engine->functionBehaviours.name = "_builtin_function_";
106#ifndef AS_MAX_PORTABILITY
107	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCScriptFunction,AddRef), asCALL_THISCALL); asASSERT( r >= 0 );
108	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASE, "void f()", asMETHOD(asCScriptFunction,Release), asCALL_THISCALL); asASSERT( r >= 0 );
109	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(asCScriptFunction,GetRefCount), asCALL_THISCALL); asASSERT( r >= 0 );
110	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_SETGCFLAG, "void f()", asMETHOD(asCScriptFunction,SetFlag), asCALL_THISCALL); asASSERT( r >= 0 );
111	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(asCScriptFunction,GetFlag), asCALL_THISCALL); asASSERT( r >= 0 );
112	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(asCScriptFunction,EnumReferences), asCALL_THISCALL); asASSERT( r >= 0 );
113	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(asCScriptFunction,ReleaseAllHandles), asCALL_THISCALL); asASSERT( r >= 0 );
114#else
115	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptFunction_AddRef_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
116	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptFunction_Release_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
117	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptFunction_GetRefCount_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
118	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ScriptFunction_SetFlag_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
119	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ScriptFunction_GetFlag_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
120	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ScriptFunction_EnumReferences_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
121	r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ScriptFunction_ReleaseAllHandles_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
122#endif
123}
124
125// internal
126asCScriptFunction::asCScriptFunction(asCScriptEngine *engine, asCModule *mod, int _funcType)
127{
128	refCount.set(1);
129	this->engine           = engine;
130	funcType               = _funcType;
131	module                 = mod; 
132	objectType             = 0; 
133	name                   = ""; 
134	isReadOnly             = false;
135	stackNeeded            = 0;
136	sysFuncIntf            = 0;
137	signatureId            = 0;
138	scriptSectionIdx       = -1;
139	dontCleanUpOnException = false;
140	vfTableIdx             = -1;
141	jitFunction            = 0;
142	gcFlag                 = false;
143
144	// Notify the GC of script functions
145	if( funcType == asFUNC_SCRIPT )
146		engine->gc.AddScriptObjectToGC(this, &engine->functionBehaviours);
147}
148
149// internal
150asCScriptFunction::~asCScriptFunction()
151{
152	// Imported functions are not reference counted, nor are dummy 
153	// functions that are allocated on the stack
154	asASSERT( funcType == -1              || 
155		      funcType == asFUNC_IMPORTED ||
156		      refCount.get() == 0         );
157
158	ReleaseReferences();
159
160	// Tell engine to free the function id
161	if( funcType != -1 && funcType != asFUNC_IMPORTED && id )
162		engine->FreeScriptFunctionId(id);
163
164	for( asUINT n = 0; n < variables.GetLength(); n++ )
165	{
166		asDELETE(variables[n],asSScriptVariable);
167	}
168
169	if( sysFuncIntf )
170	{
171		asDELETE(sysFuncIntf,asSSystemFunctionInterface);
172	}
173}
174
175// interface
176int asCScriptFunction::GetId() const
177{
178	return id;
179}
180
181// interface
182int asCScriptFunction::AddRef()
183{
184	gcFlag = false;
185	asASSERT( funcType != asFUNC_IMPORTED );
186	return refCount.atomicInc();
187}
188
189// interface
190int asCScriptFunction::Release()
191{
192	gcFlag = false;
193	asASSERT( funcType != asFUNC_IMPORTED );
194	int r = refCount.atomicDec();
195	if( r == 0 && funcType != -1 ) // Dummy functions are allocated on the stack and cannot be deleted
196		asDELETE(this,asCScriptFunction);
197
198	return r;
199}
200
201// interface
202const char *asCScriptFunction::GetModuleName() const
203{
204	if( module )
205	{
206		return module->name.AddressOf();
207	}
208
209	return 0;
210}
211
212// interface
213asIObjectType *asCScriptFunction::GetObjectType() const
214{
215	return objectType;
216}
217
218// interface
219const char *asCScriptFunction::GetObjectName() const 
220{
221	if( objectType )
222		return objectType->GetName();
223
224	return 0;
225}
226
227// interface
228const char *asCScriptFunction::GetName() const
229{
230	return name.AddressOf();
231}
232
233// interface
234bool asCScriptFunction::IsClassMethod() const
235{
236	return objectType && objectType->IsInterface() == false;
237}
238
239// interface
240bool asCScriptFunction::IsInterfaceMethod() const
241{
242	return objectType && objectType->IsInterface();
243}
244
245// interface
246bool asCScriptFunction::IsReadOnly() const
247{
248	return isReadOnly;
249}
250
251// internal
252int asCScriptFunction::GetSpaceNeededForArguments()
253{
254	// We need to check the size for each type
255	int s = 0;
256	for( asUINT n = 0; n < parameterTypes.GetLength(); n++ )
257		s += parameterTypes[n].GetSizeOnStackDWords();
258
259	return s;
260}
261
262// internal
263int asCScriptFunction::GetSpaceNeededForReturnValue()
264{
265	return returnType.GetSizeOnStackDWords();
266}
267
268// internal
269asCString asCScriptFunction::GetDeclarationStr(bool includeObjectName) const
270{
271	asCString str;
272
273	str = returnType.Format();
274	str += " ";
275	if( objectType && includeObjectName )
276	{
277		if( objectType->name != "" )
278			str += objectType->name + "::";
279		else
280			str += "_unnamed_type_::";
281	}
282	asASSERT(name.GetLength() > 0);
283	if( name == "" )
284		str += "_unnamed_function_(";
285	else
286		str += name + "(";
287
288	if( parameterTypes.GetLength() > 0 )
289	{
290		asUINT n;
291		for( n = 0; n < parameterTypes.GetLength() - 1; n++ )
292		{
293			str += parameterTypes[n].Format();
294			if( parameterTypes[n].IsReference() && inOutFlags.GetLength() > n )
295			{
296				if( inOutFlags[n] == asTM_INREF ) str += "in";
297				else if( inOutFlags[n] == asTM_OUTREF ) str += "out";
298				else if( inOutFlags[n] == asTM_INOUTREF ) str += "inout";
299			}
300			str += ", ";
301		}
302
303		str += parameterTypes[n].Format();
304		if( parameterTypes[n].IsReference() && inOutFlags.GetLength() > n )
305		{
306			if( inOutFlags[n] == asTM_INREF ) str += "in";
307			else if( inOutFlags[n] == asTM_OUTREF ) str += "out";
308			else if( inOutFlags[n] == asTM_INOUTREF ) str += "inout";
309		}
310	}
311
312	str += ")";
313
314	if( isReadOnly )
315		str += " const";
316
317	return str;
318}
319
320// internal
321int asCScriptFunction::GetLineNumber(int programPosition)
322{
323	if( lineNumbers.GetLength() == 0 ) return 0;
324
325	// Do a binary search in the buffer
326	int max = (int)lineNumbers.GetLength()/2 - 1;
327	int min = 0;
328	int i = max/2;
329
330	for(;;)
331	{
332		if( lineNumbers[i*2] < programPosition )
333		{
334			// Have we found the largest number < programPosition?
335			if( max == i ) return lineNumbers[i*2+1];
336			if( lineNumbers[i*2+2] > programPosition ) return lineNumbers[i*2+1];
337
338			min = i + 1;
339			i = (max + min)/2; 
340		}
341		else if( lineNumbers[i*2] > programPosition )
342		{
343			// Have we found the smallest number > programPosition?
344			if( min == i ) return lineNumbers[i*2+1];
345
346			max = i - 1;
347			i = (max + min)/2;
348		}
349		else
350		{
351			// We found the exact position
352			return lineNumbers[i*2+1];
353		}
354	}
355}
356
357// internal
358void asCScriptFunction::AddVariable(asCString &name, asCDataType &type, int stackOffset)
359{
360	asSScriptVariable *var = asNEW(asSScriptVariable);
361	var->name        = name;
362	var->type        = type;
363	var->stackOffset = stackOffset;
364	variables.PushLast(var);
365}
366
367// internal
368void asCScriptFunction::ComputeSignatureId()
369{
370	// This function will compute the signatureId based on the 
371	// function name, return type, and parameter types. The object 
372	// type for methods is not used, so that class methods and  
373	// interface methods match each other.
374	for( asUINT n = 0; n < engine->signatureIds.GetLength(); n++ )
375	{
376		if( !IsSignatureEqual(engine->signatureIds[n]) ) continue;
377
378		// We don't need to increment the reference counter here, because 
379		// asCScriptEngine::FreeScriptFunctionId will maintain the signature
380		// id as the function is freed.
381		signatureId = engine->signatureIds[n]->signatureId;
382		return;
383	}
384
385	signatureId = id;
386	engine->signatureIds.PushLast(this);
387}
388
389// internal
390bool asCScriptFunction::IsSignatureEqual(const asCScriptFunction *func) const
391{
392	if( name              != func->name              ) return false;
393	if( returnType        != func->returnType        ) return false;
394	if( isReadOnly        != func->isReadOnly        ) return false;
395	if( inOutFlags        != func->inOutFlags        ) return false;
396	if( parameterTypes    != func->parameterTypes    ) return false;
397	if( (objectType != 0) != (func->objectType != 0) ) return false;
398
399	return true;
400}
401
402// internal
403void asCScriptFunction::AddReferences()
404{
405	asUINT n;
406
407	// Only count references if there is any bytecode
408	if( byteCode.GetLength() ) 
409	{
410		if( returnType.IsObject() )
411			returnType.GetObjectType()->AddRef();
412
413		for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
414			if( parameterTypes[p].IsObject() )
415				parameterTypes[p].GetObjectType()->AddRef();
416	}
417
418	// TODO: global: The global var address should be stored in the instruction directly
419	// Go through the byte code and add references to all resources used by the function
420	for( n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] )
421	{
422		switch( *(asBYTE*)&byteCode[n] )
423		{
424		// Object types
425		case asBC_OBJTYPE:
426		case asBC_FREE:
427		case asBC_REFCPY:
428			{
429                asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
430				objType->AddRef();
431			}
432			break;
433
434		// Object type and function
435		case asBC_ALLOC:
436			{
437				asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
438				objType->AddRef();
439
440				int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE);
441				if( func )
442					engine->scriptFunctions[func]->AddRef();
443			}
444			break;
445
446		// Global variables
447		case asBC_LDG:
448		case asBC_PGA:
449		case asBC_PshG4:
450		case asBC_SetG4:
451		case asBC_CpyVtoG4:
452			// Need to increase the reference for each global variable
453			{
454				int gvarIdx = asBC_WORDARG0(&byteCode[n]);
455				asCConfigGroup *group = GetConfigGroupByGlobalVarPtrIndex(gvarIdx);
456				if( group != 0 ) group->AddRef();
457			}
458			break;
459
460		case asBC_LdGRdR4:
461		case asBC_CpyGtoV4:
462			// Need to increase the reference for each global variable
463			{
464				int gvarIdx = asBC_WORDARG1(&byteCode[n]);
465				asCConfigGroup *group = GetConfigGroupByGlobalVarPtrIndex(gvarIdx);
466				if( group != 0 ) group->AddRef();
467			}
468			break;
469
470		// System functions
471		case asBC_CALLSYS:
472			{
473				int funcId = asBC_INTARG(&byteCode[n]);
474				asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId);
475				if( group != 0 ) group->AddRef();
476
477				engine->scriptFunctions[funcId]->AddRef();
478			}
479			break;
480
481		// Functions
482		case asBC_CALL:
483		case asBC_CALLINTF:
484			{
485				int func = asBC_INTARG(&byteCode[n]);
486				engine->scriptFunctions[func]->AddRef();
487			}
488			break;
489		}
490	}
491
492	// Add reference to the global properties
493	for( n = 0; n < globalVarPointers.GetLength(); n++ )
494	{
495		asCGlobalProperty *prop = GetPropertyByGlobalVarPtrIndex(n);
496		prop->AddRef();
497	}
498}
499
500// internal
501void asCScriptFunction::ReleaseReferences()
502{
503	asUINT n;
504
505	// Only count references if there is any bytecode
506	if( byteCode.GetLength() )
507	{
508		if( returnType.IsObject() )
509			returnType.GetObjectType()->Release();
510
511		for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
512			if( parameterTypes[p].IsObject() )
513				parameterTypes[p].GetObjectType()->Release();
514	}
515
516	// TODO: global: The global var address should be stored in the instruction directly
517	// Go through the byte code and release references to all resources used by the function
518	for( n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] )
519	{
520		switch( *(asBYTE*)&byteCode[n] )
521		{
522		// Object types
523		case asBC_OBJTYPE:
524		case asBC_FREE:
525		case asBC_REFCPY:
526			{
527				asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
528				if( objType ) 
529					objType->Release();
530			}
531			break;
532
533		// Object type and function
534		case asBC_ALLOC:
535			{
536				asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
537				if( objType )
538					objType->Release();
539
540				int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE);
541				if( func )
542					engine->scriptFunctions[func]->Release();
543			}
544			break;
545
546		// Global variables
547		case asBC_LDG:
548		case asBC_PGA:
549		case asBC_PshG4:
550		case asBC_SetG4:
551		case asBC_CpyVtoG4:
552			// Need to decrease the reference for each global variable
553			{
554				int gvarIdx = asBC_WORDARG0(&byteCode[n]);
555				asCConfigGroup *group = GetConfigGroupByGlobalVarPtrIndex(gvarIdx);
556				if( group != 0 ) group->Release();
557			}
558			break;
559
560		case asBC_LdGRdR4:
561		case asBC_CpyGtoV4:
562			// Need to decrease the reference for each global variable
563			{
564				int gvarIdx = asBC_WORDARG1(&byteCode[n]);
565				asCConfigGroup *group = GetConfigGroupByGlobalVarPtrIndex(gvarIdx);
566				if( group != 0 ) group->Release();
567			}
568			break;
569
570		// System functions
571		case asBC_CALLSYS:
572			{
573				int funcId = asBC_INTARG(&byteCode[n]);
574				asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId);
575				if( group != 0 ) group->Release();
576
577				if( funcId )
578					engine->scriptFunctions[funcId]->Release();
579			}
580			break;
581
582		// Functions
583		case asBC_CALL:
584		case asBC_CALLINTF:
585			{
586				int func = asBC_INTARG(&byteCode[n]);
587				if( func )
588					engine->scriptFunctions[func]->Release();
589			}
590			break;
591		}
592	}
593
594	// Release the global properties
595	for( n = 0; n < globalVarPointers.GetLength(); n++ )
596	{
597		asCGlobalProperty *prop = GetPropertyByGlobalVarPtrIndex(n);
598		prop->Release();
599	}
600
601	// Release the jit compiled function
602	if( jitFunction )
603		engine->jitCompiler->ReleaseJITFunction(jitFunction);
604	jitFunction = 0;
605}
606
607// interface
608int asCScriptFunction::GetReturnTypeId() const
609{
610	return engine->GetTypeIdFromDataType(returnType);
611}
612
613// interface
614int asCScriptFunction::GetParamCount() const
615{
616	return (int)parameterTypes.GetLength();
617}
618
619// interface
620int asCScriptFunction::GetParamTypeId(int index, asDWORD *flags) const
621{
622	if( index < 0 || (unsigned)index >= parameterTypes.GetLength() )
623		return asINVALID_ARG;
624
625	if( flags )
626		*flags = inOutFlags[index];
627
628	return engine->GetTypeIdFromDataType(parameterTypes[index]);
629}
630
631// interface
632asIScriptEngine *asCScriptFunction::GetEngine() const
633{
634	return engine;
635}
636
637// interface
638const char *asCScriptFunction::GetDeclaration(bool includeObjectName) const
639{
640	asASSERT(threadManager);
641	asCString *tempString = &threadManager->GetLocalData()->string;
642	*tempString = GetDeclarationStr(includeObjectName);
643	return tempString->AddressOf();
644}
645
646// interface
647const char *asCScriptFunction::GetScriptSectionName() const
648{
649	if( scriptSectionIdx >= 0 )
650		return engine->scriptSectionNames[scriptSectionIdx]->AddressOf();
651	
652	return 0;
653}
654
655// interface
656const char *asCScriptFunction::GetConfigGroup() const
657{
658	asCConfigGroup *group = engine->FindConfigGroupForFunction(id);
659	if( group == 0 )
660		return 0;
661
662	return group->groupName.AddressOf();
663}
664
665// internal
666void asCScriptFunction::JITCompile()
667{
668    asIJITCompiler *jit = engine->GetJITCompiler();
669    if( !jit )
670        return;
671
672	// Release the previous function, if any
673    if( jitFunction )
674    {
675        engine->jitCompiler->ReleaseJITFunction(jitFunction);
676        jitFunction = 0;
677    }
678
679	// Compile for native system
680	int r = jit->CompileFunction(this, &jitFunction);
681	if( r < 0 )
682	{
683		asASSERT( jitFunction == 0 );
684	}
685}
686
687// interface
688asDWORD *asCScriptFunction::GetByteCode(asUINT *length)
689{
690	if( length )
691		*length = (asUINT)byteCode.GetLength();
692
693	if( byteCode.GetLength() )
694	{
695		return byteCode.AddressOf();
696	}
697
698	return 0;
699}
700
701// internal
702int asCScriptFunction::GetGlobalVarPtrIndex(int gvarId)
703{
704	void *ptr = engine->globalProperties[gvarId]->GetAddressOfValue();
705
706	// Check if this pointer has been stored already
707	for( int n = 0; n < (signed)globalVarPointers.GetLength(); n++ )
708		if( globalVarPointers[n] == ptr )
709			return n;
710
711	// Add the new variable to the array
712	globalVarPointers.PushLast(ptr);
713	return (int)globalVarPointers.GetLength()-1;
714}
715
716// internal
717asCConfigGroup *asCScriptFunction::GetConfigGroupByGlobalVarPtrIndex(int index)
718{
719	void *gvarPtr = globalVarPointers[index];
720
721	int gvarId = -1;
722	for( asUINT g = 0; g < engine->registeredGlobalProps.GetLength(); g++ )
723	{
724		if( engine->registeredGlobalProps[g] && engine->registeredGlobalProps[g]->GetAddressOfValue() == gvarPtr )
725		{
726			gvarId = engine->registeredGlobalProps[g]->id;
727			break;
728		}
729	}
730
731	if( gvarId >= 0 )
732	{
733		// Find the config group from the property id
734		return engine->FindConfigGroupForGlobalVar(gvarId);
735	}
736
737	return 0;
738}
739
740// internal
741asCGlobalProperty *asCScriptFunction::GetPropertyByGlobalVarPtrIndex(int index)
742{
743	void *gvarPtr = globalVarPointers[index];
744
745	for( asUINT g = 0; g < engine->globalProperties.GetLength(); g++ )
746		if( engine->globalProperties[g] && engine->globalProperties[g]->GetAddressOfValue() == gvarPtr )
747			return engine->globalProperties[g];
748
749	return 0;
750}
751
752// internal
753int asCScriptFunction::GetRefCount()
754{
755	return refCount.get();
756}
757
758// internal
759void asCScriptFunction::SetFlag()
760{
761	gcFlag = true;
762}
763
764// internal
765bool asCScriptFunction::GetFlag()
766{
767	return gcFlag;
768}
769
770// internal
771void asCScriptFunction::EnumReferences(asIScriptEngine *)
772{
773	// Notify the GC of all object types used
774	if( returnType.IsObject() )
775		engine->GCEnumCallback(returnType.GetObjectType());
776
777	for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
778		if( parameterTypes[p].IsObject() )
779			engine->GCEnumCallback(parameterTypes[p].GetObjectType());
780
781	// Notify the GC of all script functions that is accessed
782	for( asUINT n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] )
783	{
784		switch( *(asBYTE*)&byteCode[n] )
785		{
786		case asBC_OBJTYPE:
787		case asBC_FREE:
788		case asBC_REFCPY:
789			{
790                asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
791				engine->GCEnumCallback(objType);
792			}
793			break;
794
795		case asBC_ALLOC:
796			{
797				asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
798				engine->GCEnumCallback(objType);
799
800				int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE);
801				if( func )
802					engine->GCEnumCallback(engine->scriptFunctions[func]);
803			}
804			break;
805
806		case asBC_CALL:
807		case asBC_CALLINTF:
808			{
809				int func = asBC_INTARG(&byteCode[n]);
810				if( func )
811					engine->GCEnumCallback(engine->scriptFunctions[func]);
812			}
813			break;
814		}
815	}
816}
817
818// internal
819void asCScriptFunction::ReleaseAllHandles(asIScriptEngine *)
820{
821	// Release paramaters
822	if( byteCode.GetLength() ) 
823	{
824		if( returnType.IsObject() )
825		{
826			returnType.GetObjectType()->Release();
827			returnType = asCDataType::CreatePrimitive(ttVoid, false);
828		}
829
830		for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
831			if( parameterTypes[p].IsObject() )
832			{
833				parameterTypes[p].GetObjectType()->Release();
834				parameterTypes[p] = asCDataType::CreatePrimitive(ttInt, false);
835			}
836	}
837
838	// Release all script functions
839	for( asUINT n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] )
840	{
841		switch( *(asBYTE*)&byteCode[n] )
842		{
843		// Object types
844		case asBC_OBJTYPE:
845		case asBC_FREE:
846		case asBC_REFCPY:
847			{
848                asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
849				objType->Release();
850				*(void**)&byteCode[n+1] = 0;
851			}
852			break;
853
854		case asBC_ALLOC:
855			{
856				asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
857				objType->Release();
858				*(void**)&byteCode[n+1] = 0;
859
860				int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE);
861				if( func )
862				{
863					engine->scriptFunctions[func]->Release();
864					byteCode[n+AS_PTR_SIZE+1] = 0;
865				}
866			}
867			break;
868
869		case asBC_CALL:
870		case asBC_CALLINTF:
871			{
872				int func = asBC_INTARG(&byteCode[n]);
873				if( func )
874				{
875					engine->scriptFunctions[func]->Release();
876					byteCode[n+1] = 0;
877				}
878			}
879			break;
880		}
881	}
882}
883
884END_AS_NAMESPACE
885