Просмотр исходного кода

Migrated to AngelScript 2.21.0.
Removed manual invocation of AngelScript garbage collection.

Lasse Öörni 14 лет назад
Родитель
Сommit
40caea422e
38 измененных файлов с 1105 добавлено и 454 удалено
  1. 1 1
      Docs/Urho3D.dox
  2. 0 6
      Engine/Engine/Engine.cpp
  3. 0 1
      Engine/Engine/ScriptAPI.cpp
  4. 2 2
      Engine/Script/Addons.cpp
  5. 0 10
      Engine/Script/Script.cpp
  6. 0 2
      Engine/Script/Script.h
  7. 0 3
      Engine/Script/ScriptFile.cpp
  8. 1 1
      Readme.txt
  9. 38 34
      ThirdParty/AngelScript/include/angelscript.h
  10. 2 2
      ThirdParty/AngelScript/source/as_atomic.cpp
  11. 32 20
      ThirdParty/AngelScript/source/as_builder.cpp
  12. 16 0
      ThirdParty/AngelScript/source/as_bytecode.cpp
  13. 1 0
      ThirdParty/AngelScript/source/as_bytecode.h
  14. 1 1
      ThirdParty/AngelScript/source/as_callfunc.cpp
  15. 2 2
      ThirdParty/AngelScript/source/as_callfunc_ppc_64.cpp
  16. 2 1
      ThirdParty/AngelScript/source/as_callfunc_x64_msvc.cpp
  17. 208 0
      ThirdParty/AngelScript/source/as_callfunc_x64_msvc_asm.asm
  18. 40 63
      ThirdParty/AngelScript/source/as_compiler.cpp
  19. 2 3
      ThirdParty/AngelScript/source/as_compiler.h
  20. 64 4
      ThirdParty/AngelScript/source/as_config.h
  21. 67 9
      ThirdParty/AngelScript/source/as_context.cpp
  22. 6 5
      ThirdParty/AngelScript/source/as_context.h
  23. 11 4
      ThirdParty/AngelScript/source/as_criticalsection.h
  24. 361 143
      ThirdParty/AngelScript/source/as_gc.cpp
  25. 24 12
      ThirdParty/AngelScript/source/as_gc.h
  26. 43 37
      ThirdParty/AngelScript/source/as_module.cpp
  27. 14 14
      ThirdParty/AngelScript/source/as_module.h
  28. 34 32
      ThirdParty/AngelScript/source/as_objecttype.cpp
  29. 11 11
      ThirdParty/AngelScript/source/as_objecttype.h
  30. 14 2
      ThirdParty/AngelScript/source/as_parser.cpp
  31. 16 3
      ThirdParty/AngelScript/source/as_restore.cpp
  32. 18 2
      ThirdParty/AngelScript/source/as_scriptengine.cpp
  33. 4 2
      ThirdParty/AngelScript/source/as_scriptengine.h
  34. 46 13
      ThirdParty/AngelScript/source/as_scriptfunction.cpp
  35. 5 3
      ThirdParty/AngelScript/source/as_scriptfunction.h
  36. 6 1
      ThirdParty/AngelScript/source/as_scriptobject.cpp
  37. 1 4
      ThirdParty/AngelScript/source/as_texts.h
  38. 12 1
      ThirdParty/AngelScript/source/as_thread.cpp

+ 1 - 1
Docs/Urho3D.dox

