Пример #1
0
// internal
void asCScriptFunction::JITCompile()
{
	if( funcType != asFUNC_SCRIPT )
		return;

	asASSERT( scriptData );

	asIJITCompiler *jit = engine->GetJITCompiler();
	if( !jit )
		return;

	// Release the previous function, if any
	if( scriptData->jitFunction )
	{
		engine->jitCompiler->ReleaseJITFunction(scriptData->jitFunction);
		scriptData->jitFunction = 0;
	}

	// Compile for native system
	int r = jit->CompileFunction(this, &scriptData->jitFunction);
	if( r < 0 )
	{
		asASSERT( scriptData->jitFunction == 0 );
	}
}
Пример #2
0
void asCConfigGroup::ValidateNoUsage(asCScriptEngine *engine, asCObjectType *type)
{
	for( asUINT n = 0; n < engine->scriptFunctions.GetLength(); n++ )
	{
		asCScriptFunction *func = engine->scriptFunctions[n];
		if( func == 0 ) continue;

		// Ignore factory, list factory, and members
		if( func->name == "_beh_2_" || func->name == "_beh_3_" || func->objectType == type )
			continue;

		asASSERT( func->returnType.GetObjectType() != type );

		for( asUINT p = 0; p < func->parameterTypes.GetLength(); p++ )
		{
			asASSERT(func->parameterTypes[p].GetObjectType() != type);
		}
	}

	// TODO: Check also usage of the type in global variables 

	// TODO: Check also usage of the type in local variables in script functions

	// TODO: Check also usage of the type as members of classes

	// TODO: Check also usage of the type as sub types in other types
}
asCScriptObject::~asCScriptObject()
{
	if( weakRefFlag )
	{
		weakRefFlag->Release();
		weakRefFlag = 0;
	}

	// The engine pointer should be available from the objectType
	asCScriptEngine *engine = objType->engine;

	// Destroy all properties
	// In most cases the members are initialized in the order they have been declared, 
	// so it's safer to uninitialize them from last to first. The order may be different
	// depending on the use of inheritance and or initialization in the declaration.
	// TODO: Should the order of initialization be stored by the compiler so that the 
	//       reverse order can be guaranteed during the destruction?
	for( int n = (int)objType->properties.GetLength()-1; n >= 0; n-- )
	{
		asCObjectProperty *prop = objType->properties[n];
		if( prop->type.IsObject() )
		{
			// Destroy the object
			asCObjectType *propType = prop->type.GetObjectType();
			if( prop->type.IsReference() || propType->flags & asOBJ_REF )
			{
				void **ptr = (void**)(((char*)this) + prop->byteOffset);
				if( *ptr )
				{
					FreeObject(*ptr, propType, engine);
					*(asDWORD*)ptr = 0;
				}
			}
			else
			{
				// The object is allocated inline. As only POD objects may be allocated inline
				// it is not a problem to call the destructor even if the object may never have
				// been initialized, e.g. if an exception interrupted the constructor.
				asASSERT( propType->flags & asOBJ_POD );

				void *ptr = (void**)(((char*)this) + prop->byteOffset);
				if( propType->beh.destruct )
					engine->CallObjectMethod(ptr, propType->beh.destruct);
			}
		}
	}

	objType->Release();
	objType = 0;

	// Something is really wrong if the refCount is not 0 by now
	asASSERT( refCount.get() == 0 );
}
Пример #4
0
// This function should prepare system functions so that it will be faster to call them
int PrepareSystemFunctionGeneric(asCScriptFunction *func, asSSystemFunctionInterface *internal, asCScriptEngine * /*engine*/)
{
	asASSERT(internal->callConv == ICC_GENERIC_METHOD || internal->callConv == ICC_GENERIC_FUNC);

	// Calculate the size needed for the parameters
	internal->paramSize = func->GetSpaceNeededForArguments();

	// Prepare the clean up instructions for the function arguments
	internal->cleanArgs.SetLength(0);
	int offset = 0;
	for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
	{
		asCDataType &dt = func->parameterTypes[n];

		if( dt.IsObject() && !dt.IsReference() )
		{
			asSTypeBehaviour *beh = &dt.GetObjectType()->beh;
			if( dt.GetObjectType()->flags & asOBJ_REF )
			{
				asASSERT( (dt.GetObjectType()->flags & asOBJ_NOCOUNT) || beh->release );
				if( beh->release )
				{
					asSSystemFunctionInterface::SClean clean;
					clean.op  = 0; // call release
					clean.ot  = dt.GetObjectType();
					clean.off = short(offset);
					internal->cleanArgs.PushLast(clean);
				}
			}
			else
			{
				asSSystemFunctionInterface::SClean clean;
				clean.op  = 1; // call free
				clean.ot  = dt.GetObjectType();
				clean.off = short(offset);

				// Call the destructor then free the memory
				if( beh->destruct )
					clean.op = 2; // call destruct, then free

				internal->cleanArgs.PushLast(clean);
			}
		}

		if( dt.IsObject() && !dt.IsObjectHandle() && !dt.IsReference() )
			offset += AS_PTR_SIZE;
		else
			offset += dt.GetSizeOnStackDWords();
	}

	return 0;
}
Пример #5
0
eTokenType asCTokenizer::GetToken(const char *source, size_t sourceLength, size_t *tokenLength, asETokenClass *tc) const
{
	asASSERT(source != 0);
	asASSERT(tokenLength != 0);

	eTokenType tokenType;
	size_t     tlen;
	asETokenClass t = ParseToken(source, sourceLength, tlen, tokenType);
	if( tc          ) *tc          = t;
	if( tokenLength ) *tokenLength = tlen;

	return tokenType;
}
Пример #6
0
// internal
void asCScriptFunction::JITCompile()
{
	if( funcType != asFUNC_SCRIPT )
		return;

	asASSERT( scriptData );

	asIJITCompiler *jit = engine->GetJITCompiler();
	if( !jit )
		return;

	// Make sure the function has been compiled with JitEntry instructions
	// For functions that has JitEntry this will be a quick test
	asUINT length;
	asDWORD *byteCode = GetByteCode(&length);
	asDWORD *end = byteCode + length;
	bool foundJitEntry = false;
	while( byteCode < end )
	{
		// Determine the instruction
		asEBCInstr op = asEBCInstr(*(asBYTE*)byteCode);
		if( op == asBC_JitEntry )
		{
			foundJitEntry = true;
			break;
		}

		// Move to next instruction
		byteCode += asBCTypeSize[asBCInfo[op].type];
	}

	if( !foundJitEntry )
	{
		asCString msg;
		msg.Format(TXT_NO_JIT_IN_FUNC_s, GetDeclaration());
		engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
	}

	// Release the previous function, if any
	if( scriptData->jitFunction )
	{
		engine->jitCompiler->ReleaseJITFunction(scriptData->jitFunction);
		scriptData->jitFunction = 0;
	}

	// Compile for native system
	int r = jit->CompileFunction(this, &scriptData->jitFunction);
	if( r < 0 )
		asASSERT( scriptData->jitFunction == 0 );
}
Пример #7
0
// 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;
}
Пример #8
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;
}
Пример #9
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;
}
Пример #10
0
void asCThreadManager::Unprepare()
{
	asASSERT(threadManager);

	if( threadManager == 0 )
		return;

	// It's necessary to protect this section so no
	// other thread attempts to call AddRef or Release
	// while clean up is in progress.
	ENTERCRITICALSECTION(threadManager->criticalSection);
	if( --threadManager->refCount == 0 )
	{
		// Make sure the local data is destroyed, at least for the current thread
		CleanupLocalData();

		// As the critical section will be destroyed together
		// with the thread manager we must first clear the global
		// variable in case a new thread manager needs to be created;
		asCThreadManager *mgr = threadManager;
		threadManager = 0;

		// Leave the critical section before it is destroyed
		LEAVECRITICALSECTION(mgr->criticalSection);

		asDELETE(mgr,asCThreadManager);
	}
	else
		LEAVECRITICALSECTION(threadManager->criticalSection);
}
Пример #11
0
asCFuncdefType::asCFuncdefType(asCScriptEngine *en, asCScriptFunction *func) : asCTypeInfo(en)
{
	asASSERT(func->funcType == asFUNC_FUNCDEF);
	asASSERT(func->funcdefType == 0);

	// A function pointer is special kind of reference type
	flags       = asOBJ_REF | asOBJ_FUNCDEF | (func->isShared ? asOBJ_SHARED : 0);
	name        = func->name;
	nameSpace   = func->nameSpace;
	module      = func->module;
	accessMask  = func->accessMask;
	funcdef     = func; // reference already counted by the asCScriptFunction constructor
	parentClass = 0;

	func->funcdefType = this;
}
// interface
const char *asCScriptFunction::GetDeclaration(bool includeObjectName) const
{
    asASSERT(threadManager);
    asCString *tempString = &threadManager->GetLocalData()->string;
    *tempString = GetDeclarationStr(includeObjectName);
    return tempString->AddressOf();
}
Пример #13
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;
}
eTokenType asCTokenizer::GetToken(const char *source, size_t sourceLength, size_t *tokenLength, asETokenClass *tc)
{
	asASSERT(source != 0);
	asASSERT(tokenLength != 0);

	this->source = source;
	this->sourceLength = sourceLength;

	asETokenClass t = ParseToken();
	if( tc ) *tc = t;

	// Copy the output to the token
	*tokenLength = this->tokenLength;

	return tokenType;
}
Пример #15
0
void asCGarbageCollector::GCEnumCallback(void *reference)
{
	// This function will only be called within the critical section gcCollecting
	asASSERT(isProcessing);

	if( detectState == countReferences_loop )
	{
		// Find the reference in the map
		asSMapNode<void*, asSIntTypePair> *cursor = 0;
		if( gcMap.MoveTo(&cursor, reference) )
		{
			// Decrease the counter in the map for the reference
			gcMap.GetValue(cursor).i--;
		}
	}
	else if( detectState == detectGarbage_loop2 )
	{
		// Find the reference in the map
		asSMapNode<void*, asSIntTypePair> *cursor = 0;
		if( gcMap.MoveTo(&cursor, reference) )
		{
			// Add the object to the list of objects to mark as alive
			liveObjects.PushLast(reference);
		}
	}
}
// internal
asCScriptFunction::~asCScriptFunction()
{
    // Clean user data
    if( userData && engine->cleanFunctionFunc )
        engine->cleanFunctionFunc(this);

    // Imported functions are not reference counted, nor are dummy
    // functions that are allocated on the stack
    asASSERT( funcType == asFUNC_DUMMY    ||
              funcType == asFUNC_IMPORTED ||
              refCount.get() == 0         );

    ReleaseReferences();

    // Tell engine to free the function id
    if( funcType != -1 && funcType != asFUNC_IMPORTED && id )
        engine->FreeScriptFunctionId(id);

    for( asUINT n = 0; n < variables.GetLength(); n++ )
    {
        asDELETE(variables[n],asSScriptVariable);
    }

    if( sysFuncIntf )
    {
        asDELETE(sysFuncIntf,asSSystemFunctionInterface);
    }

    for( asUINT p = 0; p < defaultArgs.GetLength(); p++ )
    {
        if( defaultArgs[p] )
            asDELETE(defaultArgs[p], asCString);
    }
}
Пример #17
0
// 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;
}
asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other)
{
	if( &other != this )
	{
		asASSERT( other.objType->DerivesFrom(objType) );

		asCScriptEngine *engine = objType->engine;

		// Copy all properties
		for( asUINT n = 0; n < objType->properties.GetLength(); n++ )
		{
			asCObjectProperty *prop = objType->properties[n];
			if( prop->type.IsObject() )
			{
				void **dst = (void**)(((char*)this) + prop->byteOffset);
				void **src = (void**)(((char*)&other) + prop->byteOffset);
				if( !prop->type.IsObjectHandle() )
					CopyObject(*src, *dst, prop->type.GetObjectType(), engine);
				else
					CopyHandle((asDWORD*)src, (asDWORD*)dst, prop->type.GetObjectType(), engine);
			}
			else
			{
				void *dst = ((char*)this) + prop->byteOffset;
				void *src = ((char*)&other) + prop->byteOffset;
				memcpy(dst, src, prop->type.GetSizeInMemoryBytes());
			}
		}
	}

	return *this;
}
Пример #19
0
void asCGarbageCollector::ReturnNode(asSMapNode_t *node)
{
	// This function will only be called within the critical section gcCollecting
	asASSERT(isProcessing);

	if( node )
		freeNodes.PushLast(node);
}
Пример #20
0
// internal
void asCScriptFunction::EnumReferences(asIScriptEngine *)
{
	asASSERT( funcType == asFUNC_DELEGATE );

	// Delegate
	if( objForDelegate )
		engine->GCEnumCallback(objForDelegate);
}
Пример #21
0
void asCGlobalProperty::SetInitFunc(asCScriptFunction *in_initFunc)
{
	// This should only be done once
	asASSERT( initFunc == 0 );

	initFunc = in_initFunc;
	initFunc->AddRefInternal();
}
Пример #22
0
void asCGlobalProperty::SetInitFunc(asCScriptFunction *initFunc)
{
	// This should only be done once
	asASSERT( this->initFunc == 0 );

	this->initFunc = initFunc;
	this->initFunc->AddRef();
}
Пример #23
0
// If base is 0 the string should be prefixed by 0x, 0d, 0o, or 0b to allow the function to automatically determine the radix
asQWORD asStringScanUInt64(const char *string, int base, size_t *numScanned)
{
	asASSERT(base == 10 || base == 16 || base == 0);

	const char *end = string;

	asQWORD res = 0;
	if( base == 10 )
	{
		while( *end >= '0' && *end <= '9' )
		{
			res *= 10;
			res += *end++ - '0';
		}
	}
	else
	{
		if( base == 0 && string[0] == '0')
		{
			// Determine the radix from the prefix
			switch( string[1] )
			{
			case 'b': case 'B': base = 2; break;
			case 'o': case 'O': base = 8; break;
			case 'd': case 'D': base = 10; break;
			case 'x': case 'X': base = 16; break;
			}
			end += 2;
		}

		asASSERT( base );

		if( base )
		{
			for( int nbr; (nbr = asCharToNbr(*end, base)) >= 0; end++ )
				res = res * base + nbr;
		}
	}

	if( numScanned )
		*numScanned = end - string;

	return res;
}
// interface
int asCScriptFunction::Release() const
{
    gcFlag = false;
    asASSERT( funcType != asFUNC_IMPORTED );
    int r = refCount.atomicDec();
    if( r == 0 && funcType != -1 ) // Dummy functions are allocated on the stack and cannot be deleted
        asDELETE(const_cast<asCScriptFunction*>(this),asCScriptFunction);

    return r;
}
Пример #25
0
// internal
// TODO: cleanup: This method should probably be a member of the engine
asCGlobalProperty *asCScriptFunction::GetPropertyByGlobalVarPtr(void *gvarPtr)
{
	asSMapNode<void*, asCGlobalProperty*> *node;
	if( engine->varAddressMap.MoveTo(&node, gvarPtr) )
	{
		asASSERT(gvarPtr == node->value->GetAddressOfValue());
		return node->value;
	}
	return 0;
}
Пример #26
0
bool asCDataType::IsEnumType() const
{
    // Do a sanity check on the objectType, to verify that we aren't trying to access memory after it has been released
    asASSERT(typeInfo == 0 || typeInfo->name.GetLength() < 100);

    if (typeInfo && (typeInfo->flags & asOBJ_ENUM))
        return true;

    return false;
}
Пример #27
0
void asCScriptObject::CopyHandle(asPWORD *src, asPWORD *dst, asCObjectType *objType, asCScriptEngine *engine)
{
	// asOBJ_NOCOUNT doesn't have addref or release behaviours
	asASSERT( (objType->flags & asOBJ_NOCOUNT) || (objType->beh.release && objType->beh.addref) );

	if( *dst && objType->beh.release )
		engine->CallObjectMethod(*(void**)dst, objType->beh.release);
	*dst = *src;
	if( *dst && objType->beh.addref )
		engine->CallObjectMethod(*(void**)dst, objType->beh.addref);
}
Пример #28
0
// interface
const char *asCModule::GetImportedFunctionDeclaration(int index)
{
	asCScriptFunction *func = GetImportedFunction(index);
	if( func == 0 ) return 0;

	asASSERT(threadManager);
	asCString *tempString = &threadManager->GetLocalData()->string;
	*tempString = func->GetDeclarationStr();

	return tempString->AddressOf();
}
Пример #29
0
// internal
void asCScriptFunction::ReleaseAllHandles(asIScriptEngine *)
{
	asASSERT( funcType == asFUNC_DELEGATE );

	// Release paramaters

	// Delegate
	if( objForDelegate )
		engine->ReleaseScriptObject(objForDelegate, funcForDelegate->GetObjectType());
	objForDelegate = 0;
}
// interface
const char *asCScriptFunction::GetVarDecl(asUINT index) const
{
    if( index >= variables.GetLength() )
        return 0;

    asASSERT(threadManager);
    asCString *tempString = &threadManager->GetLocalData()->string;
    *tempString = variables[index]->type.Format();
    *tempString += " " + variables[index]->name;

    return tempString->AddressOf();
}