@@ -56,7 +56,7 @@ Urho3D is greatly inspired by OGRE (http://www.ogre3d.org/) and Horde3D (http://
 
 Urho3D uses the following third-party libraries:
 
-- AngelScript 2.21.0 WIP (http://www.angelcode.com/angelscript/)
+- AngelScript 2.21.0 (http://www.angelcode.com/angelscript/)
 - ENet 1.3.1 (http://enet.bespin.org/)
 - FreeType 2.3.12 (http://www.freetype.org/)
 - GLee 5.4 (http://elf-stone.com/)

+ 0 - 6
Engine/Engine/Engine.cpp

@@ -253,12 +253,6 @@ void Engine::RunFrame()
     time->BeginFrame(timeStep_);
     
     Render();
-    
-    // If scripting initialized, garbage collect before getting the next time step
-    Script* script = GetSubsystem<Script>();
-    if (script)
-        script->GarbageCollect(false);
-    
     GetNextTimeStep();
     
     time->EndFrame();

+ 0 - 1
Engine/Engine/ScriptAPI.cpp

@@ -292,7 +292,6 @@ static void RegisterScript(asIScriptEngine* engine)
 {
     RegisterObject<Script>(engine, "Script");
     engine->RegisterObjectMethod("Script", "bool Execute(const String&in)", asMETHOD(Script, Execute), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Script", "void GarbageCollect(bool)", asMETHOD(Script, GarbageCollect), asCALL_THISCALL);
     engine->RegisterObjectMethod("Script", "void DumpAPI()", asMETHOD(Script, DumpAPI), asCALL_THISCALL);
     engine->RegisterObjectMethod("Script", "void set_defaultScriptFile(ScriptFile@+)", asMETHOD(Script, SetDefaultScriptFile), asCALL_THISCALL);
     engine->RegisterObjectMethod("Script", "ScriptFile@+ get_defaultScriptFile() const", asMETHOD(Script, GetDefaultScriptFile), asCALL_THISCALL);

+ 2 - 2
Engine/Script/Addons.cpp

@@ -89,7 +89,7 @@ static bool ScriptArrayTemplateCallback(asIObjectType* ot)
         if ((flags & asOBJ_VALUE) && !(flags & asOBJ_POD))
         {
             // Verify that there is a default constructor
-            for (int n = 0; n < subtype->GetBehaviourCount(); ++n)
+            for (unsigned n = 0; n < subtype->GetBehaviourCount(); ++n)
             {
                 asEBehaviours beh;
                 int funcId = subtype->GetBehaviourByIndex(n, &beh);
@@ -110,7 +110,7 @@ static bool ScriptArrayTemplateCallback(asIObjectType* ot)
         else if ((flags & asOBJ_REF))
         {
             // Verify that there is a default factory
-            for (int n = 0; n < subtype->GetFactoryCount(); ++n)
+            for (unsigned n = 0; n < subtype->GetFactoryCount(); ++n)
             {
                 int funcId = subtype->GetFactoryIdByIndex(n);
                 asIScriptFunction* func = ot->GetEngine()->GetFunctionDescriptorById(funcId);

+ 0 - 10
Engine/Script/Script.cpp

@@ -184,16 +184,6 @@ bool Script::Execute(const String& line)
     return success;
 }
 
-void Script::GarbageCollect(bool fullCycle)
-{
-    PROFILE(GarbageCollect);
-    
-    if (fullCycle)
-        scriptEngine_->GarbageCollect(asGC_FULL_CYCLE);
-    else
-        scriptEngine_->GarbageCollect(asGC_ONE_STEP);
-}
-
 void Script::SetDefaultScriptFile(ScriptFile* file)
 {
     defaultScriptFile_ = file;

+ 0 - 2
Engine/Script/Script.h

@@ -58,8 +58,6 @@ public:
     
     /// Compile and execute a line of script in immediate mode
     bool Execute(const String& line);
-    /// Perform garbage collection
-    void GarbageCollect(bool fullCycle);
     /// Set immediate mode script file
     void SetDefaultScriptFile(ScriptFile* file);
     /// Set immediate mode scene

+ 0 - 3
Engine/Script/ScriptFile.cpp

@@ -520,9 +520,6 @@ void ScriptFile::ReleaseModule()
         methods_.Clear();
         UnsubscribeFromAllEventsWithUserData();
         
-        // Perform a full garbage collection cycle now
-        script_->GarbageCollect(true);
-        
         // Remove the module
         script_->GetModuleMap().Erase(scriptModule_);
         asIScriptEngine* engine = script_->GetScriptEngine();

+ 1 - 1
Readme.txt

@@ -36,7 +36,7 @@ Urho3D is greatly inspired by OGRE (http://www.ogre3d.org) and Horde3D
   http://timothylottes.blogspot.com/2011/04/nvidia-fxaa-ii-for-console.html
 
 Urho3D uses the following third-party libraries:
-- AngelScript 2.21.0 WIP (http://www.angelcode.com/angelscript/)
+- AngelScript 2.21.0 (http://www.angelcode.com/angelscript/)
 - ENet 1.3.1 (http://enet.bespin.org/)
 - FreeType 2.3.12 (http://www.freetype.org/)
 - GLee 5.4 (http://elf-stone.com/)

+ 38 - 34
ThirdParty/AngelScript/include/angelscript.h

@@ -90,7 +90,8 @@ enum asEEngineProp
 	asEP_INCLUDE_JIT_INSTRUCTIONS     = 12,
 	asEP_STRING_ENCODING              = 13,
 	asEP_PROPERTY_ACCESSOR_MODE       = 14,
-	asEP_EXPAND_DEF_ARRAY_TO_TMPL     = 15
+	asEP_EXPAND_DEF_ARRAY_TO_TMPL     = 15,
+	asEP_AUTO_GARBAGE_COLLECT         = 16
 };
 
 // Calling conventions
@@ -568,7 +569,7 @@ public:
 
 	// Garbage collection
 	virtual int  GarbageCollect(asDWORD flags = asGC_FULL_CYCLE) = 0;
-	virtual void GetGCStatistics(asUINT *currentSize, asUINT *totalDestroyed = 0, asUINT *totalDetected = 0) const = 0;
+	virtual void GetGCStatistics(asUINT *currentSize, asUINT *totalDestroyed = 0, asUINT *totalDetected = 0, asUINT *newObjects = 0, asUINT *totalNewDestroyed = 0) const = 0;
 	virtual void NotifyGarbageCollectorOfNewObject(void *obj, int typeId) = 0;
 	virtual void GCEnumCallback(void *reference) = 0;
 
@@ -591,23 +592,23 @@ public:
 	virtual const char      *GetName() const = 0;
 
 	// Compilation
-    virtual int  AddScriptSection(const char *name, const char *code, size_t codeLength = 0, int lineOffset = 0) = 0;
+	virtual int  AddScriptSection(const char *name, const char *code, size_t codeLength = 0, int lineOffset = 0) = 0;
 	virtual int  Build() = 0;
 	virtual int  CompileFunction(const char *sectionName, const char *code, int lineOffset, asDWORD compileFlags, asIScriptFunction **outFunc) = 0;
 	virtual int  CompileGlobalVar(const char *sectionName, const char *code, int lineOffset) = 0;
 
 	// Functions
-	virtual int                GetFunctionCount() const = 0;
-	virtual int                GetFunctionIdByIndex(int index) const = 0;
+	virtual asUINT             GetFunctionCount() const = 0;
+	virtual int                GetFunctionIdByIndex(asUINT index) const = 0;
 	virtual int                GetFunctionIdByName(const char *name) const = 0;
 	virtual int                GetFunctionIdByDecl(const char *decl) const = 0;
-	virtual asIScriptFunction *GetFunctionDescriptorByIndex(int index) const = 0;
+	virtual asIScriptFunction *GetFunctionDescriptorByIndex(asUINT index) const = 0;
 	virtual asIScriptFunction *GetFunctionDescriptorById(int funcId) const = 0;
 	virtual int                RemoveFunction(int funcId) = 0;
 
 	// Global variables
-	virtual int         ResetGlobalVars() = 0;
-	virtual int         GetGlobalVarCount() const = 0;
+	virtual int         ResetGlobalVars(asIScriptContext *ctx = 0) = 0;
+	virtual asUINT      GetGlobalVarCount() const = 0;
 	virtual int         GetGlobalVarIndexByName(const char *name) const = 0;
 	virtual int         GetGlobalVarIndexByDecl(const char *decl) const = 0;
 	virtual const char *GetGlobalVarDeclaration(asUINT index) const = 0;
@@ -616,27 +617,27 @@ public:
 	virtual int         RemoveGlobalVar(asUINT index) = 0;
 
 	// Type identification
-	virtual int            GetObjectTypeCount() const = 0;
+	virtual asUINT         GetObjectTypeCount() const = 0;
 	virtual asIObjectType *GetObjectTypeByIndex(asUINT index) const = 0;
 	virtual int            GetTypeIdByDecl(const char *decl) const = 0;
 
 	// Enums
-	virtual int         GetEnumCount() const = 0;
+	virtual asUINT      GetEnumCount() const = 0;
 	virtual const char *GetEnumByIndex(asUINT index, int *enumTypeId) const = 0;
 	virtual int         GetEnumValueCount(int enumTypeId) const = 0;
 	virtual const char *GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const = 0;
 
 	// Typedefs
-	virtual int         GetTypedefCount() const = 0;
+	virtual asUINT      GetTypedefCount() const = 0;
 	virtual const char *GetTypedefByIndex(asUINT index, int *typeId) const = 0;
 
 	// Dynamic binding between modules
-	virtual int         GetImportedFunctionCount() const = 0;
+	virtual asUINT      GetImportedFunctionCount() const = 0;
 	virtual int         GetImportedFunctionIndexByDecl(const char *decl) const = 0;
-	virtual const char *GetImportedFunctionDeclaration(int importIndex) const = 0;
-	virtual const char *GetImportedFunctionSourceModule(int importIndex) const = 0;
-	virtual int         BindImportedFunction(int importIndex, int funcId) = 0;
-	virtual int         UnbindImportedFunction(int importIndex) = 0;
+	virtual const char *GetImportedFunctionDeclaration(asUINT importIndex) const = 0;
+	virtual const char *GetImportedFunctionSourceModule(asUINT importIndex) const = 0;
+	virtual int         BindImportedFunction(asUINT importIndex, int funcId) = 0;
+	virtual int         UnbindImportedFunction(asUINT importIndex) = 0;
 	virtual int         BindAllImportedFunctions() = 0;
 	virtual int         UnbindAllImportedFunctions() = 0;
 
@@ -704,10 +705,11 @@ public:
 	virtual asIScriptFunction *GetFunction(asUINT stackLevel = 0) = 0;
 	virtual int                GetLineNumber(asUINT stackLevel = 0, int *column = 0, const char **sectionName = 0) = 0;
 	virtual int                GetVarCount(asUINT stackLevel = 0) = 0;
-	virtual const char        *GetVarName(int varIndex, asUINT stackLevel = 0) = 0;
-	virtual const char        *GetVarDeclaration(int varIndex, asUINT stackLevel = 0) = 0;
-	virtual int                GetVarTypeId(int varIndex, asUINT stackLevel = 0) = 0;
-	virtual void              *GetAddressOfVar(int varIndex, asUINT stackLevel = 0) = 0;
+	virtual const char        *GetVarName(asUINT varIndex, asUINT stackLevel = 0) = 0;
+	virtual const char        *GetVarDeclaration(asUINT varIndex, asUINT stackLevel = 0) = 0;
+	virtual int                GetVarTypeId(asUINT varIndex, asUINT stackLevel = 0) = 0;
+	virtual void              *GetAddressOfVar(asUINT varIndex, asUINT stackLevel = 0) = 0;
+	virtual bool               IsVarInScope(asUINT varIndex, asUINT stackLevel = 0) = 0;
 	virtual int                GetThisTypeId(asUINT stackLevel = 0) = 0;
 	virtual void              *GetThisPointer(asUINT stackLevel = 0) = 0;
 
@@ -804,29 +806,29 @@ public:
 	virtual int              GetSubTypeId() const = 0;
 
 	// Interfaces
-	virtual int              GetInterfaceCount() const = 0;
+	virtual asUINT           GetInterfaceCount() const = 0;
 	virtual asIObjectType   *GetInterface(asUINT index) const = 0;
 
 	// Factories
-	virtual int                GetFactoryCount() const = 0;
-	virtual int                GetFactoryIdByIndex(int index) const = 0;
+	virtual asUINT             GetFactoryCount() const = 0;
+	virtual int                GetFactoryIdByIndex(asUINT index) const = 0;
 	virtual int                GetFactoryIdByDecl(const char *decl) const = 0;
 
 	// Methods
-	virtual int                GetMethodCount() const = 0;
-	virtual int                GetMethodIdByIndex(int index, bool getVirtual = true) const = 0;
+	virtual asUINT             GetMethodCount() const = 0;
+	virtual int                GetMethodIdByIndex(asUINT index, bool getVirtual = true) const = 0;
 	virtual int                GetMethodIdByName(const char *name, bool getVirtual = true) const = 0;
 	virtual int                GetMethodIdByDecl(const char *decl, bool getVirtual = true) const = 0;
-	virtual asIScriptFunction *GetMethodDescriptorByIndex(int index, bool getVirtual = true) const = 0;
+	virtual asIScriptFunction *GetMethodDescriptorByIndex(asUINT index, bool getVirtual = true) const = 0;
 
 	// Properties
-	virtual int         GetPropertyCount() const = 0;
-	virtual int         GetProperty(asUINT index, const char **name, int *typeId = 0, bool *isPrivate = 0, int *offset = 0) const = 0;
+	virtual asUINT      GetPropertyCount() const = 0;
+	virtual int         GetProperty(asUINT index, const char **name, int *typeId = 0, bool *isPrivate = 0, int *offset = 0, bool *isReference = 0) const = 0;
 	virtual const char *GetPropertyDeclaration(asUINT index) const = 0;
 
 	// Behaviours
-	virtual int GetBehaviourCount() const = 0;
-	virtual int GetBehaviourByIndex(asUINT index, asEBehaviours *outBehaviour) const = 0;
+	virtual asUINT GetBehaviourCount() const = 0;
+	virtual int    GetBehaviourByIndex(asUINT index, asEBehaviours *outBehaviour) const = 0;
 
 protected:
 	virtual ~asIObjectType() {}
@@ -853,14 +855,15 @@ public:
 	virtual bool             IsReadOnly() const = 0;
 	virtual bool             IsPrivate() const = 0;
 
-	virtual int              GetParamCount() const = 0;
-	virtual int              GetParamTypeId(int index, asDWORD *flags = 0) const = 0;
+	virtual asUINT           GetParamCount() const = 0;
+	virtual int              GetParamTypeId(asUINT index, asDWORD *flags = 0) const = 0;
 	virtual int              GetReturnTypeId() const = 0;
 
 	// Debug information
-	virtual int              GetVarCount() const = 0;
+	virtual asUINT           GetVarCount() const = 0;
 	virtual int              GetVar(asUINT index, const char **name, int *typeId = 0) const = 0;
 	virtual const char *     GetVarDecl(asUINT index) const = 0;
+	virtual int              FindNextLineWithCode(int line) const = 0;
 
 	// For JIT compilation
 	virtual asDWORD         *GetByteCode(asUINT *length = 0) = 0;
@@ -1272,6 +1275,7 @@ enum asEBCInstr
 	asBC_MAXBYTECODE	= 186,
 
 	// Temporary tokens. Can't be output to the final program
+	asBC_VarDecl        = 251,
 	asBC_Block          = 252,
 	asBC_ObjInfo		= 253,
 	asBC_LINE			= 254,
@@ -1612,8 +1616,8 @@ const asSBCInfo asBCInfo[256] =
 	asBCINFO_DUMMY(248),
 	asBCINFO_DUMMY(249),
 	asBCINFO_DUMMY(250),
-	asBCINFO_DUMMY(251),
 
+	asBCINFO(VarDecl,   W_ARG,          0),
 	asBCINFO(Block,     INFO,           0),
 	asBCINFO(ObjInfo,	rW_DW_ARG,		0),
 	asBCINFO(LINE,		INFO,			0),

+ 2 - 2
ThirdParty/AngelScript/source/as_atomic.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2010 Andreas Jonsson
+   Copyright (c) 2003-2011 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -122,7 +122,7 @@ asDWORD asCAtomic::atomicDec()
 	return InterlockedDecrement((LONG*)&value);
 }
 
-#elif defined(AS_LINUX) || defined(AS_BSD)
+#elif defined(AS_LINUX) || defined(AS_BSD) || defined(AS_ILLUMOS)
 
 //
 // atomic_inc_and_test() and atomic_dec_and_test() from asm/atomic.h is not meant 

+ 32 - 20
ThirdParty/AngelScript/source/as_builder.cpp

@@ -1627,20 +1627,6 @@ void asCBuilder::CompileClasses()
 				else
 				{
 					decl->objType->interfaces.PushLast(objType);
-
-					// Make sure all the methods of the interface are implemented
-					for( asUINT i = 0; i < objType->methods.GetLength(); i++ )
-					{
-						if( !DoesMethodExist(decl->objType, objType->methods[i]) )
-						{
-							int r, c;
-							file->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
-							asCString str;
-							str.Format(TXT_MISSING_IMPLEMENTATION_OF_s,
-								engine->GetFunctionDeclaration(objType->methods[i]).AddressOf());
-							WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
-						}
-					}
 				}
 			}
 
@@ -1802,6 +1788,29 @@ void asCBuilder::CompileClasses()
 		toValidate.PushLast(decl);
 	}
 
+	// Verify that all interface methods are implemented in the classes
+	// We do this here so the base class' methods have already been inherited 
+	for( n = 0; n < classDeclarations.GetLength(); n++ )
+	{
+		sClassDeclaration *decl = classDeclarations[n];
+		for( asUINT m = 0; m < decl->objType->interfaces.GetLength(); m++ )
+		{
+			asCObjectType *objType = decl->objType->interfaces[m];
+			for( asUINT i = 0; i < objType->methods.GetLength(); i++ )
+			{
+				if( !DoesMethodExist(decl->objType, objType->methods[i]) )
+				{
+					int r, c;
+					decl->script->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
+					asCString str;
+					str.Format(TXT_MISSING_IMPLEMENTATION_OF_s,
+						engine->GetFunctionDeclaration(objType->methods[i]).AddressOf());
+					WriteError(decl->script->name.AddressOf(), str.AddressOf(), r, c);
+				}
+			}
+		}
+	}
+
 	// Verify that the declared structures are valid, e.g. that the structure
 	// doesn't contain a member of its own type directly or indirectly
 	while( toValidate.GetLength() > 0 )
@@ -1890,8 +1899,6 @@ void asCBuilder::CompileClasses()
 
 	if( numErrors > 0 ) return;
 
-	// TODO: The declarations form a graph, all circles in
-	//       the graph must be flagged as potential circles
 
 	// Urho3D: disable garbage collection from script classes
 	/*
@@ -1909,17 +1916,22 @@ void asCBuilder::CompileClasses()
 			{
 				if( dt.IsObjectHandle() )
 				{
-					// TODO: Can this handle really generate a circular reference?
-					//       Only if the handle is of a type that can reference this type, either directly or indirectly
+					// TODO: optimize: If it is known that the handle can't be involved in a circular reference
+					//                 then this object doesn't need to be marked as garbage collected. 
+					//                 - The application could set a flag when registering the object.
+					//                 - The script classes can be marked as final, then the compiler will 
+					//                   be able to determine whether the class is garbage collected or not.
 
 					ot->flags |= asOBJ_GC;
+					break;
 				}
 				else if( dt.GetObjectType()->flags & asOBJ_GC )
 				{
-					// TODO: Just because the member type is a potential circle doesn't mean that this one is
-					//       Only if the object is of a type that can reference this type, either directly or indirectly
+					// TODO: optimize: Just because the member type is a potential circle doesn't mean that this one is
+					//                 Only if the object is of a type that can reference this type, either directly or indirectly
 
 					ot->flags |= asOBJ_GC;
+					break;
 				}
 			}
 		}

+ 16 - 0
ThirdParty/AngelScript/source/as_bytecode.cpp

@@ -1261,6 +1261,10 @@ void asCByteCode::ExtractObjectVariableInfo(asCScriptFunction *outFunc)
 			info.option         = *(int*)ARG_DW(instr->arg);
 			outFunc->objVariableInfo.PushLast(info);
 		}
+		else if( instr->op == asBC_VarDecl )
+		{
+			outFunc->variables[instr->wArg[0]]->declaredAtProgramPos = pos;
+		}
 		else
 			pos += instr->size;
 
@@ -1473,6 +1477,18 @@ void asCByteCode::Block(bool start)
 	last->wArg[0]  = start ? 1 : 0;
 }
 
+void asCByteCode::VarDecl(int varDeclIdx)
+{
+	if( AddInstruction() < 0 )
+		return;
+
+	last->op       = asBC_VarDecl;
+	last->size     = 0;
+	last->stackInc = 0;
+	last->wArg[0]  = (asWORD)varDeclIdx;
+}
+
+
 int asCByteCode::FindLabel(int label, cByteInstruction *from, cByteInstruction **dest, int *positionDelta)
 {
 	// Search forward

+ 1 - 0
ThirdParty/AngelScript/source/as_bytecode.h

@@ -96,6 +96,7 @@ public:
 	void Line(int line, int column);
 	void ObjInfo(int offset, int info);
 	void Block(bool start);
+	void VarDecl(int varDeclIdx);
 	void Call(asEBCInstr bc, int funcID, int pop);
 	void CallPtr(asEBCInstr bc, int funcPtrVar, int pop);
 	void Alloc(asEBCInstr bc, void *objID, int funcID, int pop);

+ 1 - 1
ThirdParty/AngelScript/source/as_callfunc.cpp

@@ -161,7 +161,7 @@ int PrepareSystemFunction(asCScriptFunction *func, asSSystemFunctionInterface *i
 		else if( objType & asOBJ_APP_CLASS )
 		{
 			internal->hostReturnFloat = false;
-			if( objType & COMPLEX_MASK )
+			if( objType & COMPLEX_RETURN_MASK )
 			{
 				internal->hostReturnInMemory = true;
 				internal->hostReturnSize     = sizeof(void*)/4;

+ 2 - 2
ThirdParty/AngelScript/source/as_callfunc_ppc_64.cpp

@@ -664,14 +664,14 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
 		{
 			if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() )
 			{
-				#ifdef COMPLEX_OBJS_PASSED_BY_REF
+#ifdef COMPLEX_OBJS_PASSED_BY_REF
 				if( descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK )
 				{
 					paramBuffer[dpos++] = args[spos++];
 					++paramSize;
 				}
 				else
-				#endif
+#endif
 				{
 					// NOTE: we may have to do endian flipping here
 

+ 2 - 1
ThirdParty/AngelScript/source/as_callfunc_x64_msvc.cpp

@@ -101,7 +101,8 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
 	{
 		if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() )
 		{
-			if( descr->parameterTypes[n].GetSizeInMemoryDWords() >= AS_LARGE_OBJ_MIN_SIZE )
+			if( descr->parameterTypes[n].GetSizeInMemoryDWords() >= AS_LARGE_OBJ_MIN_SIZE ||
+				(descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK) )
 			{
 				allArgBuffer[dpos++] = *(asQWORD*)&args[spos];
 				spos += AS_PTR_SIZE;

+ 208 - 0
ThirdParty/AngelScript/source/as_callfunc_x64_msvc_asm.asm

@@ -0,0 +1,208 @@
+;
+;  AngelCode Scripting Library
+;  Copyright (c) 2003-2011 Andreas Jonsson
+;
+;  This software is provided 'as-is', without any express or implied 
+;  warranty. In no event will the authors be held liable for any 
+;  damages arising from the use of this software.
+;
+;  Permission is granted to anyone to use this software for any 
+;  purpose, including commercial applications, and to alter it and 
+;  redistribute it freely, subject to the following restrictions:
+;
+;  1. The origin of this software must not be misrepresented; you 
+;     must not claim that you wrote the original software. If you use
+;     this software in a product, an acknowledgment in the product 
+;     documentation would be appreciated but is not required.
+;
+;  2. Altered source versions must be plainly marked as such, and 
+;     must not be misrepresented as being the original software.
+;
+;  3. This notice may not be removed or altered from any source 
+;     distribution.
+;
+;  The original version of this library can be located at:
+;  http://www.angelcode.com/angelscript/
+;
+;  Andreas Jonsson
+;  [email protected]
+;
+
+.code
+PUBLIC CallX64
+
+; asQWORD CallX64(const asQWORD *args, const asQWORD *floatArgs, int paramSize, asQWORD func)
+
+CallX64 PROC FRAME
+
+	; PROLOG
+
+	; We must save preserved registers that are used
+	; TODO: No need to save unused registers
+
+	push rbp
+.pushreg rbp
+	push rsi
+.pushreg rsi
+	push r11
+.pushreg r11
+	push rdi
+.pushreg rdi
+	push r12
+.pushreg r12
+	push r13
+.pushreg r13
+	push r14
+.pushreg r14
+	push r15
+.pushreg r15
+	push rbx
+.pushreg rbx
+	sub rsp, 050h
+.allocstack 050h
+	mov rbp, rsp
+.setframe rbp, 0
+.endprolog
+
+	; Move function param to non-scratch register
+	mov r14, r9		; r14 = function
+
+	; Allocate space on the stack for the arguments
+	; Make room for at least 4 arguments even if there are less. When
+    ; the compiler does optimizations for speed it may use these for 
+	; temporary storage.
+	mov rdi, r8
+	add rdi, 32
+
+	; Make sure the stack pointer is 16byte aligned so the
+	; whole program optimizations will work properly
+	; TODO: optimize: Can this be optimized with fewer instructions?
+	mov rsi, rsp
+	sub rsi, rdi
+	and rsi, 8h
+	add rdi, rsi	
+	sub rsp, rdi
+		
+	; Jump straight to calling the function if no parameters
+	cmp r8d, 0		; Compare paramSize with 0
+	je	callfunc	; Jump to call funtion if (paramSize == 0)
+
+	; Move params to non-scratch registers
+	mov rsi, rcx	; rsi = pArgs
+	mov r11, rdx	; r11 = pFloatArgs (can be NULL)
+	mov r12d, r8d	; r12 = paramSize
+	
+	; Copy arguments from script stack to application stack
+	; Order is (first to last):
+	; rcx, rdx, r8, r9 & everything else goes on stack
+	mov rcx, qword ptr [rsi]
+	mov rdx, qword ptr [rsi + 8]
+	mov r8,  qword ptr [rsi + 16]
+	mov r9,  qword ptr [rsi + 24]
+	
+	; Negate the 4 params from the size to be copied
+	sub r12d, 32
+	js  copyfloat	; Jump if negative result
+	jz	copyfloat	; Jump if zero result
+	
+	; Now copy all remaining params onto stack allowing space for first four
+	; params to be flushed back to the stack if required by the callee.
+	
+	add rsi, 32		; Position input pointer 4 args ahead
+	mov r13, rsp	; Put the stack pointer into r13
+	add r13, 32	 	; Leave space for first 4 args on stack
+
+copyoverflow:
+	mov r15, qword ptr [rsi]	; Read param from source stack into r15
+	mov qword ptr [r13], r15	; Copy param to real stack
+	add r13, 8					; Move virtual stack pointer
+	add rsi, 8					; Move source stack pointer
+	sub r12d, 8					; Decrement remaining count
+	jnz copyoverflow			; Continue if more params
+
+copyfloat:
+	; Any floating point params?
+	cmp r11, 0
+	je  callfunc
+	
+	movlpd xmm0, qword ptr [r11]
+	movlpd xmm1, qword ptr [r11 + 8]
+	movlpd xmm2, qword ptr [r11 + 16]
+	movlpd xmm3, qword ptr [r11 + 24]
+	
+callfunc:
+	
+	; Call function
+	call r14
+	
+	; Restore the stack
+	mov rsp, rbp
+		
+	; EPILOG: Restore stack & preserved registers
+	add rsp, 050h
+	pop rbx
+	pop r15
+	pop r14
+	pop r13
+	pop r12
+	pop rdi
+	pop r11
+	pop rsi
+	pop rbp
+
+	; return value in RAX
+	ret
+
+CallX64 ENDP
+
+
+PUBLIC GetReturnedFloat
+
+; asDWORD GetReturnedFloat()
+
+GetReturnedFloat PROC FRAME
+
+	; PROLOG: Store registers and allocate stack space
+	
+	sub rsp, 8   ; We'll need 4 bytes for temporary storage (8 bytes with alignment)
+.allocstack 8
+.endprolog
+
+	; Move the float value from the XMM0 register to RAX register
+	movss dword ptr [rsp], xmm0
+	mov   eax, dword ptr [rsp]
+	
+	; EPILOG: Clean up
+	
+	add rsp, 8
+
+	ret
+
+GetReturnedFloat ENDP
+
+
+PUBLIC GetReturnedDouble
+
+; asDWORD GetReturnedDouble()
+
+GetReturnedDouble PROC FRAME
+
+	; PROLOG: Store registers and allocate stack space
+	
+	sub rsp, 8	; We'll need 8 bytes for temporary storage
+.allocstack 8
+.endprolog
+
+	; Move the double value from the XMM0 register to the RAX register
+	movlpd qword ptr [rsp], xmm0
+	mov    rax, qword ptr [rsp]
+	
+	; EPILOG: Clean up
+	
+	add rsp, 8
+	
+	ret
+	
+GetReturnedDouble ENDP
+
+END

+ 40 - 63
ThirdParty/AngelScript/source/as_compiler.cpp

@@ -95,8 +95,6 @@ void asCCompiler::Reset(asCBuilder *builder, asCScriptCode *script, asCScriptFun
 	continueLabels.SetLength(0);
 
 	byteCode.ClearAll();
-
-	globalExpression = false;
 }
 
 int asCCompiler::CompileDefaultConstructor(asCBuilder *builder, asCScriptCode *script, asCScriptFunction *outFunc)
@@ -282,6 +280,8 @@ int asCCompiler::CompileFunction(asCBuilder *builder, asCScriptCode *script, asC
 			if( vs.DeclareVariable(name.AddressOf(), type, stackPos, true) < 0 )
 				Error(TXT_PARAMETER_ALREADY_DECLARED, node);
 
+			// Add marker for variable declaration
+			byteCode.VarDecl((int)outFunc->variables.GetLength());
 			outFunc->AddVariable(name, type, stackPos);
 
 			node = node->next;
@@ -744,7 +744,6 @@ void asCCompiler::CompileStatementBlock(asCScriptNode *block, bool ownVariableSc
 int asCCompiler::CompileGlobalVariable(asCBuilder *builder, asCScriptCode *script, asCScriptNode *node, sGlobalVariableDescription *gvar, asCScriptFunction *outFunc)
 {
 	Reset(builder, script, outFunc);
-	globalExpression = true;
 
 	// Add a variable scope (even though variables can't be declared)
 	AddVariableScope();
@@ -1406,7 +1405,12 @@ void asCCompiler::MoveArgsToStack(int funcID, asCByteCode *bc, asCArray<asSExprC
 				{
 					// Send the object as a reference to the object, 
 					// and not to the variable holding the object
-					bc->InstrWORD(asBC_GETOBJREF, (asWORD)offset);
+					if( !IsVariableOnHeap(args[n]->type.stackOffset) )
+						// TODO: optimize: Actually the reference can be pushed on the stack directly
+						//                 as the value allocated on the stack is guaranteed to be safe
+						bc->InstrWORD(asBC_GETREF, (asWORD)offset);
+					else
+						bc->InstrWORD(asBC_GETOBJREF, (asWORD)offset);
 				}
 				else
 					bc->InstrWORD(asBC_GETREF, (asWORD)offset);
@@ -1710,6 +1714,8 @@ void asCCompiler::CompileDeclaration(asCScriptNode *decl, asCByteCode *bc)
 			return;
 		}
 
+		// Add marker that the variable has been declared
+		bc->VarDecl((int)outFunc->variables.GetLength());
 		outFunc->AddVariable(name, type, offset);
 
 		// Keep the node for the variable decl
@@ -3785,7 +3791,7 @@ bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, boo
 
 #ifdef AS_64BIT_PTR
 				int offset = AllocateVariable(asCDataType::CreatePrimitive(ttUInt64, false), true);
-				ctx->bc.InstrW_QW(asBC_SetV8, offset, 0);
+				ctx->bc.InstrW_QW(asBC_SetV8, (asWORD)offset, 0);
 				ctx->bc.InstrW_W(asBC_CMPi64, ctx->type.stackOffset, offset);
 				DeallocateVariable(offset);
 #else
@@ -4846,7 +4852,9 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData
 		if( from->type.dataType.IsFloatType() )
 		{
 			float fc = from->type.floatValue;
-			asUINT uic = asUINT(fc);
+			// Some compilers set the value to 0 when converting a negative float to unsigned int.
+			// To maintain a consistent behaviour across compilers we convert to int first.
+			asUINT uic = asUINT(int(fc));
 
 			if( float(uic) != fc )
 			{
@@ -4862,7 +4870,9 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData
 		else if( from->type.dataType.IsDoubleType() )
 		{
 			double fc = from->type.doubleValue;
-			asUINT uic = asUINT(fc);
+			// Some compilers set the value to 0 when converting a negative double to unsigned int.
+			// To maintain a consistent behaviour across compilers we convert to int first.
+			asUINT uic = asUINT(int(fc));
 
 			if( double(uic) != fc )
 			{
@@ -5101,7 +5111,7 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData
 		}
 		else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 2 )
 		{
-			float fc = float((signed)from->type.qwordValue);
+			float fc = float((asINT64)from->type.qwordValue);
 
 			if( asQWORD(fc) != from->type.qwordValue )
 			{
@@ -5196,7 +5206,7 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData
 		}
 		else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 2 )
 		{
-			double fc = double((signed)from->type.qwordValue);
+			double fc = double((asINT64)from->type.qwordValue);
 
 			if( asQWORD(fc) != from->type.qwordValue )
 			{
@@ -5443,13 +5453,6 @@ int asCCompiler::CompileAssignment(asCScriptNode *expr, asSExprContext *ctx)
 	asCScriptNode *lexpr = expr->firstChild;
 	if( lexpr->next )
 	{
-		if( globalExpression )
-		{
-			Error(TXT_ASSIGN_IN_GLOBAL_EXPR, expr);
-			ctx->type.SetDummy();
-			return -1;
-		}
-
 		// Compile the two expression terms
 		asSExprContext lctx(engine), rctx(engine);
 		int rr = CompileAssignment(lexpr->next->next, &rctx);
@@ -5856,12 +5859,12 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s
 			{
 				// This is an index access, check if there is a property accessor that takes an index arg
 				asSExprContext dummyArg(engine);
-				r = FindPropertyAccessor(name, &access, &dummyArg, errNode);
+				r = FindPropertyAccessor(name, &access, &dummyArg, errNode, true);
 			}
 			if( r == 0 )
 			{
 				// Normal property access
-				r = FindPropertyAccessor(name, &access, errNode);
+				r = FindPropertyAccessor(name, &access, errNode, true);
 			}
 			if( r < 0 ) return -1;
 			if( access.property_get || access.property_set )
@@ -6944,15 +6947,6 @@ void asCCompiler::CompileConstructCall(asCScriptNode *node, asSExprContext *ctx)
 		return;
 	}
 
-	if( globalExpression )
-	{
-		Error(TXT_FUNCTION_IN_GLOBAL_EXPR, node);
-
-		// Output dummy code
-		ctx->type.SetDummy();
-		return;
-	}
-
 	// Compile the arguments
 	asCArray<asSExprContext *> args;
 	asCArray<asCTypeInfo> temporaryVariables;
@@ -7124,8 +7118,8 @@ void asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx,
 	asCScriptNode *nm = node->lastChild->prev;
 	name.Assign(&script->code[nm->tokenPos], nm->tokenLength);
 
-	// TODO: funcdef: First check for a local variable of a function type
-	//                Must not allow function names, nor global variables to be returned in this instance
+	// First check for a local variable of a function type
+	// Must not allow function names, nor global variables to be returned in this instance
 	asSExprContext funcPtr(engine);
 	if( objectType == 0 )
 		r = CompileVariableAccess(name, scope, &funcPtr, node, true, true);
@@ -7156,19 +7150,18 @@ void asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx,
 			// TODO: funcdef: It is still possible that there is a global variable of a function type
 		}
 	}
-
-	if( funcs.GetLength() == 0 && funcPtr.type.dataType.GetFuncDef() )
+	else if( !funcPtr.type.dataType.GetFuncDef() )
 	{
-		funcs.PushLast(funcPtr.type.dataType.GetFuncDef()->id);
+		// The variable is not a function
+		asCString msg;
+		msg.Format(TXT_NOT_A_FUNC_s_IS_VAR, name.AddressOf());
+		Error(msg.AddressOf(), node);
+		return;
 	}
 
-	if( globalExpression )
+	if( funcs.GetLength() == 0 && funcPtr.type.dataType.GetFuncDef() )
 	{
-		Error(TXT_FUNCTION_IN_GLOBAL_EXPR, node);
-
-		// Output dummy code
-		ctx->type.SetDummy();
-		return;
+		funcs.PushLast(funcPtr.type.dataType.GetFuncDef()->id);
 	}
 
 	// Compile the arguments
@@ -7510,11 +7503,6 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx
 	{
 		// Need a reference to the primitive that will be updated
 		// The result of this expression is the same reference as before
-		if( globalExpression )
-		{
-			Error(TXT_INC_OP_IN_GLOBAL_EXPR, node);
-			return -1;
-		}
 
 		// Make sure the reference isn't a temporary variable
 		if( ctx->type.isTemporary )
@@ -7613,12 +7601,12 @@ void asCCompiler::ConvertToReference(asSExprContext *ctx)
 	}
 }
 
-int asCCompiler::FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asCScriptNode *node)
+int asCCompiler::FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asCScriptNode *node, bool isThisAccess)
 {
-	return FindPropertyAccessor(name, ctx, 0, node);
+	return FindPropertyAccessor(name, ctx, 0, node, isThisAccess);
 }
 
-int asCCompiler::FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node)
+int asCCompiler::FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node, bool isThisAccess)
 {
 	if( engine->ep.propertyAccessorMode == 0 )
 	{
@@ -7763,7 +7751,7 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asSExprContext *ctx
 	// Check if we are within one of the accessors
 	int realGetId = getId;
 	int realSetId = setId;
-	if( outFunc->objectType )
+	if( outFunc->objectType && isThisAccess )
 	{
 		// The property accessors would be virtual functions, so we need to find the real implementation
 		asCScriptFunction *getFunc = getId ? engine->scriptFunctions[getId] : 0;
@@ -7778,11 +7766,12 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asSExprContext *ctx
 			realSetId = outFunc->objectType->virtualFunctionTable[setFunc->vfTableIdx]->id;
 	}
 
-	if( (realGetId && realGetId == outFunc->id) ||
-		(realSetId && realSetId == outFunc->id) )
+	// Avoid recursive call, by not treating this as a property accessor call.
+	// This will also allow having the real property with the same name as the accessors.
+	if( (isThisAccess || outFunc->objectType == 0) &&
+		((realGetId && realGetId == outFunc->id) ||
+		 (realSetId && realSetId == outFunc->id)) )
 	{
-		// Avoid recursive call, by not treating this as a property accessor call.
-		// This will also allow having the real property with the same name as the accessors.
 		getId = 0;
 		setId = 0;
 	}
@@ -8093,12 +8082,6 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct
 	}
 	else if( op == ttInc || op == ttDec )
 	{
-		if( globalExpression )
-		{
-			Error(TXT_INC_OP_IN_GLOBAL_EXPR, node);
-			return -1;
-		}
-
 		// Make sure the reference isn't a temporary variable
 		if( ctx->type.isTemporary )
 		{
@@ -8263,12 +8246,6 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ct
 		}
 		else
 		{
-			if( globalExpression )
-			{
-				Error(TXT_METHOD_IN_GLOBAL_EXPR, node);
-				return -1;
-			}
-
 			// Make sure it is an object we are accessing
 			if( !ctx->type.dataType.IsObject() )
 			{

+ 2 - 3
ThirdParty/AngelScript/source/as_compiler.h

@@ -167,8 +167,8 @@ protected:
 	// Helper functions
 	void ProcessPropertyGetAccessor(asSExprContext *ctx, asCScriptNode *node);
 	int  ProcessPropertySetAccessor(asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node);
-	int  FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asCScriptNode *node);
-	int  FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node);
+	int  FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asCScriptNode *node, bool isThisAccess = false);
+	int  FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node, bool isThisAccess = false);
 	void SwapPostFixOperands(asCArray<asCScriptNode *> &postfix, asCArray<asCScriptNode *> &target);
 	void PrepareTemporaryObject(asCScriptNode *node, asSExprContext *ctx, asCArray<int> *reservedVars, bool forceOnHeap = false);
 	void PrepareOperand(asSExprContext *ctx, asCScriptNode *node);
@@ -259,7 +259,6 @@ protected:
 	asCArray<int>         freeVariables;
 	asCArray<int>         tempVariables;
 
-	bool globalExpression;
 	bool isCompilingDefaultArg;
 	bool isProcessingDeferredParams;
 	int noCodeOutput;

+ 64 - 4
ThirdParty/AngelScript/source/as_config.h

@@ -231,6 +231,7 @@
 // AS_IPHONE  - Apple IPhone
 // AS_ANDROID - Android
 // AS_HAIKU   - Haiku
+// AS_ILLUMOS - Illumos like (OpenSolaris, OpenIndiana, NCP, etc)
 
 
 
@@ -259,10 +260,14 @@
 // find the virtual base object. x is the method pointer received by the register
 // function;
 
-// COMPLEX_MASK
-// This constant shows what attributes determines if an object is returned in memory
+// COMPLEX_RETURN_MASK
+// This constant shows what attributes determine if an object is returned in memory
 // or in the registers as normal structures
 
+// COMPLEX_MASK
+// This constant shows what attributes determine if an object is implicitly passed 
+// by reference or not, even if the argument is declared by value
+
 // THISCALL_RETURN_SIMPLE_IN_MEMORY
 // CDECL_RETURN_SIMPLE_IN_MEMORY
 // STDCALL_RETURN_SIMPLE_IN_MEMORY
@@ -351,6 +356,7 @@
 
 	#define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK
 	#define COMPLEX_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR)
+	#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR)
 	#define STDCALL __stdcall
 	#define AS_SIZEOF_BOOL 1
 	#define AS_WINDOWS_THREADS
@@ -403,7 +409,6 @@
 		#define AS_XENON
 		#define AS_BIG_ENDIAN
 	#else
-		// Support native calling conventions on x86, but not 64bit yet
 		#if defined(_XBOX) || (defined(_M_IX86) && !defined(__LP64__))
 			#define AS_X86
 		#elif defined(_M_X64)
@@ -411,6 +416,9 @@
 			#define AS_CALLEE_DESTROY_OBJ_BY_VAL
 			#define AS_LARGE_OBJS_PASSED_BY_REF
 			#define AS_LARGE_OBJ_MIN_SIZE 3
+			#define COMPLEX_OBJS_PASSED_BY_REF
+			#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
+			#define COMPLEX_MASK (asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
 		#endif
 	#endif
 
@@ -428,12 +436,17 @@
 		#define STDCALL_RETURN_SIMPLE_IN_MEMORY
 		#define COMPLEX_OBJS_PASSED_BY_REF
 		#define COMPLEX_MASK asOBJ_APP_CLASS_ASSIGNMENT
+		#define COMPLEX_RETURN_MASK asOBJ_APP_CLASS_ASSIGNMENT
 	#endif
 
 	#ifndef COMPLEX_MASK
 		#define COMPLEX_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT)
 	#endif
 
+	#ifndef COMPLEX_RETURN_MASK
+		#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT)
+	#endif
+
 	#define UNREACHABLE_RETURN
 #endif
 
@@ -447,6 +460,7 @@
 	#define asVSNPRINTF(a, b, c, d) _vsnprintf(a, b, c, d)
 	#define THISCALL_CALLEE_POPS_ARGUMENTS
 	#define COMPLEX_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT)
+	#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT)
 	#define AS_SIZEOF_BOOL 1
 	#define AS_WINDOWS_THREADS
 	#define STDCALL __stdcall
@@ -474,6 +488,7 @@
 	#define COMPLEX_OBJS_PASSED_BY_REF
 	#define ASM_AT_N_T  // AT&T style inline assembly
 	#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR)
+	#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR)
 	#define AS_SIZEOF_BOOL 1
 	#define asVSNPRINTF(a, b, c, d) vsnprintf(a, b, c, d)
 
@@ -517,6 +532,7 @@
 	#define CALLEE_POPS_HIDDEN_RETURN_POINTER
 	#define COMPLEX_OBJS_PASSED_BY_REF
 	#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR)
+	#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR)
 	#define AS_NO_MEMORY_H
 	#define AS_SIZEOF_BOOL 1
 	#define STDCALL __attribute__((stdcall))
@@ -548,6 +564,8 @@
 			#define AS_X86
 			#undef COMPLEX_MASK
 			#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
+			#undef COMPLEX_RETURN_MASK
+			#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
 		#elif defined(__LP64__) && !defined(__ppc__) && !defined(__PPC__)
 			// http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/LowLevelABI/140-x86-64_Function_Calling_Conventions/x86_64.html#//apple_ref/doc/uid/TP40005035-SW1
 			#define AS_NO_THREADS
@@ -556,6 +574,8 @@
 			#define SPLIT_OBJS_BY_MEMBER_TYPES
 			#undef COMPLEX_MASK
 			#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
+			#undef COMPLEX_RETURN_MASK
+			#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
 			// STDCALL is not available on 64bit Mac
 			#undef STDCALL
 			#define STDCALL
@@ -567,6 +587,8 @@
 			#define STDCALL_RETURN_SIMPLE_IN_MEMORY
 			#undef COMPLEX_MASK
 			#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
+			#undef COMPLEX_RETURN_MASK
+			#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
 		#elif (defined(__ppc__) || defined(__PPC__)) && defined(__LP64__)
 			#define AS_PPC_64
 		#elif (defined(_ARM_) || defined(__arm__))
@@ -591,6 +613,8 @@
 			#define COMPLEX_OBJS_PASSED_BY_REF
 			#undef COMPLEX_MASK
 			#define COMPLEX_MASK asOBJ_APP_CLASS_DESTRUCTOR
+			#undef COMPLEX_RETURN_MASK
+			#define COMPLEX_RETURN_MASK asOBJ_APP_CLASS_DESTRUCTOR
 		#else
 			// Unknown CPU type
 			#define AS_MAX_PORTABILITY
@@ -606,6 +630,8 @@
 
 		#undef COMPLEX_MASK
 		#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
+		#undef COMPLEX_RETURN_MASK
+		#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
 
 		#if defined(i386) && !defined(__LP64__)
 			// Support native calling conventions on Intel 32bit CPU
@@ -631,6 +657,8 @@
 
 			#undef COMPLEX_MASK
 			#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
+			#undef COMPLEX_RETURN_MASK
+			#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
 
 			// Support native calling conventions on Intel 32bit CPU
 			#define AS_X86
@@ -640,6 +668,8 @@
 			#define SPLIT_OBJS_BY_MEMBER_TYPES
 			#undef COMPLEX_MASK
 			#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
+			#undef COMPLEX_RETURN_MASK
+			#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
 			// STDCALL is not available on 64bit Linux
 			#undef STDCALL
 			#define STDCALL
@@ -677,6 +707,8 @@
 		#if defined(i386) && !defined(__LP64__)
 			#undef COMPLEX_MASK
 			#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
+			#undef COMPLEX_RETURN_MASK
+			#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
 			#define AS_X86
 		#elif defined(__LP64__)
 			#define AS_X64_GCC
@@ -684,6 +716,8 @@
 			#define SPLIT_OBJS_BY_MEMBER_TYPES
 			#undef COMPLEX_MASK
 			#define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
+			#undef COMPLEX_RETURN_MASK
+			#define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR)
 			#undef STDCALL
 			#define STDCALL
 		#else
@@ -776,6 +810,32 @@
 			#define AS_NO_ATOMIC
 		#endif
 
+	// Illumos
+	#elif defined(__sun)
+		#if defined(__i386__) && !defined(__LP64__)
+			#define THISCALL_RETURN_SIMPLE_IN_MEMORY
+			#define CDECL_RETURN_SIMPLE_IN_MEMORY
+			#define STDCALL_RETURN_SIMPLE_IN_MEMORY
+
+			// Support native calling conventions on Intel 32bit CPU
+			#define AS_X86
+		#elif defined(__LP64__)
+			#define AS_X64_GCC
+			#define HAS_128_BIT_PRIMITIVES
+			#define SPLIT_OBJS_BY_MEMBER_TYPES
+			// STDCALL is not available on 64bit Linux
+			#undef STDCALL
+			#define STDCALL
+		#else
+			#define AS_MAX_PORTABILITY
+		#endif
+		#define AS_ILLUMOS
+		#define AS_POSIX_THREADS
+
+		#if !( ( (__GNUC__ == 4) && (__GNUC_MINOR__ >= 1) || __GNUC__ > 4) )
+			// Only with GCC 4.1 was the atomic instructions available
+			#define AS_NO_ATOMIC
+		#endif
 	#endif
 
 	#define I64(x) x##ll
@@ -829,7 +889,7 @@
 #endif
 
 // Is the target a 64bit system?
-#if defined(__LP64__) || defined(__amd64__) || defined(_M_X64)
+#if defined(__LP64__) || defined(__amd64__) || defined(__x86_64__) || defined(_M_X64)
 	#ifndef AS_64BIT_PTR
 		#define AS_64BIT_PTR
 	#endif

+ 67 - 9
ThirdParty/AngelScript/source/as_context.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2010 Andreas Jonsson
+   Copyright (c) 2003-2011 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -1096,6 +1096,8 @@ void asCContext::PopCallState()
 // interface
 asUINT asCContext::GetCallstackSize()
 {
+	if( currentFunction == 0 ) return 0;
+
 	// The current function is accessed at stackLevel 0
 	return asUINT(1 + callStack.GetLength() / CALLSTACK_FRAME_SIZE);
 }
@@ -3487,6 +3489,61 @@ void asCContext::CleanStack()
 	inExceptionHandler = false;
 }
 
+// Interface
+bool asCContext::IsVarInScope(asUINT varIndex, asUINT stackLevel)
+{
+	asASSERT( stackLevel < GetCallstackSize() );
+
+	asCScriptFunction *func;
+	asUINT pos;
+
+	if( stackLevel == 0 )
+	{
+		func = currentFunction;
+		pos = asUINT(regs.programPointer - func->byteCode.AddressOf());
+	}
+	else
+	{
+		size_t *s = callStack.AddressOf() + (GetCallstackSize()-stackLevel-1)*CALLSTACK_FRAME_SIZE;
+		func = (asCScriptFunction*)s[1];
+		pos = asUINT((asDWORD*)s[2] - func->byteCode.AddressOf());
+	}
+
+	// First determine if the program position is after the variable declaration
+	if( func->variables.GetLength() <= varIndex ) return false;
+	if( func->variables[varIndex]->declaredAtProgramPos > pos ) return false;
+
+	asUINT declaredAt = func->variables[varIndex]->declaredAtProgramPos;
+
+	// If the program position is after the variable declaration it is necessary 
+	// determine if the program position is still inside the statement block where 
+	// the variable was delcared.
+	for( int n = 0; n < (int)func->objVariableInfo.GetLength(); n++ )
+	{
+		if( func->objVariableInfo[n].programPos >= declaredAt )
+		{
+			// If the current block ends between the declaredAt and current 
+			// program position, then we know the variable is no longer visible
+			int level = 0;
+			for( ; n < (int)func->objVariableInfo.GetLength(); n++ )
+			{
+				if( func->objVariableInfo[n].programPos > pos )
+					break;
+
+				if( func->objVariableInfo[n].option == asBLOCK_BEGIN ) level++;
+				if( func->objVariableInfo[n].option == asBLOCK_END && --level < 0 )
+					return false;
+			}
+
+			break;
+		}
+	}
+
+	// Variable is visible
+	return true;
+}
+
+// Internal
 void asCContext::DetermineLiveObjects(asCArray<int> &liveObjects, asUINT stackLevel)
 {
 	asASSERT( stackLevel < GetCallstackSize() );
@@ -3623,10 +3680,11 @@ void asCContext::CleanStackFrame()
 			}
 		}
 
-		if( currentFunction->objectType )
+		// If the object is a script declared object, then we must release it
+		// as the compiler adds a reference at the entry of the function. Make sure
+		// the function has actually been entered
+		if( currentFunction->objectType && regs.programPointer != currentFunction->byteCode.AddressOf() )
 		{
-			// If the object is a script declared object, then we must release it
-			// as the compiler adds a reference at the entry of the function
 			asSTypeBehaviour *beh = &currentFunction->objectType->beh;
 			if( beh->release && *(size_t*)&regs.stackFramePointer[0] != 0 )
 			{
@@ -3884,7 +3942,7 @@ int asCContext::GetVarCount(asUINT stackLevel)
 }
 
 // interface
-const char *asCContext::GetVarName(int varIndex, asUINT stackLevel)
+const char *asCContext::GetVarName(asUINT varIndex, asUINT stackLevel)
 {
 	asIScriptFunction *func = GetFunction(stackLevel);
 	if( func == 0 ) return 0;
@@ -3895,7 +3953,7 @@ const char *asCContext::GetVarName(int varIndex, asUINT stackLevel)
 }
 
 // interface
-const char *asCContext::GetVarDeclaration(int varIndex, asUINT stackLevel)
+const char *asCContext::GetVarDeclaration(asUINT varIndex, asUINT stackLevel)
 {
 	asIScriptFunction *func = GetFunction(stackLevel);
 	if( func == 0 ) return 0;
@@ -3904,7 +3962,7 @@ const char *asCContext::GetVarDeclaration(int varIndex, asUINT stackLevel)
 }
 
 // interface
-int asCContext::GetVarTypeId(int varIndex, asUINT stackLevel)
+int asCContext::GetVarTypeId(asUINT varIndex, asUINT stackLevel)
 {
 	asIScriptFunction *func = GetFunction(stackLevel);
 	if( func == 0 ) return asINVALID_ARG;
@@ -3915,7 +3973,7 @@ int asCContext::GetVarTypeId(int varIndex, asUINT stackLevel)
 }
 
 // interface
-void *asCContext::GetAddressOfVar(int varIndex, asUINT stackLevel)
+void *asCContext::GetAddressOfVar(asUINT varIndex, asUINT stackLevel)
 {
 	if( stackLevel >= GetCallstackSize() ) return 0;
 
@@ -3936,7 +3994,7 @@ void *asCContext::GetAddressOfVar(int varIndex, asUINT stackLevel)
 	if( func == 0 )
 		return 0;
 
-	if( varIndex < 0 || varIndex >= (signed)func->variables.GetLength() )
+	if( varIndex >= func->variables.GetLength() )
 		return 0;
 
 	// For object variables it's necessary to dereference the pointer to get the address of the value

+ 6 - 5
ThirdParty/AngelScript/source/as_context.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2010 Andreas Jonsson
+   Copyright (c) 2003-2011 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -107,10 +107,11 @@ public:
 	asIScriptFunction *GetFunction(asUINT stackLevel);
 	int                GetLineNumber(asUINT stackLevel, int *column, const char **sectionName);
 	int                GetVarCount(asUINT stackLevel);
-	const char        *GetVarName(int varIndex, asUINT stackLevel);
-	const char        *GetVarDeclaration(int varIndex, asUINT stackLevel);
-	int                GetVarTypeId(int varIndex, asUINT stackLevel);
-	void              *GetAddressOfVar(int varIndex, asUINT stackLevel);
+	const char        *GetVarName(asUINT varIndex, asUINT stackLevel);
+	const char        *GetVarDeclaration(asUINT varIndex, asUINT stackLevel);
+	int                GetVarTypeId(asUINT varIndex, asUINT stackLevel);
+	void              *GetAddressOfVar(asUINT varIndex, asUINT stackLevel);
+	bool               IsVarInScope(asUINT varIndex, asUINT stackLevel);
 	int                GetThisTypeId(asUINT stackLevel);
     void              *GetThisPointer(asUINT stackLevel);
 

+ 11 - 4
ThirdParty/AngelScript/source/as_criticalsection.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2010 Andreas Jonsson
+   Copyright (c) 2003-2011 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -48,12 +48,14 @@ BEGIN_AS_NAMESPACE
 #define DECLARECRITICALSECTION(x) 
 #define ENTERCRITICALSECTION(x) 
 #define LEAVECRITICALSECTION(x) 
+#define TRYENTERCRITICALSECTION(x) true
 
 #else
 
-#define DECLARECRITICALSECTION(x) asCThreadCriticalSection x
-#define ENTERCRITICALSECTION(x)   x.Enter()
-#define LEAVECRITICALSECTION(x)   x.Leave()
+#define DECLARECRITICALSECTION(x)  asCThreadCriticalSection x
+#define ENTERCRITICALSECTION(x)    x.Enter()
+#define LEAVECRITICALSECTION(x)    x.Leave()
+#define TRYENTERCRITICALSECTION(x) x.TryEnter()
 
 #ifdef AS_POSIX_THREADS
 
@@ -69,6 +71,7 @@ public:
 
 	void Enter();
 	void Leave();
+	bool TryEnter();
 
 protected:
 	pthread_mutex_t criticalSection;
@@ -81,6 +84,9 @@ END_AS_NAMESPACE
 #include <xtl.h>
 #else
 #define WIN32_LEAN_AND_MEAN
+#ifndef _WIN32_WINNT
+  #define _WIN32_WINNT 0x0400 // We need this to get the declaration for TryEnterCriticalSection
+#endif
 #include <windows.h>
 #endif
 BEGIN_AS_NAMESPACE
@@ -96,6 +102,7 @@ public:
 
 	void Enter();
 	void Leave();
+	bool TryEnter();
 
 protected:
 	CRITICAL_SECTION criticalSection;

+ 361 - 143
ThirdParty/AngelScript/source/as_gc.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2010 Andreas Jonsson
+   Copyright (c) 2003-2011 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied
    warranty. In no event will the authors be held liable for any
@@ -46,150 +46,234 @@ BEGIN_AS_NAMESPACE
 
 asCGarbageCollector::asCGarbageCollector()
 {
-	engine       = 0;
-	detectState  = clearCounters_init;
-	destroyState = destroyGarbage_init;
-	numDestroyed = 0;
-	numDetected  = 0;
+	engine          = 0;
+	detectState     = clearCounters_init;
+	destroyNewState = destroyGarbage_init;
+	destroyOldState = destroyGarbage_init;
+	numDestroyed    = 0;
+	numNewDestroyed = 0;
+	numDetected     = 0;
 }
 
 void asCGarbageCollector::AddScriptObjectToGC(void *obj, asCObjectType *objType)
 {
 	engine->CallObjectMethod(obj, objType->beh.addref);
-	asSObjTypePair ot = {obj, objType};
+	asSObjTypePair ot = {obj, objType, 0};
+
+	// Invoke the garbage collector to destroy a little garbage as new comes in
+	// This will maintain the number of objects in the GC at a maintainable level without
+	// halting the application, and without burdening the application with manually invoking the 
+	// garbage collector.
+	if( engine->ep.autoGarbageCollect && gcNewObjects.GetLength() )
+	{
+		// If the GC is already processing in another thread, then don't try this again
+		// TODO: What if it is already processing in this thread?
+		if( TRYENTERCRITICALSECTION(gcCollecting) )
+		{
+			// TODO: The number of iterations should be dynamic, and increase 
+			//       if the number of objects in the garbage collector grows high
+
+			// Run one step of DetectGarbage
+			if( gcOldObjects.GetLength() )
+			{
+				IdentifyGarbageWithCyclicRefs();
+				DestroyOldGarbage();
+			}
+
+			// Run a few steps of DestroyGarbage
+			int iter = (int)gcNewObjects.GetLength();
+			if( iter > 10 ) iter = 10;
+			while( iter-- > 0 )
+				DestroyNewGarbage();
+
+			LEAVECRITICALSECTION(gcCollecting);
+		}
+	}
 
 	// Add the data to the gcObjects array in a critical section as
 	// another thread might be calling this method at the same time
 	ENTERCRITICALSECTION(gcCritical);
-	gcObjects.PushLast(ot);
+	gcNewObjects.PushLast(ot);
 	LEAVECRITICALSECTION(gcCritical);
 }
 
 int asCGarbageCollector::GarbageCollect(asDWORD flags)
 {
-	// The application is responsible for making sure
-	// the gc is only executed by one thread at a time.
-
-	bool doDetect  = (flags & asGC_DETECT_GARBAGE)  || !(flags & asGC_DESTROY_GARBAGE);
-	bool doDestroy = (flags & asGC_DESTROY_GARBAGE) || !(flags & asGC_DETECT_GARBAGE);
-
-	if( flags & asGC_FULL_CYCLE )
+	// If the GC is already processing in another thread, then don't enter here again
+	// TODO: What if it is already processing in this thread?
+	if( TRYENTERCRITICALSECTION(gcCollecting) )
 	{
-		// Reset the state
-		if( doDetect )
-			detectState  = clearCounters_init;
-		if( doDestroy )
-			destroyState = destroyGarbage_init;
-
-		int r = 1;
-		unsigned int count = (unsigned int)gcObjects.GetLength();
-		for(;;)
+		bool doDetect  = (flags & asGC_DETECT_GARBAGE)  || !(flags & asGC_DESTROY_GARBAGE);
+		bool doDestroy = (flags & asGC_DESTROY_GARBAGE) || !(flags & asGC_DETECT_GARBAGE);
+
+		if( flags & asGC_FULL_CYCLE )
 		{
-			// Detect all garbage with cyclic references
+			// Reset the state
 			if( doDetect )
-				while( (r = IdentifyGarbageWithCyclicRefs()) == 1 );
-
-			// Now destroy all known garbage
+			{
+				// Move all objects to the old list, so we guarantee that all is detected
+				for( asUINT n = (asUINT)gcNewObjects.GetLength(); n-- > 0; )
+					MoveObjectToOldList(n);
+				detectState  = clearCounters_init;
+			}
 			if( doDestroy )
-				while( (r = DestroyGarbage()) == 1 );
+			{
+				destroyNewState = destroyGarbage_init;
+				destroyOldState = destroyGarbage_init;
+			}
 
-			// Run another iteration if any garbage was destroyed
-			if( count != gcObjects.GetLength() )
-				count = (unsigned int)gcObjects.GetLength();
-			else
-				break;
-		}
+			int r = 1;
+			unsigned int count = (unsigned int)(gcNewObjects.GetLength() + gcOldObjects.GetLength());
+			for(;;)
+			{
+				// Detect all garbage with cyclic references
+				if( doDetect )
+					while( (r = IdentifyGarbageWithCyclicRefs()) == 1 );
 
-		// Take the opportunity to clear unused types as well
-		engine->ClearUnusedTypes();
+				// Now destroy all known garbage
+				if( doDestroy )
+				{
+					while( (r = DestroyNewGarbage()) == 1 );
+					while( (r = DestroyOldGarbage()) == 1 );
+				}
 
-		return 0;
-	}
-	else
-	{
-		// Destroy the garbage that we know of
-		if( doDestroy )
-			DestroyGarbage();
+				// Run another iteration if any garbage was destroyed
+				if( count != (unsigned int)(gcNewObjects.GetLength() + gcOldObjects.GetLength()) )
+					count = (unsigned int)(gcNewObjects.GetLength() + gcOldObjects.GetLength());
+				else
+					break;
+			}
 
-		// Run another incremental step of the identification of cyclic references
-		if( doDetect )
-			IdentifyGarbageWithCyclicRefs();
-	}
+			// Take the opportunity to clear unused types as well
+			engine->ClearUnusedTypes();
+
+			LEAVECRITICALSECTION(gcCollecting);
+			return 0;
+		}
+		else
+		{
+			// Destroy the garbage that we know of
+			if( doDestroy )
+			{
+				DestroyNewGarbage();
+				DestroyOldGarbage();
+			}
 
+			// Run another incremental step of the identification of cyclic references
+			if( doDetect )
+				IdentifyGarbageWithCyclicRefs();
+		}
+
+		LEAVECRITICALSECTION(gcCollecting);
+	}
+	
 	// Return 1 to indicate that the cycle wasn't finished
 	return 1;
 }
 
-void asCGarbageCollector::GetStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected) const
+void asCGarbageCollector::GetStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected, asUINT *newObjects, asUINT *totalNewDestroyed) const
 {
 	// It's not necessary to protect this access, as
 	// it doesn't matter if another thread is currently
 	// appending a new object.
 	if( currentSize )
-		*currentSize = (asUINT)gcObjects.GetLength();
+		*currentSize = (asUINT)(gcNewObjects.GetLength() + gcOldObjects.GetLength());
 
 	if( totalDestroyed )
 		*totalDestroyed = numDestroyed;
 
 	if( totalDetected )
 		*totalDetected = numDetected;
-}
 
-void asCGarbageCollector::ClearMap()
-{
-	// Decrease reference counter for all objects removed from the map
-	asSMapNode<void*, asSIntTypePair> *cursor = 0;
-	gcMap.MoveFirst(&cursor);
-	while( cursor )
-	{
-		void *obj = gcMap.GetKey(cursor);
-		asSIntTypePair it = gcMap.GetValue(cursor);
+	if( newObjects )
+		*newObjects = (asUINT)gcNewObjects.GetLength();
 
-		engine->CallObjectMethod(obj, it.type->beh.release);
+	if( totalNewDestroyed )
+		*totalNewDestroyed = numNewDestroyed;
+}
 
-		gcMap.MoveNext(&cursor, cursor);
-	}
+asCGarbageCollector::asSObjTypePair asCGarbageCollector::GetNewObjectAtIdx(int idx)
+{
+	// We need to protect this access with a critical section as
+	// another thread might be appending an object at the same time
+	ENTERCRITICALSECTION(gcCritical);
+	asSObjTypePair gcObj = gcNewObjects[idx];
+	LEAVECRITICALSECTION(gcCritical);
 
-	gcMap.EraseAll();
+	return gcObj;
 }
 
-asCGarbageCollector::asSObjTypePair asCGarbageCollector::GetObjectAtIdx(int idx)
+asCGarbageCollector::asSObjTypePair asCGarbageCollector::GetOldObjectAtIdx(int idx)
 {
 	// We need to protect this access with a critical section as
 	// another thread might be appending an object at the same time
 	ENTERCRITICALSECTION(gcCritical);
-	asSObjTypePair gcObj = gcObjects[idx];
+	asSObjTypePair gcObj = gcOldObjects[idx];
 	LEAVECRITICALSECTION(gcCritical);
 
 	return gcObj;
 }
 
-void asCGarbageCollector::RemoveObjectAtIdx(int idx)
+void asCGarbageCollector::RemoveNewObjectAtIdx(int idx)
+{
+	// We need to protect this update with a critical section as
+	// another thread might be appending an object at the same time
+	ENTERCRITICALSECTION(gcCritical);
+	if( idx == (int)gcNewObjects.GetLength() - 1)
+		gcNewObjects.PopLast();
+	else
+		gcNewObjects[idx] = gcNewObjects.PopLast();
+	LEAVECRITICALSECTION(gcCritical);
+}
+
+void asCGarbageCollector::RemoveOldObjectAtIdx(int idx)
+{
+	// We need to protect this update with a critical section as
+	// another thread might be appending an object at the same time
+	ENTERCRITICALSECTION(gcCritical);
+	if( idx == (int)gcOldObjects.GetLength() - 1)
+		gcOldObjects.PopLast();
+	else
+		gcOldObjects[idx] = gcOldObjects.PopLast();
+	LEAVECRITICALSECTION(gcCritical);
+}
+
+void asCGarbageCollector::MoveObjectToOldList(int idx)
 {
 	// We need to protect this update with a critical section as
 	// another thread might be appending an object at the same time
 	ENTERCRITICALSECTION(gcCritical);
-	if( idx == (int)gcObjects.GetLength() - 1)
-		gcObjects.PopLast();
+	gcOldObjects.PushLast(gcNewObjects[idx]);
+	if( idx == (int)gcNewObjects.GetLength() - 1)
+		gcNewObjects.PopLast();
 	else
-		gcObjects[idx] = gcObjects.PopLast();
+		gcNewObjects[idx] = gcNewObjects.PopLast();
+	LEAVECRITICALSECTION(gcCritical);
+}
+
+void asCGarbageCollector::IncreaseCounterForNewObject(int idx)
+{
+	// We need to protect this update with a critical section as
+	// another thread might be appending an object at the same time
+	ENTERCRITICALSECTION(gcCritical);
+	gcNewObjects[idx].count++;
 	LEAVECRITICALSECTION(gcCritical);
 }
 
-int asCGarbageCollector::DestroyGarbage()
+int asCGarbageCollector::DestroyNewGarbage()
 {
 	for(;;)
 	{
-		switch( destroyState )
+		switch( destroyNewState )
 		{
 		case destroyGarbage_init:
 		{
 			// If there are no objects to be freed then don't start
-			if( gcObjects.GetLength() == 0 )
+			if( gcNewObjects.GetLength() == 0 )
 				return 0;
 
-			destroyIdx = (asUINT)-1;
-			destroyState = destroyGarbage_loop;
+			destroyNewIdx = (asUINT)-1;
+			destroyNewState = destroyGarbage_loop;
 		}
 		break;
 
@@ -203,9 +287,9 @@ int asCGarbageCollector::DestroyGarbage()
 			// Destroy all objects that have refCount == 1. If any objects are
 			// destroyed, go over the list again, because it may have made more
 			// objects reach refCount == 1.
-			while( ++destroyIdx < gcObjects.GetLength() )
+			if( ++destroyNewIdx < gcNewObjects.GetLength() )
 			{
-				asSObjTypePair gcObj = GetObjectAtIdx(destroyIdx);
+				asSObjTypePair gcObj = GetNewObjectAtIdx(destroyNewIdx);
 				if( engine->CallObjectMethodRetInt(gcObj.obj, gcObj.type->beh.gcGetRefCount) == 1 )
 				{
 					// Release the object immediately
@@ -226,8 +310,9 @@ int asCGarbageCollector::DestroyGarbage()
 					if( !addRef )
 					{
 						numDestroyed++;
-						RemoveObjectAtIdx(destroyIdx);
-						destroyIdx--;
+						numNewDestroyed++;
+						RemoveNewObjectAtIdx(destroyNewIdx);
+						destroyNewIdx--;
 					}
 					else
 					{
@@ -236,26 +321,132 @@ int asCGarbageCollector::DestroyGarbage()
 						engine->CallObjectMethod(gcObj.obj, gcObj.type->beh.addref);
 					}
 
-					destroyState = destroyGarbage_haveMore;
+					destroyNewState = destroyGarbage_haveMore;
+				}
+				else if( gcObj.count == 3 )
+				{
+					// We've already verified this object multiple times. It is likely
+					// to live for quite a long time so we'll move it to the list if old objects
+					MoveObjectToOldList(destroyNewIdx);
+					destroyNewIdx--;
+				}
+				else
+				{
+					// Increase the counter for the number of times the object has been verified
+					IncreaseCounterForNewObject(destroyNewIdx);
+				}
 
-					// Allow the application to work a little
-					return 1;
+				// Allow the application to work a little
+				return 1;
+			}
+			else
+			{
+				if( destroyNewState == destroyGarbage_haveMore )
+				{
+					// Restart the cycle
+					destroyNewState = destroyGarbage_init;
+				}
+				else
+				{
+					// Restart the cycle
+					destroyNewState = destroyGarbage_init;
+
+					// Return 0 to tell the application that there 
+					// is no more garbage to destroy at the moment
+					return 0;
 				}
 			}
+		}
+		break;
+		}
+	}
+
+	// Shouldn't reach this point
+	UNREACHABLE_RETURN;
+}
 
-			if( destroyState == destroyGarbage_haveMore )
+int asCGarbageCollector::DestroyOldGarbage()
+{
+	for(;;)
+	{
+		switch( destroyOldState )
+		{
+		case destroyGarbage_init:
+		{
+			// If there are no objects to be freed then don't start
+			if( gcOldObjects.GetLength() == 0 )
+				return 0;
+
+			destroyOldIdx = (asUINT)-1;
+			destroyOldState = destroyGarbage_loop;
+		}
+		break;
+
+		case destroyGarbage_loop:
+		case destroyGarbage_haveMore:
+		{
+			// If the refCount has reached 1, then only the GC still holds a
+			// reference to the object, thus we don't need to worry about the
+			// application touching the objects during collection.
+
+			// Destroy all objects that have refCount == 1. If any objects are
+			// destroyed, go over the list again, because it may have made more
+			// objects reach refCount == 1.
+			if( ++destroyOldIdx < gcOldObjects.GetLength() )
 			{
-				// Restart the cycle
-				destroyState = destroyGarbage_init;
+				asSObjTypePair gcObj = GetOldObjectAtIdx(destroyOldIdx);
+				if( engine->CallObjectMethodRetInt(gcObj.obj, gcObj.type->beh.gcGetRefCount) == 1 )
+				{
+					// Release the object immediately
+
+					// Make sure the refCount is really 0, because the
+					// destructor may have increased the refCount again.
+					bool addRef = false;
+					if( gcObj.type->flags & asOBJ_SCRIPT_OBJECT )
+					{
+						// Script objects may actually be resurrected in the destructor
+						int refCount = ((asCScriptObject*)gcObj.obj)->Release();
+						if( refCount > 0 ) addRef = true;
+					}
+					else
+						engine->CallObjectMethod(gcObj.obj, gcObj.type->beh.release);
+
+					// Was the object really destroyed?
+					if( !addRef )
+					{
+						numDestroyed++;
+						RemoveOldObjectAtIdx(destroyOldIdx);
+						destroyOldIdx--;
+					}
+					else
+					{
+						// Since the object was resurrected in the
+						// destructor, we must add our reference again
+						engine->CallObjectMethod(gcObj.obj, gcObj.type->beh.addref);
+					}
+
+					destroyOldState = destroyGarbage_haveMore;
+				}
+
+				// Allow the application to work a little
+				return 1;
 			}
 			else
 			{
-				// Restart the cycle
-				destroyState = destroyGarbage_init;
+				if( destroyOldState == destroyGarbage_haveMore )
+				{
+					// Restart the cycle
+					destroyOldState = destroyGarbage_init;
+				}
+				else
+				{
+					// Restart the cycle
+					destroyOldState = destroyGarbage_init;
 
-				// Return 0 to tell the application that there 
-				// is no more garbage to destroy at the moment
-				return 0;
+					// Return 0 to tell the application that there 
+					// is no more garbage to destroy at the moment
+					return 0;
+				}
 			}
 		}
 		break;
@@ -273,14 +464,36 @@ int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
 		switch( detectState )
 		{
 		case clearCounters_init:
-		{
-			ClearMap();
 			detectState = clearCounters_loop;
-			detectIdx = 0;
-		}
 		break;
 
 		case clearCounters_loop:
+		{
+			// Decrease reference counter for all objects removed from the map
+			asSMapNode<void*, asSIntTypePair> *cursor = 0;
+			gcMap.MoveFirst(&cursor);
+			if( cursor )
+			{
+				void *obj = gcMap.GetKey(cursor);
+				asSIntTypePair it = gcMap.GetValue(cursor);
+
+				engine->CallObjectMethod(obj, it.type->beh.release);
+
+				gcMap.Erase(cursor);
+
+				return 1;
+			}
+
+			detectState = buildMap_init;
+		}
+		break;
+
+		case buildMap_init:
+			detectIdx = 0;
+			detectState = buildMap_loop;
+		break;
+
+		case buildMap_loop:
 		{
 			// Build a map of objects that will be checked, the map will
 			// hold the object pointer as key, and the gcCount and the
@@ -293,10 +506,10 @@ int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
 			// be used during the analyzing for cyclic references. This
 			// isn't a problem, as the next time the GC cycle starts the
 			// object will be verified.
-			while( detectIdx < gcObjects.GetLength() )
+			if( detectIdx < gcOldObjects.GetLength() )
 			{
 				// Add the gc count for this object
-				asSObjTypePair gcObj = GetObjectAtIdx(detectIdx);
+				asSObjTypePair gcObj = GetOldObjectAtIdx(detectIdx);
 				int refCount = engine->CallObjectMethodRetInt(gcObj.obj, gcObj.type->beh.gcGetRefCount);
 				if( refCount > 1 )
 				{
@@ -309,23 +522,20 @@ int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
 					// Mark the object so that we can
 					// see if it has changed since read
 					engine->CallObjectMethod(gcObj.obj, gcObj.type->beh.gcSetFlag);
+				}
 
-					detectIdx++;
+				detectIdx++; 
 
-					// Let the application work a little
-					return 1;
-				}
-				else
-					detectIdx++;
+				// Let the application work a little
+				return 1;
 			}
-
-			detectState = countReferences_init;
+			else
+				detectState = countReferences_init;
 		}
 		break;
 
 		case countReferences_init:
 		{
-			detectIdx = (asUINT)-1;
 			gcMap.MoveFirst(&gcMapCursor);
 			detectState = countReferences_loop;
 		}
@@ -344,7 +554,7 @@ int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
 
 			// Any new objects created after this step in the GC cycle won't be
 			// in the map, and is thus automatically considered alive.
-			while( gcMapCursor )
+			if( gcMapCursor )
 			{
 				void *obj = gcMap.GetKey(gcMapCursor);
 				asCObjectType *type = gcMap.GetValue(gcMapCursor).type;
@@ -353,19 +563,18 @@ int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
 				if( engine->CallObjectMethodRetBool(obj, type->beh.gcGetFlag) )
 				{
 					engine->CallObjectMethod(obj, engine, type->beh.gcEnumReferences);
-
-					// Allow the application to work a little
-					return 1;
 				}
-			}
 
-			detectState = detectGarbage_init;
+				// Allow the application to work a little
+				return 1;
+			}
+			else
+				detectState = detectGarbage_init;
 		}
 		break;
 
 		case detectGarbage_init:
 		{
-			detectIdx = (asUINT)-1;
 			gcMap.MoveFirst(&gcMapCursor);
 			liveObjects.SetLength(0);
 			detectState = detectGarbage_loop1;
@@ -382,7 +591,7 @@ int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
 			// references were not found in the map.
 
 			// Add all alive objects from the map to the liveObjects array
-			while( gcMapCursor )
+			if( gcMapCursor )
 			{
 				asSMapNode<void*, asSIntTypePair> *cursor = gcMapCursor;
 				gcMap.MoveNext(&gcMapCursor, gcMapCursor);
@@ -394,13 +603,13 @@ int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
 				if( !gcFlag || it.i > 0 )
 				{
 					liveObjects.PushLast(obj);
-
-					// Allow the application to work a little
-					return 1;
 				}
-			}
 
-			detectState = detectGarbage_loop2;
+				// Allow the application to work a little
+				return 1;
+			}
+			else
+				detectState = detectGarbage_loop2;
 		}
 		break;
 
@@ -410,7 +619,7 @@ int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
 			// As the object is removed, all the objects it references are added to the
 			// liveObjects list, by calling EnumReferences. Only objects still in the map
 			// will be added to the liveObjects list.
-			while( liveObjects.GetLength() )
+			if( liveObjects.GetLength() )
 			{
 				void *gcObj = liveObjects.PopLast();
 				asCObjectType *type = 0;
@@ -432,18 +641,22 @@ int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
 				// Allow the application to work a little
 				return 1;
 			}
-
-			detectState = verifyUnmarked;
+			else
+				detectState = verifyUnmarked_init;
 		}
 		break;
 
-		case verifyUnmarked:
+		case verifyUnmarked_init:
+			gcMap.MoveFirst(&gcMapCursor);
+			detectState = verifyUnmarked_loop;
+			break;
+
+		case verifyUnmarked_loop:
 		{
 			// In this step we must make sure that none of the objects still in the map
 			// has been touched by the application. If they have then we must run the
 			// detectGarbage loop once more.
-			gcMap.MoveFirst(&gcMapCursor);
-			while( gcMapCursor )
+			if( gcMapCursor )
 			{
 				void *gcObj = gcMap.GetKey(gcMapCursor);
 				asCObjectType *type = gcMap.GetValue(gcMapCursor).type;
@@ -453,21 +666,24 @@ int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
 				{
 					// The unmarked object was touched, rerun the detectGarbage loop
 					detectState = detectGarbage_init;
-					return 1;
 				}
+				else
+					gcMap.MoveNext(&gcMapCursor, gcMapCursor);
 
-				gcMap.MoveNext(&gcMapCursor, gcMapCursor);
+				// Allow the application to work a little
+				return 1;
+			}
+			else
+			{
+				// No unmarked object was touched, we can now be sure
+				// that objects that have gcCount == 0 really is garbage
+				detectState = breakCircles_init;
 			}
-
-			// No unmarked object was touched, we can now be sure
-			// that objects that have gcCount == 0 really is garbage
-			detectState = breakCircles_init;
 		}
 		break;
 
 		case breakCircles_init:
 		{
-			detectIdx = (asUINT)-1;
 			gcMap.MoveFirst(&gcMapCursor);
 			detectState = breakCircles_loop;
 		}
@@ -480,7 +696,7 @@ int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
 			// kept alive through circular references. To be able to free
 			// these objects we need to force the breaking of the circle
 			// by having the objects release their references.
-			while( gcMapCursor )
+			if( gcMapCursor )
 			{
 				numDetected++;
 				void *gcObj = gcMap.GetKey(gcMapCursor);
@@ -494,19 +710,21 @@ int asCGarbageCollector::IdentifyGarbageWithCyclicRefs()
 				// Allow the application to work a little
 				return 1;
 			}
-
-			// If no garbage was detected we can finish now
-			if( detectState != breakCircles_haveGarbage )
-			{
-				// Restart the GC
-				detectState = clearCounters_init;
-				return 0;
-			}
 			else
 			{
-				// Restart the GC
-				detectState = clearCounters_init;
-				return 1;
+				// If no garbage was detected we can finish now
+				if( detectState != breakCircles_haveGarbage )
+				{
+					// Restart the GC
+					detectState = clearCounters_init;
+					return 0;
+				}
+				else
+				{
+					// Restart the GC
+					detectState = clearCounters_init;
+					return 1;
+				}
 			}
 		}
 		break;

+ 24 - 12
ThirdParty/AngelScript/source/as_gc.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2010 Andreas Jonsson
+   Copyright (c) 2003-2011 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -56,14 +56,14 @@ public:
 	asCGarbageCollector();
 
 	int  GarbageCollect(asDWORD flags);
-	void GetStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected) const;
+	void GetStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected, asUINT *newObjects, asUINT *totalNewDestroyed) const;
 	void GCEnumCallback(void *reference);
 	void AddScriptObjectToGC(void *obj, asCObjectType *objType);
 
 	asCScriptEngine *engine;
 
 protected:
-	struct asSObjTypePair {void *obj; asCObjectType *type;};
+	struct asSObjTypePair {void *obj; asCObjectType *type; int count;};
 	struct asSIntTypePair {int i; asCObjectType *type;};
 
 	enum egcDestroyState
@@ -77,25 +77,33 @@ protected:
 	{
 		clearCounters_init = 0,
 		clearCounters_loop,
+		buildMap_init,
+		buildMap_loop,
 		countReferences_init,
 		countReferences_loop,
 		detectGarbage_init,
 		detectGarbage_loop1,
 		detectGarbage_loop2,
-		verifyUnmarked,
+		verifyUnmarked_init,
+		verifyUnmarked_loop,
 		breakCircles_init,
 		breakCircles_loop,
 		breakCircles_haveGarbage
 	};
 
-	int            DestroyGarbage();
+	int            DestroyNewGarbage();
+	int            DestroyOldGarbage();
 	int            IdentifyGarbageWithCyclicRefs();
-	void           ClearMap();
-	asSObjTypePair GetObjectAtIdx(int idx);
-	void           RemoveObjectAtIdx(int idx);
+	asSObjTypePair GetNewObjectAtIdx(int idx);
+	asSObjTypePair GetOldObjectAtIdx(int idx);
+	void           RemoveNewObjectAtIdx(int idx);
+	void           RemoveOldObjectAtIdx(int idx);
+	void           MoveObjectToOldList(int idx);
+	void           IncreaseCounterForNewObject(int idx);
 
 	// Holds all the objects known by the garbage collector
-	asCArray<asSObjTypePair>           gcObjects;
+	asCArray<asSObjTypePair>           gcNewObjects;
+	asCArray<asSObjTypePair>           gcOldObjects;
 
 	// This array temporarily holds references to objects known to be live objects
 	asCArray<void*>                    liveObjects;
@@ -105,16 +113,20 @@ protected:
 	asCMap<void*, asSIntTypePair>      gcMap;
 
 	// State variables
-	egcDestroyState                    destroyState;
-	asUINT                             destroyIdx;
+	egcDestroyState                    destroyNewState;
+	egcDestroyState                    destroyOldState;
+	asUINT                             destroyNewIdx;
+	asUINT                             destroyOldIdx;
 	asUINT                             numDestroyed;
+	asUINT                             numNewDestroyed;
 	egcDetectState                     detectState;
 	asUINT                             detectIdx;
 	asUINT                             numDetected;
 	asSMapNode<void*, asSIntTypePair> *gcMapCursor;
 
 	// Critical section for multithreaded access
-	DECLARECRITICALSECTION(gcCritical);
+	DECLARECRITICALSECTION(gcCritical);   // Used for adding/removing objects
+	DECLARECRITICALSECTION(gcCollecting); // Used for processing
 };
 
 END_AS_NAMESPACE

+ 43 - 37
ThirdParty/AngelScript/source/as_module.cpp

@@ -157,34 +157,31 @@ int asCModule::Build()
 
 	// Initialize global variables
 	if( r >= 0 && engine->ep.initGlobalVarsAfterBuild )
-		r = ResetGlobalVars();
+		r = ResetGlobalVars(0);
 
 	return r;
 }
 
 // interface
-int asCModule::ResetGlobalVars()
+int asCModule::ResetGlobalVars(asIScriptContext *ctx)
 {
 	if( isGlobalVarInitialized ) 
 		CallExit();
 
-	// TODO: The application really should do this manually through a context
-	//       otherwise it cannot properly handle script exceptions that may be
-	//       thrown by object initializations.
-	return CallInit();
+	return CallInit(ctx);
 }
 
 // interface
-int asCModule::GetFunctionIdByIndex(int index) const
+int asCModule::GetFunctionIdByIndex(asUINT index) const
 {
-	if( index < 0 || index >= (int)globalFunctions.GetLength() )
+	if( index >= globalFunctions.GetLength() )
 		return asNO_FUNCTION;
 
 	return globalFunctions[index]->id;
 }
 
 // internal
-int asCModule::CallInit()
+int asCModule::CallInit(asIScriptContext *myCtx)
 {
 	if( isGlobalVarInitialized ) 
 		return asERROR;
@@ -200,7 +197,7 @@ int asCModule::CallInit()
 	}
 
 	// Call the init function for each of the global variables
-	asIScriptContext *ctx = 0;
+	asIScriptContext *ctx = myCtx;
 	int r = asEXECUTION_FINISHED;
 	for( n = 0; n < scriptGlobals.GetLength() && r == asEXECUTION_FINISHED; n++ )
 	{
@@ -247,7 +244,7 @@ int asCModule::CallInit()
 		}
 	}
 
-	if( ctx )
+	if( ctx && !myCtx )
 	{
 		ctx->Release();
 		ctx = 0;
@@ -335,7 +332,9 @@ void asCModule::InternalReset()
 	// Free bind information
 	for( n = 0; n < bindInformations.GetLength(); n++ )
 	{
-		engine->importedFunctions[bindInformations[n]->importedFunctionSignature->id & 0xFFFF] = 0 ;
+		asUINT id = bindInformations[n]->importedFunctionSignature->id & 0xFFFF;
+		engine->importedFunctions[id] = 0;
+		engine->freeImportedFunctionIdxs.PushLast(id);
 
 		asDELETE(bindInformations[n]->importedFunctionSignature, asCScriptFunction);
 		asDELETE(bindInformations[n], sBindInfo);
@@ -386,9 +385,9 @@ int asCModule::GetFunctionIdByName(const char *name) const
 }
 
 // interface
-int asCModule::GetImportedFunctionCount() const
+asUINT asCModule::GetImportedFunctionCount() const
 {
-	return (int)bindInformations.GetLength();
+	return (asUINT)bindInformations.GetLength();
 }
 
 // interface
@@ -434,9 +433,9 @@ int asCModule::GetImportedFunctionIndexByDecl(const char *decl) const
 }
 
 // interface
-int asCModule::GetFunctionCount() const
+asUINT asCModule::GetFunctionCount() const
 {
-	return (int)globalFunctions.GetLength();
+	return (asUINT)globalFunctions.GetLength();
 }
 
 // interface
@@ -485,9 +484,9 @@ int asCModule::GetFunctionIdByDecl(const char *decl) const
 }
 
 // interface
-int asCModule::GetGlobalVarCount() const
+asUINT asCModule::GetGlobalVarCount() const
 {
-	return (int)scriptGlobals.GetLength();
+	return (asUINT)scriptGlobals.GetLength();
 }
 
 // interface
@@ -522,9 +521,9 @@ int asCModule::RemoveGlobalVar(asUINT index)
 }
 
 // interface
-asIScriptFunction *asCModule::GetFunctionDescriptorByIndex(int index) const
+asIScriptFunction *asCModule::GetFunctionDescriptorByIndex(asUINT index) const
 {
-	if( index < 0 || index >= (int)globalFunctions.GetLength() )
+	if( index >= globalFunctions.GetLength() )
 		return 0;
 
 	return globalFunctions[index];
@@ -611,9 +610,9 @@ int asCModule::GetGlobalVar(asUINT index, const char **name, int *typeId, bool *
 }
 
 // interface
-int asCModule::GetObjectTypeCount() const
+asUINT asCModule::GetObjectTypeCount() const
 {
-	return (int)classTypes.GetLength();
+	return (asUINT)classTypes.GetLength();
 }
 
 // interface 
@@ -638,9 +637,9 @@ int asCModule::GetTypeIdByDecl(const char *decl) const
 }
 
 // interface
-int asCModule::GetEnumCount() const
+asUINT asCModule::GetEnumCount() const
 {
-	return (int)enumTypes.GetLength();
+	return (asUINT)enumTypes.GetLength();
 }
 
 // interface
@@ -684,9 +683,9 @@ const char *asCModule::GetEnumValueByIndex(int enumTypeId, asUINT index, int *ou
 }
 
 // interface
-int asCModule::GetTypedefCount() const
+asUINT asCModule::GetTypedefCount() const
 {
-	return (int)typeDefs.GetLength();
+	return (asUINT)typeDefs.GetLength();
 }
 
 // interface
@@ -705,6 +704,10 @@ const char *asCModule::GetTypedefByIndex(asUINT index, int *typeId) const
 // internal
 int asCModule::GetNextImportedFunctionId()
 {
+	// TODO: multithread: This will break if one thread if freeing a module, while another is being compiled
+	if( engine->freeImportedFunctionIdxs.GetLength() )
+		return FUNC_IMPORTED | (asUINT)engine->freeImportedFunctionIdxs[engine->freeImportedFunctionIdxs.GetLength()-1];
+
 	return FUNC_IMPORTED | (asUINT)engine->importedFunctions.GetLength();
 }
 
@@ -784,7 +787,10 @@ int asCModule::AddImportedFunction(int id, const char *name, const asCDataType &
 	bindInformations.PushLast(info);
 
 	// Add the info to the array in the engine
-	engine->importedFunctions.PushLast(info);
+	if( engine->freeImportedFunctionIdxs.GetLength() )
+		engine->importedFunctions[engine->freeImportedFunctionIdxs.PopLast()] = info;
+	else
+		engine->importedFunctions.PushLast(info);
 
 	return 0;
 }
@@ -796,7 +802,7 @@ asCScriptFunction *asCModule::GetImportedFunction(int index) const
 }
 
 // interface
-int asCModule::BindImportedFunction(int index, int sourceId)
+int asCModule::BindImportedFunction(asUINT index, int sourceId)
 {
 	// First unbind the old function
 	int r = UnbindImportedFunction(index);
@@ -830,9 +836,9 @@ int asCModule::BindImportedFunction(int index, int sourceId)
 }
 
 // interface
-int asCModule::UnbindImportedFunction(int index)
+int asCModule::UnbindImportedFunction(asUINT index)
 {
-	if( index < 0 || index > (int)bindInformations.GetLength() )
+	if( index >= bindInformations.GetLength() )
 		return asINVALID_ARG;
 
 	// Remove reference to old module
@@ -847,7 +853,7 @@ int asCModule::UnbindImportedFunction(int index)
 }
 
 // interface
-const char *asCModule::GetImportedFunctionDeclaration(int index) const
+const char *asCModule::GetImportedFunctionDeclaration(asUINT index) const
 {
 	asCScriptFunction *func = GetImportedFunction(index);
 	if( func == 0 ) return 0;
@@ -860,9 +866,9 @@ const char *asCModule::GetImportedFunctionDeclaration(int index) const
 }
 
 // interface
-const char *asCModule::GetImportedFunctionSourceModule(int index) const
+const char *asCModule::GetImportedFunctionSourceModule(asUINT index) const
 {
-	if( index >= (int)bindInformations.GetLength() )
+	if( index >= bindInformations.GetLength() )
 		return 0;
 
 	return bindInformations[index]->importFromModule.AddressOf();
@@ -909,8 +915,8 @@ int asCModule::BindAllImportedFunctions()
 // interface
 int asCModule::UnbindAllImportedFunctions()
 {
-	int c = GetImportedFunctionCount();
-	for( int n = 0; n < c; ++n )
+	asUINT c = GetImportedFunctionCount();
+	for( asUINT n = 0; n < c; ++n )
 		UnbindImportedFunction(n);
 
 	return asSUCCESS;
@@ -1053,7 +1059,7 @@ void asCModule::ResolveInterfaceIds(asCArray<void*> *substitutions)
 			if( classTypes[c]->IsInterface() )
 			{
 				asCObjectType *intf = classTypes[c];
-				for( int m = 0; m < intf->GetMethodCount(); m++ )
+				for( asUINT m = 0; m < intf->GetMethodCount(); m++ )
 				{
 					asCScriptFunction *func = engine->GetScriptFunction(intf->methods[m]);
 					if( func )
@@ -1061,7 +1067,7 @@ void asCModule::ResolveInterfaceIds(asCArray<void*> *substitutions)
 						if( func->returnType.GetObjectType() == equals[i].a )
 							func->returnType.SetObjectType(equals[i].b);
 
-						for( int p = 0; p < func->GetParamCount(); p++ )
+						for( asUINT p = 0; p < func->GetParamCount(); p++ )
 						{
 							if( func->parameterTypes[p].GetObjectType() == equals[i].a )
 								func->parameterTypes[p].SetObjectType(equals[i].b);

+ 14 - 14
ThirdParty/AngelScript/source/as_module.h

@@ -105,17 +105,17 @@ public:
 	virtual int  CompileGlobalVar(const char *sectionName, const char *code, int lineOffset);
 
 	// Script functions
-	virtual int                GetFunctionCount() const;
-	virtual int                GetFunctionIdByIndex(int index) const;
+	virtual asUINT             GetFunctionCount() const;
+	virtual int                GetFunctionIdByIndex(asUINT index) const;
 	virtual int                GetFunctionIdByName(const char *name) const;
 	virtual int                GetFunctionIdByDecl(const char *decl) const;
-	virtual asIScriptFunction *GetFunctionDescriptorByIndex(int index) const;
+	virtual asIScriptFunction *GetFunctionDescriptorByIndex(asUINT index) const;
 	virtual asIScriptFunction *GetFunctionDescriptorById(int funcId) const;
 	virtual int                RemoveFunction(int funcId);
 
 	// Script global variables
-	virtual int         ResetGlobalVars();
-	virtual int         GetGlobalVarCount() const;
+	virtual int         ResetGlobalVars(asIScriptContext *ctx);
+	virtual asUINT      GetGlobalVarCount() const;
 	virtual int         GetGlobalVarIndexByName(const char *name) const;
 	virtual int         GetGlobalVarIndexByDecl(const char *decl) const;
 	virtual const char *GetGlobalVarDeclaration(asUINT index) const;
@@ -124,27 +124,27 @@ public:
 	virtual int         RemoveGlobalVar(asUINT index);
 
 	// Type identification
-	virtual int            GetObjectTypeCount() const;
+	virtual asUINT         GetObjectTypeCount() const;
 	virtual asIObjectType *GetObjectTypeByIndex(asUINT index) const;
 	virtual int            GetTypeIdByDecl(const char *decl) const;
 
 	// Enums
-	virtual int         GetEnumCount() const;
+	virtual asUINT      GetEnumCount() const;
 	virtual const char *GetEnumByIndex(asUINT index, int *enumTypeId) const;
 	virtual int         GetEnumValueCount(int enumTypeId) const;
 	virtual const char *GetEnumValueByIndex(int enumTypeId, asUINT index, int *outValue) const;
 
 	// Typedefs
-	virtual int         GetTypedefCount() const;
+	virtual asUINT      GetTypedefCount() const;
 	virtual const char *GetTypedefByIndex(asUINT index, int *typeId) const;
 
 	// Dynamic binding between modules
-	virtual int         GetImportedFunctionCount() const;
+	virtual asUINT      GetImportedFunctionCount() const;
 	virtual int         GetImportedFunctionIndexByDecl(const char *decl) const;
-	virtual const char *GetImportedFunctionDeclaration(int importIndex) const;
-	virtual const char *GetImportedFunctionSourceModule(int importIndex) const;
-	virtual int         BindImportedFunction(int index, int sourceID);
-	virtual int         UnbindImportedFunction(int importIndex);
+	virtual const char *GetImportedFunctionDeclaration(asUINT importIndex) const;
+	virtual const char *GetImportedFunctionSourceModule(asUINT importIndex) const;
+	virtual int         BindImportedFunction(asUINT index, int sourceID);
+	virtual int         UnbindImportedFunction(asUINT importIndex);
 	virtual int         BindAllImportedFunctions();
 	virtual int         UnbindAllImportedFunctions();
 
@@ -167,7 +167,7 @@ public:
 
 	void InternalReset();
 
-	int  CallInit();
+	int  CallInit(asIScriptContext *ctx);
 	void CallExit();
 
 	void JITCompile();

+ 34 - 32
ThirdParty/AngelScript/source/as_objecttype.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2010 Andreas Jonsson
+   Copyright (c) 2003-2011 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -274,9 +274,9 @@ int asCObjectType::GetSubTypeId() const
 	return asERROR;
 }
 
-int asCObjectType::GetInterfaceCount() const
+asUINT asCObjectType::GetInterfaceCount() const
 {
-	return (int)interfaces.GetLength();
+	return (asUINT)interfaces.GetLength();
 }
 
 asIObjectType *asCObjectType::GetInterface(asUINT index) const
@@ -298,14 +298,14 @@ asIScriptEngine *asCObjectType::GetEngine() const
 	return engine;
 }
 
-int asCObjectType::GetFactoryCount() const
+asUINT asCObjectType::GetFactoryCount() const
 {
-	return (int)beh.factories.GetLength();
+	return (asUINT)beh.factories.GetLength();
 }
 
-int asCObjectType::GetFactoryIdByIndex(int index) const
+int asCObjectType::GetFactoryIdByIndex(asUINT index) const
 {
-	if( index < 0 || (unsigned)index >= beh.factories.GetLength() )
+	if( index >= beh.factories.GetLength() )
 		return asINVALID_ARG;
 
 	return beh.factories[index];
@@ -321,15 +321,15 @@ int asCObjectType::GetFactoryIdByDecl(const char *decl) const
 }
 
 // interface
-int asCObjectType::GetMethodCount() const
+asUINT asCObjectType::GetMethodCount() const
 {
-	return (int)methods.GetLength();
+	return (asUINT)methods.GetLength();
 }
 
 // interface
-int asCObjectType::GetMethodIdByIndex(int index, bool getVirtual) const
+int asCObjectType::GetMethodIdByIndex(asUINT index, bool getVirtual) const
 {
-	if( index < 0 || (unsigned)index >= methods.GetLength() )
+	if( index >= methods.GetLength() )
 		return asINVALID_ARG;
 
 	if( !getVirtual )
@@ -397,9 +397,9 @@ int asCObjectType::GetMethodIdByDecl(const char *decl, bool getVirtual) const
 }
 
 // interface
-asIScriptFunction *asCObjectType::GetMethodDescriptorByIndex(int index, bool getVirtual) const
+asIScriptFunction *asCObjectType::GetMethodDescriptorByIndex(asUINT index, bool getVirtual) const
 {
-	if( index < 0 || (unsigned)index >= methods.GetLength() ) 
+	if( index >= methods.GetLength() ) 
 		return 0;
 
 	if( !getVirtual )
@@ -413,13 +413,13 @@ asIScriptFunction *asCObjectType::GetMethodDescriptorByIndex(int index, bool get
 }
 
 // interface
-int asCObjectType::GetPropertyCount() const
+asUINT asCObjectType::GetPropertyCount() const
 {
-	return (int)properties.GetLength();
+	return (asUINT)properties.GetLength();
 }
 
 // interface
-int asCObjectType::GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, int *offset) const
+int asCObjectType::GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, int *offset, bool *isReference) const
 {
 	if( index >= properties.GetLength() )
 		return asINVALID_ARG;
@@ -432,6 +432,8 @@ int asCObjectType::GetProperty(asUINT index, const char **name, int *typeId, boo
 		*isPrivate = properties[index]->isPrivate;
 	if( offset )
 		*offset = properties[index]->byteOffset;
+	if( isReference )
+		*isReference = properties[index]->type.IsReference();
 
 	return 0;
 }
@@ -460,10 +462,10 @@ asIObjectType *asCObjectType::GetBaseType() const
 	return derivedFrom; 
 }
 
-int asCObjectType::GetBehaviourCount() const
+asUINT asCObjectType::GetBehaviourCount() const
 {
 	// Count the number of behaviours (except factory functions)
-	int count = 0;
+	asUINT count = 0;
 	
 	if( beh.destruct )               count++;
 	if( beh.addref )                 count++;
@@ -478,8 +480,8 @@ int asCObjectType::GetBehaviourCount() const
 
 	// For reference types, the factories are also stored in the constructor
 	// list, so it is sufficient to enumerate only those
-	count += (int)beh.constructors.GetLength();
-	count += (int)beh.operators.GetLength() / 2;
+	count += (asUINT)beh.constructors.GetLength();
+	count += (asUINT)beh.operators.GetLength() / 2;
 
 	return count;
 }
@@ -487,63 +489,63 @@ int asCObjectType::GetBehaviourCount() const
 int asCObjectType::GetBehaviourByIndex(asUINT index, asEBehaviours *outBehaviour) const
 {
 	// Find the correct behaviour
-	int count = 0;
+	asUINT count = 0;
 
-	if( beh.destruct && count++ == (int)index ) // only increase count if the behaviour is registered
+	if( beh.destruct && count++ == index ) // only increase count if the behaviour is registered
 	{ 
 		if( outBehaviour ) *outBehaviour = asBEHAVE_DESTRUCT;
 		return beh.destruct;
 	}
 
-	if( beh.addref && count++ == (int)index )
+	if( beh.addref && count++ == index )
 	{
 		if( outBehaviour ) *outBehaviour = asBEHAVE_ADDREF;
 		return beh.addref;
 	}
 
-	if( beh.release && count++ == (int)index )
+	if( beh.release && count++ == index )
 	{
 		if( outBehaviour ) *outBehaviour = asBEHAVE_RELEASE;
 		return beh.release;
 	}
 
-	if( beh.gcGetRefCount && count++ == (int)index )
+	if( beh.gcGetRefCount && count++ == index )
 	{
 		if( outBehaviour ) *outBehaviour = asBEHAVE_GETREFCOUNT;
 		return beh.gcGetRefCount;
 	}
 
-	if( beh.gcSetFlag && count++ == (int)index )
+	if( beh.gcSetFlag && count++ == index )
 	{
 		if( outBehaviour ) *outBehaviour = asBEHAVE_SETGCFLAG;
 		return beh.gcSetFlag;
 	}
 
-	if( beh.gcGetFlag && count++ == (int)index )
+	if( beh.gcGetFlag && count++ == index )
 	{
 		if( outBehaviour ) *outBehaviour = asBEHAVE_GETGCFLAG;
 		return beh.gcGetFlag;
 	}
 
-	if( beh.gcEnumReferences && count++ == (int)index )
+	if( beh.gcEnumReferences && count++ == index )
 	{
 		if( outBehaviour ) *outBehaviour = asBEHAVE_ENUMREFS;
 		return beh.gcEnumReferences;
 	}
 
-	if( beh.gcReleaseAllReferences && count++ == (int)index )
+	if( beh.gcReleaseAllReferences && count++ == index )
 	{
 		if( outBehaviour ) *outBehaviour = asBEHAVE_RELEASEREFS;
 		return beh.gcReleaseAllReferences;
 	}
 
-	if( beh.templateCallback && count++ == (int)index )
+	if( beh.templateCallback && count++ == index )
 	{
 		if( outBehaviour ) *outBehaviour = asBEHAVE_TEMPLATE_CALLBACK;
 		return beh.templateCallback;
 	}
 
-	if( beh.listFactory && count++ == (int)index )
+	if( beh.listFactory && count++ == index )
 	{
 		if( outBehaviour ) *outBehaviour = asBEHAVE_LIST_FACTORY;
 		return beh.listFactory;
@@ -557,7 +559,7 @@ int asCObjectType::GetBehaviourByIndex(asUINT index, asEBehaviours *outBehaviour
 		return beh.constructors[index - count];
 	}
 	else 
-		count += (int)beh.constructors.GetLength();
+		count += (asUINT)beh.constructors.GetLength();
 
 	if( index - count < beh.operators.GetLength() / 2 )
 	{

+ 11 - 11
ThirdParty/AngelScript/source/as_objecttype.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2010 Andreas Jonsson
+   Copyright (c) 2003-2011 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -151,29 +151,29 @@ public:
 	int              GetSubTypeId() const;
 
 	// Interfaces
-	int              GetInterfaceCount() const;
+	asUINT           GetInterfaceCount() const;
 	asIObjectType   *GetInterface(asUINT index) const;
 
 	// Factories
-	int                GetFactoryCount() const;
-	int                GetFactoryIdByIndex(int index) const;
+	asUINT             GetFactoryCount() const;
+	int                GetFactoryIdByIndex(asUINT index) const;
 	int                GetFactoryIdByDecl(const char *decl) const;
 
 	// Methods
-	int                GetMethodCount() const;
-	int                GetMethodIdByIndex(int index, bool getVirtual) const;
+	asUINT             GetMethodCount() const;
+	int                GetMethodIdByIndex(asUINT index, bool getVirtual) const;
 	int                GetMethodIdByName(const char *name, bool getVirtual) const;
 	int                GetMethodIdByDecl(const char *decl, bool getVirtual) const;
-	asIScriptFunction *GetMethodDescriptorByIndex(int index, bool getVirtual) const;
+	asIScriptFunction *GetMethodDescriptorByIndex(asUINT index, bool getVirtual) const;
 
 	// Properties
-	int         GetPropertyCount() const;
-	int         GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, int *offset) const;
+	asUINT      GetPropertyCount() const;
+	int         GetProperty(asUINT index, const char **name, int *typeId, bool *isPrivate, int *offset, bool *isReference) const;
 	const char *GetPropertyDeclaration(asUINT index) const;
 
 	// Behaviours
-	int GetBehaviourCount() const;
-	int GetBehaviourByIndex(asUINT index, asEBehaviours *outBehaviour) const;
+	asUINT GetBehaviourCount() const;
+	int    GetBehaviourByIndex(asUINT index, asEBehaviours *outBehaviour) const;
 
 //===========================================
 // Internal

+ 14 - 2
ThirdParty/AngelScript/source/as_parser.cpp

@@ -598,7 +598,11 @@ bool asCParser::IsVarDecl()
 	if( t1.type == ttConst )
 		GetToken(&t1);
 
-	if( !IsDataType(t1) )
+	// We don't validate if the identifier is an actual declared type at this moment
+	// as it may wrongly identify the statement as a non-declaration if the user typed
+	// the name incorrectly. The real type is validated in ParseDeclaration where a
+	// proper error message can be given.
+	if( !IsRealType(t1.type) && t1.type != ttIdentifier )
 	{
 		RewindTo(&t);
 		return false;
@@ -1395,7 +1399,15 @@ asCScriptNode *asCParser::ParseDataType(bool allowVariableType)
 	GetToken(&t1);
 	if( !IsDataType(t1) && !(allowVariableType && t1.type == ttQuestion) )
 	{
-		Error(TXT_EXPECTED_DATA_TYPE, &t1);
+		if( t1.type == ttIdentifier )
+		{
+			asCString errMsg, Identifier;
+			Identifier.Assign(&script->code[t1.pos], t1.length);
+			errMsg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE, Identifier.AddressOf());
+			Error(errMsg.AddressOf(), &t1);
+		}
+		else
+			Error(TXT_EXPECTED_DATA_TYPE, &t1);
 		return node;
 	}
 

+ 16 - 3
ThirdParty/AngelScript/source/as_restore.cpp

@@ -356,8 +356,17 @@ int asCRestore::Restore()
 	{
 		sBindInfo *info = asNEW(sBindInfo);
 		info->importedFunctionSignature = ReadFunction(false, false);
-		info->importedFunctionSignature->id = int(FUNC_IMPORTED + engine->importedFunctions.GetLength());
-		engine->importedFunctions.PushLast(info);
+		if( engine->freeImportedFunctionIdxs.GetLength() )
+		{
+			int id = engine->freeImportedFunctionIdxs.PopLast();
+			info->importedFunctionSignature->id = int(FUNC_IMPORTED + id);
+			engine->importedFunctions[id] = info;
+		}
+		else
+		{
+			info->importedFunctionSignature->id = int(FUNC_IMPORTED + engine->importedFunctions.GetLength());
+			engine->importedFunctions.PushLast(info);
+		}
 		ReadString(&info->importFromModule);
 		info->boundFunctionId = -1;
 		module->bindInformations[i] = info;
@@ -428,7 +437,11 @@ int asCRestore::Restore()
 			if( module->scriptGlobals[i]->GetInitFunc() )
 				module->scriptGlobals[i]->GetInitFunc()->AddReferences();
 
-		module->CallInit();
+		if( engine->ep.initGlobalVarsAfterBuild )
+		{
+			int r = module->ResetGlobalVars(0);
+			if( r < 0 ) error = true;
+		}
 	}
 
 	return error ? asERROR : asSUCCESS;

+ 18 - 2
ThirdParty/AngelScript/source/as_scriptengine.cpp

@@ -139,6 +139,10 @@ AS_API const char * asGetLibraryOptions()
 #ifdef AS_HAIKU
 		"AS_HAIKU "
 #endif
+#ifdef AS_ILLUMOS
+		"AS_ILLUMOS "
+#endif
+
 
 	// CPU family
 #ifdef AS_PPC
@@ -284,6 +288,10 @@ int asCScriptEngine::SetEngineProperty(asEEngineProp property, asPWORD value)
 		ep.expandDefaultArrayToTemplate = value ? true : false;
 		break;
 
+	case asEP_AUTO_GARBAGE_COLLECT:
+		ep.autoGarbageCollect = value ? true : false;
+		break;
+
 	default:
 		return asINVALID_ARG;
 	}
@@ -339,6 +347,9 @@ asPWORD asCScriptEngine::GetEngineProperty(asEEngineProp property) const
 
 	case asEP_EXPAND_DEF_ARRAY_TO_TMPL:
 		return ep.expandDefaultArrayToTemplate;
+
+	case asEP_AUTO_GARBAGE_COLLECT:
+		return ep.autoGarbageCollect;
 	}
 
 	return 0;
@@ -381,6 +392,7 @@ asCScriptEngine::asCScriptEngine()
 		ep.stringEncoding               = 0;         // utf8. 1 = utf16
 		ep.propertyAccessorMode         = 2;         // 0 = disable, 1 = app registered only, 2 = app and script created
 		ep.expandDefaultArrayToTemplate = false;
+		ep.autoGarbageCollect           = true;
 	}
 
 	gc.engine = this;
@@ -2849,6 +2861,7 @@ void asCScriptEngine::CallObjectMethod(void *obj, asSSystemFunctionInterface *i,
 		} p;
 		p.func = (void (*)())(i->func);
 		void (asCSimpleDummy::*f)() = p.mthd;
+		obj = (void*)(size_t(obj) + i->baseOffset);
 		(((asCSimpleDummy*)obj)->*f)();
 	}
 	else
@@ -2914,6 +2927,7 @@ bool asCScriptEngine::CallObjectMethodRetBool(void *obj, int func)
 		} p;
 		p.func = (void (*)())(i->func);
 		bool (asCSimpleDummy::*f)() = (bool (asCSimpleDummy::*)())p.mthd;
+		obj = (void*)(size_t(obj) + i->baseOffset);
 		return (((asCSimpleDummy*)obj)->*f)();
 	}
 	else
@@ -2980,6 +2994,7 @@ int asCScriptEngine::CallObjectMethodRetInt(void *obj, int func)
 		} p;
 		p.func = (void (*)())(i->func);
 		int (asCSimpleDummy::*f)() = (int (asCSimpleDummy::*)())p.mthd;
+		obj = (void*)(size_t(obj) + i->baseOffset);
 		return (((asCSimpleDummy*)obj)->*f)();
 	}
 	else
@@ -3089,6 +3104,7 @@ void asCScriptEngine::CallObjectMethod(void *obj, void *param, asSSystemFunction
 		} p;
 		p.func = (void (*)())(i->func);
 		void (asCSimpleDummy::*f)(void *) = (void (asCSimpleDummy::*)(void *))(p.mthd);
+		obj = (void*)(size_t(obj) + i->baseOffset);
 		(((asCSimpleDummy*)obj)->*f)(param);
 	}
 	else
@@ -3185,9 +3201,9 @@ int asCScriptEngine::GarbageCollect(asDWORD flags)
 }
 
 // interface
-void asCScriptEngine::GetGCStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected) const
+void asCScriptEngine::GetGCStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected, asUINT *newObjects, asUINT *totalNewDestroyed) const
 {
-	gc.GetStatistics(currentSize, totalDestroyed, totalDetected);
+	gc.GetStatistics(currentSize, totalDestroyed, totalDetected, newObjects, totalNewDestroyed);
 }
 
 // interface

+ 4 - 2
ThirdParty/AngelScript/source/as_scriptengine.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2010 Andreas Jonsson
+   Copyright (c) 2003-2011 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -174,7 +174,7 @@ public:
 
 	// Garbage collection
 	virtual int  GarbageCollect(asDWORD flags = asGC_FULL_CYCLE);
-	virtual void GetGCStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected) const;
+	virtual void GetGCStatistics(asUINT *currentSize, asUINT *totalDestroyed, asUINT *totalDetected, asUINT *newObjects, asUINT *totalNewDestroyed) const;
 	virtual void NotifyGarbageCollectorOfNewObject(void *obj, int typeId);
 	virtual void GCEnumCallback(void *reference);
 
@@ -322,6 +322,7 @@ public:
 
 	// An array with all module imported functions
 	asCArray<sBindInfo *>  importedFunctions;
+	asCArray<int>          freeImportedFunctionIdxs;
 
 	// These resources must be protected for multiple accesses
 	mutable asCAtomic      refCount;
@@ -388,6 +389,7 @@ public:
 		int  stringEncoding;
 		int  propertyAccessorMode;
 		bool expandDefaultArrayToTemplate;
+		bool autoGarbageCollect;
 	} ep;
 };
 

+ 46 - 13
ThirdParty/AngelScript/source/as_scriptfunction.cpp

@@ -144,6 +144,10 @@ asCScriptFunction::asCScriptFunction(asCScriptEngine *engine, asCModule *mod, as
 	userData               = 0;
 	id                     = 0;
 
+	// TODO: optimize: The engine could notify the GC just before it wants to
+	//                 discard the function. That way the GC won't waste time
+	//                 trying to determine if the functions are garbage before
+	//                 they can actually be considered garbage.
 	// Notify the GC of script functions
 	if( funcType == asFUNC_SCRIPT )
 		engine->gc.AddScriptObjectToGC(this, &engine->functionBehaviours);
@@ -365,6 +369,28 @@ asCString asCScriptFunction::GetDeclarationStr(bool includeObjectName) const
 	return str;
 }
 
+// interface
+int asCScriptFunction::FindNextLineWithCode(int line) const
+{
+	if( lineNumbers.GetLength() == 0 ) return -1;
+
+	// Check if given line is outside function
+	// TODO: should start at declaration instead of first line of code
+	if( line < (lineNumbers[1]&0xFFFFF) ) return -1;
+	if( line > (lineNumbers[lineNumbers.GetLength()-1]&0xFFFFF) ) return -1;
+
+	// Find the line with code on or right after the input line
+	// TODO: optimize: Do binary search instead
+	if( line == (lineNumbers[1]&0xFFFFF) ) return line;
+	for( asUINT n = 3; n < lineNumbers.GetLength(); n += 2 )
+	{
+		if( line <= (lineNumbers[n]&0xFFFFF) )
+			return (lineNumbers[n]&0xFFFFF);
+	}
+
+	return -1;
+}
+
 // internal
 int asCScriptFunction::GetLineNumber(int programPosition)
 {
@@ -409,7 +435,7 @@ asEFuncType asCScriptFunction::GetFuncType() const
 }
 
 // interface
-int asCScriptFunction::GetVarCount() const
+asUINT asCScriptFunction::GetVarCount() const
 {
 	return int(variables.GetLength());
 }
@@ -446,9 +472,10 @@ const char *asCScriptFunction::GetVarDecl(asUINT index) const
 void asCScriptFunction::AddVariable(asCString &name, asCDataType &type, int stackOffset)
 {
 	asSScriptVariable *var = asNEW(asSScriptVariable);
-	var->name        = name;
-	var->type        = type;
-	var->stackOffset = stackOffset;
+	var->name                 = name;
+	var->type                 = type;
+	var->stackOffset          = stackOffset;
+	var->declaredAtProgramPos = 0;
 	variables.PushLast(var);
 }
 
@@ -729,15 +756,15 @@ int asCScriptFunction::GetReturnTypeId() const
 }
 
 // interface
-int asCScriptFunction::GetParamCount() const
+asUINT asCScriptFunction::GetParamCount() const
 {
-	return (int)parameterTypes.GetLength();
+	return (asUINT)parameterTypes.GetLength();
 }
 
 // interface
-int asCScriptFunction::GetParamTypeId(int index, asDWORD *flags) const
+int asCScriptFunction::GetParamTypeId(asUINT index, asDWORD *flags) const
 {
-	if( index < 0 || (unsigned)index >= parameterTypes.GetLength() )
+	if( index >= parameterTypes.GetLength() )
 		return asINVALID_ARG;
 
 	if( flags )
@@ -970,17 +997,23 @@ void asCScriptFunction::ReleaseAllHandles(asIScriptEngine *)
 		case asBC_FREE:
 		case asBC_REFCPY:
 			{
-                asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
-				objType->Release();
-				*(void**)&byteCode[n+1] = 0;
+				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]);
-				objType->Release();
-				*(void**)&byteCode[n+1] = 0;
+				if( objType )
+				{
+					objType->Release();
+				*	(void**)&byteCode[n+1] = 0;
+				}
 
 				int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE);
 				if( func )

+ 5 - 3
ThirdParty/AngelScript/source/as_scriptfunction.h

@@ -58,6 +58,7 @@ struct asSScriptVariable
 	asCString   name;
 	asCDataType type;
 	int         stackOffset;
+	asUINT      declaredAtProgramPos;
 };
 
 enum asEObjVarInfoOption
@@ -109,14 +110,15 @@ public:
 	bool                 IsReadOnly() const;
 	bool                 IsPrivate() const;
 
-	int                  GetParamCount() const;
-	int                  GetParamTypeId(int index, asDWORD *flags = 0) const;
+	asUINT               GetParamCount() const;
+	int                  GetParamTypeId(asUINT index, asDWORD *flags = 0) const;
 	int                  GetReturnTypeId() const;
 
 	// Debug information
-	int                  GetVarCount() const;
+	asUINT               GetVarCount() const;
 	int                  GetVar(asUINT index, const char **name, int *typeId = 0) const;
 	const char *         GetVarDecl(asUINT index) const;
+	int                  FindNextLineWithCode(int line) const;
 
 	// For JIT compilation
 	asDWORD             *GetByteCode(asUINT *length = 0);

+ 6 - 1
ThirdParty/AngelScript/source/as_scriptobject.cpp

@@ -40,6 +40,12 @@ BEGIN_AS_NAMESPACE
 asIScriptObject *ScriptObjectFactory(asCObjectType *objType, asCScriptEngine *engine)
 {
 	asIScriptContext *ctx;
+
+	// TODO: optimize: There should be a pool for the context so it doesn't 
+	//                 have to be allocated just for creating the script object
+
+	// TODO: It must be possible for the application to debug the creation of the object too
+
 	int r = engine->CreateContext(&ctx, true);
 	if( r < 0 )
 		return 0;
@@ -54,7 +60,6 @@ asIScriptObject *ScriptObjectFactory(asCObjectType *objType, asCScriptEngine *en
 	r = ctx->Execute();
 	if( r != asEXECUTION_FINISHED )
 	{
-		// TODO: Verify that the memory for the structure have been released already
 		ctx->Release();
 		return 0;
 	}

+ 1 - 4
ThirdParty/AngelScript/source/as_texts.h

@@ -43,7 +43,6 @@
 
 #define TXT_s_ALREADY_DECLARED            "'%s' is already declared"
 #define TXT_ARG_NOT_LVALUE                "Argument cannot be assigned. Output will be discarded."
-#define TXT_ASSIGN_IN_GLOBAL_EXPR         "Assignments are not allowed in global expressions"
 
 #define TXT_BOTH_MUST_BE_SAME                     "Both expressions must have the same type"
 #define TXT_BOTH_CONDITIONS_MUST_CALL_CONSTRUCTOR "Both conditions must call constructor"
@@ -89,7 +88,6 @@
 
 #define TXT_FAILED_TO_COMPILE_DEF_ARG_d_IN_FUNC_s "Failed while compiling default arg for parameter %d in function '%s'"
 #define TXT_FOUND_MULTIPLE_ENUM_VALUES    "Found multiple matching enum values"
-#define TXT_FUNCTION_IN_GLOBAL_EXPR       "Function calls are not allowed in global expressions"
 #define TXT_FUNCTION_ALREADY_EXIST        "A function with the same name and parameters already exist"
 #define TXT_FUNCTION_s_NOT_FOUND          "Function '%s' not found"
 
@@ -106,7 +104,6 @@
 #define TXT_ILLEGAL_OPERATION_ON_s              "Illegal operation on '%s'"
 #define TXT_ILLEGAL_TARGET_TYPE_FOR_REF_CAST    "Illegal target type for reference cast"
 #define TXT_ILLEGAL_VARIABLE_NAME_s             "Illegal variable name '%s'."
-#define TXT_INC_OP_IN_GLOBAL_EXPR               "Incremental operators are not allowed in global expressions"
 #define TXT_INIT_LIST_CANNOT_BE_USED_WITH_s     "Initialization lists cannot be used with '%s'"
 #define TXT_INTERFACE_s_ALREADY_IMPLEMENTED     "The interface '%s' is already implemented"
 #define TXT_INVALID_BREAK                       "Invalid 'break'"
@@ -120,7 +117,6 @@
 #define TXT_INVALID_UNICODE_VALUE               "Invalid unicode code point"
 #define TXT_INVALID_UNICODE_SEQUENCE_IN_SRC     "Invalid unicode sequence in source"
 
-#define TXT_METHOD_IN_GLOBAL_EXPR                   "Object method calls are not allowed in global expressions"
 #define TXT_METHOD_CANT_HAVE_NAME_OF_CLASS          "The method cannot be named with the class name"
 #define TXT_MISSING_IMPLEMENTATION_OF_s             "Missing implementation of '%s'"
 #define TXT_MORE_THAN_ONE_MATCHING_OP               "Found more than one matching operator"
@@ -150,6 +146,7 @@
 #define TXT_NO_MATCHING_OP_FOUND_FOR_TYPE_s        "No matching operator that takes the type '%s' found"
 #define TXT_NO_MATCHING_OP_FOUND_FOR_TYPES_s_AND_s "No matching operator that takes the types '%s' and '%s' found"
 #define TXT_NON_CONST_METHOD_ON_CONST_OBJ          "Non-const method call on read-only object reference"
+#define TXT_NOT_A_FUNC_s_IS_VAR                    "Expression doesn't form a function call. '%s' is a variable of a non-function type"
 #define TXT_NOT_ALL_PATHS_RETURN                   "Not all paths return a value"
 #define TXT_s_NOT_DECLARED                         "'%s' is not declared"
 #define TXT_NOT_EXACT                              "Implicit conversion of value is not exact"

+ 12 - 1
ThirdParty/AngelScript/source/as_thread.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2008 Andreas Jonsson
+   Copyright (c) 2003-2011 Andreas Jonsson
 
    This software is provided 'as-is', without any express or implied 
    warranty. In no event will the authors be held liable for any 
@@ -262,6 +262,17 @@ void asCThreadCriticalSection::Leave()
 	LeaveCriticalSection(&criticalSection);
 #endif
 }
+
+bool asCThreadCriticalSection::TryEnter()
+{
+#if defined AS_POSIX_THREADS
+	return !pthread_mutex_trylock(&criticalSection);
+#elif defined AS_WINDOWS_THREADS
+	return TryEnterCriticalSection(&criticalSection) ? true : false;
+#else
+	return true;
+#endif
+}
 #endif
 
 //========================================================================