From fac54acbc9acd838b43105de578a68dc11882991 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Mon, 30 Aug 2021 10:50:47 +0200 Subject: [PATCH] Update to angelscript 2.35 --- server/package.json | 2 +- server/src/CMakeLists.txt | 1 + .../extensions/scriptarray/scriptarray.cpp | 141 +-- .../extensions/scriptarray/scriptarray.h | 2 +- .../extensions/scriptbuilder/scriptbuilder.h | 7 +- .../extensions/scripthandle/scripthandle.cpp | 527 ++++++----- .../extensions/scripthelper/scripthelper.cpp | 3 +- .../scriptstdstring/scriptstdstring.cpp | 71 +- .../scriptstdstring/scriptstdstring_utils.cpp | 3 +- server/src/angelscript/include/angelscript.h | 15 +- server/src/angelscript/source/as_builder.cpp | 120 +-- server/src/angelscript/source/as_callfunc.cpp | 10 +- server/src/angelscript/source/as_callfunc.h | 6 +- .../angelscript/source/as_callfunc_arm64.cpp | 329 +++++++ .../source/as_callfunc_arm64_gcc.S | 219 +++++ .../source/as_callfunc_arm64_msvc.asm | 205 +++++ .../angelscript/source/as_callfunc_arm_gcc.S | 6 +- server/src/angelscript/source/as_compiler.cpp | 34 +- server/src/angelscript/source/as_compiler.h | 5 +- server/src/angelscript/source/as_config.h | 95 +- .../src/angelscript/source/as_configgroup.cpp | 3 +- server/src/angelscript/source/as_context.cpp | 25 +- server/src/angelscript/source/as_memory.cpp | 16 +- server/src/angelscript/source/as_module.cpp | 816 ++++++++++-------- server/src/angelscript/source/as_module.h | 59 +- server/src/angelscript/source/as_restore.cpp | 316 ++++--- .../angelscript/source/as_scriptengine.cpp | 131 ++- .../src/angelscript/source/as_scriptengine.h | 4 +- .../angelscript/source/as_scriptfunction.cpp | 6 +- .../angelscript/source/as_scriptobject.cpp | 63 +- .../src/angelscript/source/as_scriptobject.h | 7 +- .../src/angelscript/source/as_symboltable.h | 2 +- server/src/angelscript/source/as_typeinfo.cpp | 5 +- server/src/server.ts | 5 +- 34 files changed, 2187 insertions(+), 1072 deletions(-) create mode 100644 server/src/angelscript/source/as_callfunc_arm64.cpp create mode 100644 server/src/angelscript/source/as_callfunc_arm64_gcc.S create mode 100644 server/src/angelscript/source/as_callfunc_arm64_msvc.asm diff --git a/server/package.json b/server/package.json index 84300ff..8e5af12 100644 --- a/server/package.json +++ b/server/package.json @@ -18,6 +18,6 @@ "vscode-languageserver-textdocument": "^1.0.1" }, "scripts": { - "install": "cmake-js compile -d src -O build" + "install": "cmake-js compile -d src -O build; tsc" } } diff --git a/server/src/CMakeLists.txt b/server/src/CMakeLists.txt index 67340e1..75fba66 100644 --- a/server/src/CMakeLists.txt +++ b/server/src/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_policy(SET CMP0042 NEW) project(aslsp-native) set (CMAKE_CXX_STANDARD 20) +set(BUILD_SHARED_LIBS OFF) include_directories(${CMAKE_JS_INC} angelscript/include) message(info ${CMAKE_JS_INC}) diff --git a/server/src/angelscript/extensions/scriptarray/scriptarray.cpp b/server/src/angelscript/extensions/scriptarray/scriptarray.cpp index d7ccda3..58512f3 100644 --- a/server/src/angelscript/extensions/scriptarray/scriptarray.cpp +++ b/server/src/angelscript/extensions/scriptarray/scriptarray.cpp @@ -4,6 +4,7 @@ #include #include // sprintf #include +#include // std::sort #include "scriptarray.h" @@ -998,7 +999,7 @@ void CScriptArray::Destruct(SArrayBuffer *buf, asUINT start, asUINT end) // internal -bool CScriptArray::Less(const void *a, const void *b, bool asc, asIScriptContext *ctx, SArrayCache *cache) +bool CScriptArray::Less(const void *a, const void *b, bool asc) { if( !asc ) { @@ -1027,42 +1028,6 @@ bool CScriptArray::Less(const void *a, const void *b, bool asc, asIScriptContext #undef COMPARE } } - else - { - int r = 0; - - if( subTypeId & asTYPEID_OBJHANDLE ) - { - // Allow sort to work even if the array contains null handles - if( *(void**)a == 0 ) return true; - if( *(void**)b == 0 ) return false; - } - - // Execute object opCmp - if( cache && cache->cmpFunc ) - { - // TODO: Add proper error handling - r = ctx->Prepare(cache->cmpFunc); assert(r >= 0); - - if( subTypeId & asTYPEID_OBJHANDLE ) - { - r = ctx->SetObject(*((void**)a)); assert(r >= 0); - r = ctx->SetArgObject(0, *((void**)b)); assert(r >= 0); - } - else - { - r = ctx->SetObject((void*)a); assert(r >= 0); - r = ctx->SetArgObject(0, (void*)b); assert(r >= 0); - } - - r = ctx->Execute(); - - if( r == asEXECUTION_FINISHED ) - { - return (int)ctx->GetReturnDWord() < 0; - } - } - } return false; } @@ -1475,12 +1440,11 @@ void CScriptArray::Sort(asUINT startAt, asUINT count, bool asc) return; } - asBYTE tmp[16]; - asIScriptContext *cmpContext = 0; - bool isNested = false; - if( subTypeId & ~asTYPEID_MASK_SEQNBR ) { + asIScriptContext *cmpContext = 0; + bool isNested = false; + // Try to reuse the active context cmpContext = asGetActiveContext(); if( cmpContext ) @@ -1491,38 +1455,83 @@ void CScriptArray::Sort(asUINT startAt, asUINT count, bool asc) cmpContext = 0; } if( cmpContext == 0 ) - { cmpContext = objType->GetEngine()->RequestContext(); + + // Do the sorting + struct { + bool asc; + asIScriptContext *cmpContext; + asIScriptFunction *cmpFunc; + bool operator()(void *a, void *b) const + { + if( !asc ) + { + // Swap items + void *TEMP = a; + a = b; + b = TEMP; + } + + int r = 0; + + // Allow sort to work even if the array contains null handles + if( a == 0 ) return true; + if( b == 0 ) return false; + + // Execute object opCmp + if( cmpFunc ) + { + // TODO: Add proper error handling + r = cmpContext->Prepare(cmpFunc); assert(r >= 0); + r = cmpContext->SetObject(a); assert(r >= 0); + r = cmpContext->SetArgObject(0, b); assert(r >= 0); + r = cmpContext->Execute(); + + if( r == asEXECUTION_FINISHED ) + { + return (int)cmpContext->GetReturnDWord() < 0; + } + } + + return false; + } + } customLess = {asc, cmpContext, cache ? cache->cmpFunc : 0}; + std::sort((void**)GetArrayItemPointer(start), (void**)GetArrayItemPointer(end), customLess); + + // Clean up + if( cmpContext ) + { + if( isNested ) + { + asEContextState state = cmpContext->GetState(); + cmpContext->PopState(); + if( state == asEXECUTION_ABORTED ) + cmpContext->Abort(); + } + else + objType->GetEngine()->ReturnContext(cmpContext); } } - - // Insertion sort - for( int i = start + 1; i < end; i++ ) + else { - Copy(tmp, GetArrayItemPointer(i)); - - int j = i - 1; - - while( j >= start && Less(GetDataPointer(tmp), At(j), asc, cmpContext, cache) ) + // TODO: Use std::sort for primitive types too + + // Insertion sort + asBYTE tmp[16]; + for( int i = start + 1; i < end; i++ ) { - Copy(GetArrayItemPointer(j + 1), GetArrayItemPointer(j)); - j--; - } + Copy(tmp, GetArrayItemPointer(i)); - Copy(GetArrayItemPointer(j + 1), tmp); - } + int j = i - 1; - if( cmpContext ) - { - if( isNested ) - { - asEContextState state = cmpContext->GetState(); - cmpContext->PopState(); - if( state == asEXECUTION_ABORTED ) - cmpContext->Abort(); + while( j >= start && Less(GetDataPointer(tmp), At(j), asc) ) + { + Copy(GetArrayItemPointer(j + 1), GetArrayItemPointer(j)); + j--; + } + + Copy(GetArrayItemPointer(j + 1), tmp); } - else - objType->GetEngine()->ReturnContext(cmpContext); } } @@ -1550,7 +1559,6 @@ void CScriptArray::Sort(asIScriptFunction *func, asUINT startAt, asUINT count) return; } - asBYTE tmp[16]; asIScriptContext *cmpContext = 0; bool isNested = false; @@ -1567,6 +1575,7 @@ void CScriptArray::Sort(asIScriptFunction *func, asUINT startAt, asUINT count) cmpContext = objType->GetEngine()->RequestContext(); // Insertion sort + asBYTE tmp[16]; for (asUINT i = start + 1; i < end; i++) { Copy(tmp, GetArrayItemPointer(i)); diff --git a/server/src/angelscript/extensions/scriptarray/scriptarray.h b/server/src/angelscript/extensions/scriptarray/scriptarray.h index 41b34dd..4903a97 100644 --- a/server/src/angelscript/extensions/scriptarray/scriptarray.h +++ b/server/src/angelscript/extensions/scriptarray/scriptarray.h @@ -120,7 +120,7 @@ protected: CScriptArray(const CScriptArray &other); virtual ~CScriptArray(); - bool Less(const void *a, const void *b, bool asc, asIScriptContext *ctx, SArrayCache *cache); + bool Less(const void *a, const void *b, bool asc); void *GetArrayItemPointer(int index); void *GetDataPointer(void *buffer); void Copy(void *dst, void *src); diff --git a/server/src/angelscript/extensions/scriptbuilder/scriptbuilder.h b/server/src/angelscript/extensions/scriptbuilder/scriptbuilder.h index 4326f7c..c11f1b9 100644 --- a/server/src/angelscript/extensions/scriptbuilder/scriptbuilder.h +++ b/server/src/angelscript/extensions/scriptbuilder/scriptbuilder.h @@ -14,6 +14,8 @@ // TODO: Implement flags for turning on/off include directives and conditional programming + + //--------------------------- // Declaration // @@ -23,9 +25,10 @@ #include #endif + #if defined(_MSC_VER) && _MSC_VER <= 1200 // disable the annoying warnings on MSVC 6 -#pragma warning(disable : 4786) +#pragma warning (disable:4786) #endif #include @@ -197,7 +200,7 @@ protected: { bool operator()(const std::string &a, const std::string &b) const { - return _strcmpi(a.c_str(), b.c_str()) < 0; + return _stricmp(a.c_str(), b.c_str()) < 0; } }; std::set includedScripts; diff --git a/server/src/angelscript/extensions/scripthandle/scripthandle.cpp b/server/src/angelscript/extensions/scripthandle/scripthandle.cpp index f4de29a..df6cbbe 100644 --- a/server/src/angelscript/extensions/scripthandle/scripthandle.cpp +++ b/server/src/angelscript/extensions/scripthandle/scripthandle.cpp @@ -1,367 +1,360 @@ #include "scripthandle.h" -#include #include +#include #include BEGIN_AS_NAMESPACE -static void Construct(CScriptHandle* self) { new (self) CScriptHandle(); } -static void Construct(CScriptHandle* self, const CScriptHandle& o) { new (self) CScriptHandle(o); } +static void Construct(CScriptHandle *self) { new(self) CScriptHandle(); } +static void Construct(CScriptHandle *self, const CScriptHandle &o) { new(self) CScriptHandle(o); } // This one is not static because it needs to be friend with the CScriptHandle class -void Construct(CScriptHandle* self, void* ref, int typeId) { new (self) CScriptHandle(ref, typeId); } -static void Destruct(CScriptHandle* self) { self->~CScriptHandle(); } +void Construct(CScriptHandle *self, void *ref, int typeId) { new(self) CScriptHandle(ref, typeId); } +static void Destruct(CScriptHandle *self) { self->~CScriptHandle(); } -CScriptHandle::CScriptHandle() { - m_ref = 0; - m_type = 0; +CScriptHandle::CScriptHandle() +{ + m_ref = 0; + m_type = 0; } -CScriptHandle::CScriptHandle(const CScriptHandle& other) { - m_ref = other.m_ref; - m_type = other.m_type; +CScriptHandle::CScriptHandle(const CScriptHandle &other) +{ + m_ref = other.m_ref; + m_type = other.m_type; - AddRefHandle(); + AddRefHandle(); } -CScriptHandle::CScriptHandle(void* ref, asITypeInfo* type) { - m_ref = ref; - m_type = type; +CScriptHandle::CScriptHandle(void *ref, asITypeInfo *type) +{ + m_ref = ref; + m_type = type; - AddRefHandle(); + AddRefHandle(); } -// This constructor shouldn't be called from the application +// This constructor shouldn't be called from the application // directly as it requires an active script context -CScriptHandle::CScriptHandle(void* ref, int typeId) { - m_ref = 0; - m_type = 0; +CScriptHandle::CScriptHandle(void *ref, int typeId) +{ + m_ref = 0; + m_type = 0; - Assign(ref, typeId); + Assign(ref, typeId); } -CScriptHandle::~CScriptHandle() { ReleaseHandle(); } - -void CScriptHandle::ReleaseHandle() { - if (m_ref && m_type) { - asIScriptEngine* engine = m_type->GetEngine(); - engine->ReleaseScriptObject(m_ref, m_type); - - engine->Release(); - - m_ref = 0; - m_type = 0; - } +CScriptHandle::~CScriptHandle() +{ + ReleaseHandle(); } -void CScriptHandle::AddRefHandle() { - if (m_ref && m_type) { - asIScriptEngine* engine = m_type->GetEngine(); - engine->AddRefScriptObject(m_ref, m_type); +void CScriptHandle::ReleaseHandle() +{ + if( m_ref && m_type ) + { + asIScriptEngine *engine = m_type->GetEngine(); + engine->ReleaseScriptObject(m_ref, m_type); - // Hold on to the engine so it isn't destroyed while - // a reference to a script object is still held - engine->AddRef(); - } + engine->Release(); + + m_ref = 0; + m_type = 0; + } } -CScriptHandle& CScriptHandle::operator=(const CScriptHandle& other) { - Set(other.m_ref, other.m_type); +void CScriptHandle::AddRefHandle() +{ + if( m_ref && m_type ) + { + asIScriptEngine *engine = m_type->GetEngine(); + engine->AddRefScriptObject(m_ref, m_type); - return *this; + // Hold on to the engine so it isn't destroyed while + // a reference to a script object is still held + engine->AddRef(); + } } -void CScriptHandle::Set(void* ref, asITypeInfo* type) { - if (m_ref == ref) - return; +CScriptHandle &CScriptHandle::operator =(const CScriptHandle &other) +{ + Set(other.m_ref, other.m_type); - ReleaseHandle(); - - m_ref = ref; - m_type = type; - - AddRefHandle(); + return *this; } -void* CScriptHandle::GetRef() { return m_ref; } +void CScriptHandle::Set(void *ref, asITypeInfo *type) +{ + if( m_ref == ref ) return; -asITypeInfo* CScriptHandle::GetType() const { return m_type; } + ReleaseHandle(); -int CScriptHandle::GetTypeId() const { - if (m_type == 0) - return 0; + m_ref = ref; + m_type = type; - return m_type->GetTypeId() | asTYPEID_OBJHANDLE; + AddRefHandle(); } -// This method shouldn't be called from the application +void *CScriptHandle::GetRef() +{ + return m_ref; +} + +asITypeInfo *CScriptHandle::GetType() const +{ + return m_type; +} + +int CScriptHandle::GetTypeId() const +{ + if( m_type == 0 ) return 0; + + return m_type->GetTypeId() | asTYPEID_OBJHANDLE; +} + +// This method shouldn't be called from the application // directly as it requires an active script context -CScriptHandle& CScriptHandle::Assign(void* ref, int typeId) { - // When receiving a null handle we just clear our memory - if (typeId == 0) { - Set(0, 0); - return *this; - } +CScriptHandle &CScriptHandle::Assign(void *ref, int typeId) +{ + // When receiving a null handle we just clear our memory + if( typeId == 0 ) + { + Set(0, 0); + return *this; + } - // Dereference received handles to get the object - if (typeId & asTYPEID_OBJHANDLE) { - // Store the actual reference - ref = *(void**)ref; - typeId &= ~asTYPEID_OBJHANDLE; - } + // Dereference received handles to get the object + if( typeId & asTYPEID_OBJHANDLE ) + { + // Store the actual reference + ref = *(void**)ref; + typeId &= ~asTYPEID_OBJHANDLE; + } - // Get the object type - asIScriptContext* ctx = asGetActiveContext(); - asIScriptEngine* engine = ctx->GetEngine(); - asITypeInfo* type = engine->GetTypeInfoById(typeId); + // Get the object type + asIScriptContext *ctx = asGetActiveContext(); + asIScriptEngine *engine = ctx->GetEngine(); + asITypeInfo *type = engine->GetTypeInfoById(typeId); - // If the argument is another CScriptHandle, we should copy the content instead - if (type && strcmp(type->GetName(), "ref") == 0) { - CScriptHandle* r = (CScriptHandle*)ref; - ref = r->m_ref; - type = r->m_type; - } + // If the argument is another CScriptHandle, we should copy the content instead + if( type && strcmp(type->GetName(), "ref") == 0 ) + { + CScriptHandle *r = (CScriptHandle*)ref; + ref = r->m_ref; + type = r->m_type; + } - Set(ref, type); + Set(ref, type); - return *this; + return *this; } -bool CScriptHandle::operator==(const CScriptHandle& o) const { - if (m_ref == o.m_ref && m_type == o.m_type) - return true; +bool CScriptHandle::operator==(const CScriptHandle &o) const +{ + if( m_ref == o.m_ref && + m_type == o.m_type ) + return true; - // TODO: If type is not the same, we should attempt to do a dynamic cast, - // which may change the pointer for application registered classes + // TODO: If type is not the same, we should attempt to do a dynamic cast, + // which may change the pointer for application registered classes - return false; + return false; } -bool CScriptHandle::operator!=(const CScriptHandle& o) const { return !(*this == o); } +bool CScriptHandle::operator!=(const CScriptHandle &o) const +{ + return !(*this == o); +} -bool CScriptHandle::Equals(void* ref, int typeId) const { - // Null handles are received as reference to a null handle - if (typeId == 0) - ref = 0; +bool CScriptHandle::Equals(void *ref, int typeId) const +{ + // Null handles are received as reference to a null handle + if( typeId == 0 ) + ref = 0; - // Dereference handles to get the object - if (typeId & asTYPEID_OBJHANDLE) { - // Compare the actual reference - ref = *(void**)ref; - typeId &= ~asTYPEID_OBJHANDLE; - } + // Dereference handles to get the object + if( typeId & asTYPEID_OBJHANDLE ) + { + // Compare the actual reference + ref = *(void**)ref; + typeId &= ~asTYPEID_OBJHANDLE; + } - // TODO: If typeId is not the same, we should attempt to do a dynamic cast, - // which may change the pointer for application registered classes + // TODO: If typeId is not the same, we should attempt to do a dynamic cast, + // which may change the pointer for application registered classes - if (ref == m_ref) - return true; + if( ref == m_ref ) return true; - return false; + return false; } // AngelScript: used as '@obj = cast(ref);' -void CScriptHandle::Cast(void** outRef, int typeId) { - // If we hold a null handle, then just return null - if (m_type == 0) { - *outRef = 0; - return; - } +void CScriptHandle::Cast(void **outRef, int typeId) +{ + // If we hold a null handle, then just return null + if( m_type == 0 ) + { + *outRef = 0; + return; + } + + // It is expected that the outRef is always a handle + assert( typeId & asTYPEID_OBJHANDLE ); - // It is expected that the outRef is always a handle - assert(typeId & asTYPEID_OBJHANDLE); + // Compare the type id of the actual object + typeId &= ~asTYPEID_OBJHANDLE; + asIScriptEngine *engine = m_type->GetEngine(); + asITypeInfo *type = engine->GetTypeInfoById(typeId); - // Compare the type id of the actual object - typeId &= ~asTYPEID_OBJHANDLE; - asIScriptEngine* engine = m_type->GetEngine(); - asITypeInfo* type = engine->GetTypeInfoById(typeId); + *outRef = 0; - *outRef = 0; - - // RefCastObject will increment the refCount of the returned object if successful - engine->RefCastObject(m_ref, m_type, type, outRef); + // RefCastObject will increment the refCount of the returned object if successful + engine->RefCastObject(m_ref, m_type, type, outRef); } -void CScriptHandle::EnumReferences(asIScriptEngine* inEngine) { - // If we're holding a reference, we'll notify the garbage collector of it - if (m_ref) - inEngine->GCEnumCallback(m_ref); +void CScriptHandle::EnumReferences(asIScriptEngine *inEngine) +{ + // If we're holding a reference, we'll notify the garbage collector of it + if (m_ref) + inEngine->GCEnumCallback(m_ref); - // The object type itself is also garbage collected - if (m_type) - inEngine->GCEnumCallback(m_type); + // The object type itself is also garbage collected + if( m_type) + inEngine->GCEnumCallback(m_type); } -void CScriptHandle::ReleaseReferences(asIScriptEngine*) { - // Simply clear the content to release the references - Set(0, 0); +void CScriptHandle::ReleaseReferences(asIScriptEngine *inEngine) +{ + // Simply clear the content to release the references + Set(0, 0); } -void RegisterScriptHandle_Native(asIScriptEngine* engine) { - [[maybe_unused]] int r; +void RegisterScriptHandle_Native(asIScriptEngine *engine) +{ + int r; #if AS_CAN_USE_CPP11 - // With C++11 it is possible to use asGetTypeTraits to automatically determine the flags that represent the C++ - // class - r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), - asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asGetTypeTraits()); - assert(r >= 0); + // With C++11 it is possible to use asGetTypeTraits to automatically determine the flags that represent the C++ class + r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asGetTypeTraits()); assert( r >= 0 ); #else - r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), - asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK); - assert(r >= 0); + r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK); assert( r >= 0 ); #endif - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", - asFUNCTIONPR(Construct, (CScriptHandle*), void), asCALL_CDECL_OBJFIRST); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ref &in)", - asFUNCTIONPR(Construct, (CScriptHandle*, const CScriptHandle&), void), - asCALL_CDECL_OBJFIRST); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", - asFUNCTIONPR(Construct, (CScriptHandle*, void*, int), void), - asCALL_CDECL_OBJFIRST); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_DESTRUCT, "void f()", - asFUNCTIONPR(Destruct, (CScriptHandle*), void), asCALL_CDECL_OBJFIRST); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_ENUMREFS, "void f(int&in)", - asMETHOD(CScriptHandle, EnumReferences), asCALL_THISCALL); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_RELEASEREFS, "void f(int&in)", - asMETHOD(CScriptHandle, ReleaseReferences), asCALL_THISCALL); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "void opCast(?&out)", asMETHODPR(CScriptHandle, Cast, (void**, int), void), - asCALL_THISCALL); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ref &in)", asMETHOD(CScriptHandle, operator=), - asCALL_THISCALL); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ?&in)", asMETHOD(CScriptHandle, Assign), - asCALL_THISCALL); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "bool opEquals(const ref &in) const", - asMETHODPR(CScriptHandle, operator==,(const CScriptHandle&) const, bool), - asCALL_THISCALL); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "bool opEquals(const ?&in) const", - asMETHODPR(CScriptHandle, Equals, (void*, int)const, bool), asCALL_THISCALL); - assert(r >= 0); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", asFUNCTIONPR(Construct, (CScriptHandle *), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ref &in)", asFUNCTIONPR(Construct, (CScriptHandle *, const CScriptHandle &), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", asFUNCTIONPR(Construct, (CScriptHandle *, void *, int), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_DESTRUCT, "void f()", asFUNCTIONPR(Destruct, (CScriptHandle *), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(CScriptHandle,EnumReferences), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(CScriptHandle, ReleaseReferences), asCALL_THISCALL); assert(r >= 0); + r = engine->RegisterObjectMethod("ref", "void opCast(?&out)", asMETHODPR(CScriptHandle, Cast, (void **, int), void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ref &in)", asMETHOD(CScriptHandle, operator=), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ?&in)", asMETHOD(CScriptHandle, Assign), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "bool opEquals(const ref &in) const", asMETHODPR(CScriptHandle, operator==, (const CScriptHandle &) const, bool), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "bool opEquals(const ?&in) const", asMETHODPR(CScriptHandle, Equals, (void*, int) const, bool), asCALL_THISCALL); assert( r >= 0 ); } -void CScriptHandle_Construct_Generic(asIScriptGeneric* gen) { - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - new (self) CScriptHandle(); +void CScriptHandle_Construct_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + new(self) CScriptHandle(); } -void CScriptHandle_ConstructCopy_Generic(asIScriptGeneric* gen) { - CScriptHandle* other = reinterpret_cast(gen->GetArgAddress(0)); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - new (self) CScriptHandle(*other); +void CScriptHandle_ConstructCopy_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *other = reinterpret_cast(gen->GetArgAddress(0)); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + new(self) CScriptHandle(*other); } -void CScriptHandle_ConstructVar_Generic(asIScriptGeneric* gen) { - void* ref = gen->GetArgAddress(0); - int typeId = gen->GetArgTypeId(0); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - Construct(self, ref, typeId); +void CScriptHandle_ConstructVar_Generic(asIScriptGeneric *gen) +{ + void *ref = gen->GetArgAddress(0); + int typeId = gen->GetArgTypeId(0); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + Construct(self, ref, typeId); } -void CScriptHandle_Destruct_Generic(asIScriptGeneric* gen) { - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - self->~CScriptHandle(); +void CScriptHandle_Destruct_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + self->~CScriptHandle(); } -void CScriptHandle_Cast_Generic(asIScriptGeneric* gen) { - void** ref = reinterpret_cast(gen->GetArgAddress(0)); - int typeId = gen->GetArgTypeId(0); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - self->Cast(ref, typeId); +void CScriptHandle_Cast_Generic(asIScriptGeneric *gen) +{ + void **ref = reinterpret_cast(gen->GetArgAddress(0)); + int typeId = gen->GetArgTypeId(0); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + self->Cast(ref, typeId); } -void CScriptHandle_Assign_Generic(asIScriptGeneric* gen) { - CScriptHandle* other = reinterpret_cast(gen->GetArgAddress(0)); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - *self = *other; - gen->SetReturnAddress(self); +void CScriptHandle_Assign_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *other = reinterpret_cast(gen->GetArgAddress(0)); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + *self = *other; + gen->SetReturnAddress(self); } -void CScriptHandle_AssignVar_Generic(asIScriptGeneric* gen) { - void* ref = gen->GetArgAddress(0); - int typeId = gen->GetArgTypeId(0); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - self->Assign(ref, typeId); - gen->SetReturnAddress(self); +void CScriptHandle_AssignVar_Generic(asIScriptGeneric *gen) +{ + void *ref = gen->GetArgAddress(0); + int typeId = gen->GetArgTypeId(0); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + self->Assign(ref, typeId); + gen->SetReturnAddress(self); } -void CScriptHandle_Equals_Generic(asIScriptGeneric* gen) { - CScriptHandle* other = reinterpret_cast(gen->GetArgAddress(0)); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - gen->SetReturnByte(*self == *other); +void CScriptHandle_Equals_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *other = reinterpret_cast(gen->GetArgAddress(0)); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + gen->SetReturnByte(*self == *other); } -void CScriptHandle_EqualsVar_Generic(asIScriptGeneric* gen) { - void* ref = gen->GetArgAddress(0); - int typeId = gen->GetArgTypeId(0); - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - gen->SetReturnByte(self->Equals(ref, typeId)); +void CScriptHandle_EqualsVar_Generic(asIScriptGeneric *gen) +{ + void *ref = gen->GetArgAddress(0); + int typeId = gen->GetArgTypeId(0); + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + gen->SetReturnByte(self->Equals(ref, typeId)); } -void CScriptHandle_EnumReferences_Generic(asIScriptGeneric* gen) { - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - self->EnumReferences(gen->GetEngine()); +void CScriptHandle_EnumReferences_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + self->EnumReferences(gen->GetEngine()); } -void CScriptHandle_ReleaseReferences_Generic(asIScriptGeneric* gen) { - CScriptHandle* self = reinterpret_cast(gen->GetObject()); - self->ReleaseReferences(gen->GetEngine()); +void CScriptHandle_ReleaseReferences_Generic(asIScriptGeneric *gen) +{ + CScriptHandle *self = reinterpret_cast(gen->GetObject()); + self->ReleaseReferences(gen->GetEngine()); } -void RegisterScriptHandle_Generic(asIScriptEngine* engine) { - [[maybe_unused]] int r; +void RegisterScriptHandle_Generic(asIScriptEngine *engine) +{ + int r; - r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), - asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", - asFUNCTION(CScriptHandle_Construct_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ref &in)", - asFUNCTION(CScriptHandle_ConstructCopy_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", - asFUNCTION(CScriptHandle_ConstructVar_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_DESTRUCT, "void f()", - asFUNCTION(CScriptHandle_Destruct_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_ENUMREFS, "void f(int&in)", - asFUNCTION(CScriptHandle_EnumReferences_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectBehaviour("ref", asBEHAVE_RELEASEREFS, "void f(int&in)", - asFUNCTION(CScriptHandle_ReleaseReferences_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "void opCast(?&out)", asFUNCTION(CScriptHandle_Cast_Generic), - asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ref &in)", - asFUNCTION(CScriptHandle_Assign_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ?&in)", - asFUNCTION(CScriptHandle_AssignVar_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "bool opEquals(const ref &in) const", - asFUNCTION(CScriptHandle_Equals_Generic), asCALL_GENERIC); - assert(r >= 0); - r = engine->RegisterObjectMethod("ref", "bool opEquals(const ?&in) const", - asFUNCTION(CScriptHandle_EqualsVar_Generic), asCALL_GENERIC); - assert(r >= 0); + r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(CScriptHandle_Construct_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ref &in)", asFUNCTION(CScriptHandle_ConstructCopy_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", asFUNCTION(CScriptHandle_ConstructVar_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(CScriptHandle_Destruct_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(CScriptHandle_EnumReferences_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectBehaviour("ref", asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(CScriptHandle_ReleaseReferences_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterObjectMethod("ref", "void opCast(?&out)", asFUNCTION(CScriptHandle_Cast_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ref &in)", asFUNCTION(CScriptHandle_Assign_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ?&in)", asFUNCTION(CScriptHandle_AssignVar_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "bool opEquals(const ref &in) const", asFUNCTION(CScriptHandle_Equals_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("ref", "bool opEquals(const ?&in) const", asFUNCTION(CScriptHandle_EqualsVar_Generic), asCALL_GENERIC); assert( r >= 0 ); } -void RegisterScriptHandle(asIScriptEngine* engine) { - if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY")) - RegisterScriptHandle_Generic(engine); - else - RegisterScriptHandle_Native(engine); +void RegisterScriptHandle(asIScriptEngine *engine) +{ + if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) + RegisterScriptHandle_Generic(engine); + else + RegisterScriptHandle_Native(engine); } + END_AS_NAMESPACE diff --git a/server/src/angelscript/extensions/scripthelper/scripthelper.cpp b/server/src/angelscript/extensions/scripthelper/scripthelper.cpp index e70f075..4af4fde 100644 --- a/server/src/angelscript/extensions/scripthelper/scripthelper.cpp +++ b/server/src/angelscript/extensions/scripthelper/scripthelper.cpp @@ -975,8 +975,7 @@ string ScriptGetExceptionInfo() void RegisterExceptionRoutines(asIScriptEngine *engine) { - [[maybe_unused]] - int r; + int r; // The string type must be available assert(engine->GetTypeInfoByDecl("string")); diff --git a/server/src/angelscript/extensions/scriptstdstring/scriptstdstring.cpp b/server/src/angelscript/extensions/scriptstdstring/scriptstdstring.cpp index 2b1a175..2a96ad4 100644 --- a/server/src/angelscript/extensions/scriptstdstring/scriptstdstring.cpp +++ b/server/src/angelscript/extensions/scriptstdstring/scriptstdstring.cpp @@ -28,25 +28,26 @@ typedef map map_t; END_AS_NAMESPACE #endif +BEGIN_AS_NAMESPACE class CStdStringFactory : public asIStringFactory { public: - CStdStringFactory() = default; - ~CStdStringFactory() override + CStdStringFactory() {} + ~CStdStringFactory() { // The script engine must release each string // constant that it has requested - assert(stringCache.empty()); + assert(stringCache.size() == 0); } - const void *GetStringConstant(const char *data, asUINT length) override + const void *GetStringConstant(const char *data, asUINT length) { // The string factory might be modified from multiple // threads, so it is necessary to use a mutex. asAcquireExclusiveLock(); string str(data, length); - auto it = stringCache.find(str); + map_t::iterator it = stringCache.find(str); if (it != stringCache.end()) it->second++; else @@ -57,9 +58,9 @@ public: return reinterpret_cast(&it->first); } - int ReleaseStringConstant(const void *str) override + int ReleaseStringConstant(const void *str) { - if (str == nullptr) + if (str == 0) return asERROR; int ret = asSUCCESS; @@ -68,7 +69,7 @@ public: // threads, so it is necessary to use a mutex. asAcquireExclusiveLock(); - auto it = stringCache.find(*reinterpret_cast(str)); + map_t::iterator it = stringCache.find(*reinterpret_cast(str)); if (it == stringCache.end()) ret = asERROR; else @@ -83,9 +84,9 @@ public: return ret; } - int GetRawStringData(const void *str, char *data, asUINT *length) const override + int GetRawStringData(const void *str, char *data, asUINT *length) const { - if (str == nullptr) + if (str == 0) return asERROR; if (length) @@ -98,17 +99,17 @@ public: } // THe access to the string cache is protected with the common mutex provided by AngelScript - map_t stringCache = {}; + map_t stringCache; }; -static CStdStringFactory *stringFactory = nullptr; +static CStdStringFactory *stringFactory = 0; // TODO: Make this public so the application can also use the string // factory and share the string constants if so desired, or to // monitor the size of the string factory cache. CStdStringFactory *GetStdStringFactorySingleton() { - if( stringFactory == nullptr ) + if( stringFactory == 0 ) { // The following instance will be destroyed by the global // CStdStringFactoryCleaner instance upon application shutdown @@ -122,7 +123,7 @@ class CStdStringFactoryCleaner public: ~CStdStringFactoryCleaner() { - if (stringFactory != nullptr) + if (stringFactory) { // Only delete the string factory if the stringCache is empty // If it is not empty, it means that someone might still attempt @@ -133,13 +134,13 @@ public: if (stringFactory->stringCache.empty()) { delete stringFactory; - stringFactory = nullptr; + stringFactory = 0; } } } }; -static CStdStringFactoryCleaner cleaner = {}; +static CStdStringFactoryCleaner cleaner; static void ConstructString(string *thisPointer) @@ -461,12 +462,12 @@ static void StringResize(asUINT l, string &str) // string formatInt(int64 val, const string &in options, uint width) static string formatInt(asINT64 value, const string &options, asUINT width) { - bool leftJustify = options.find('l') != string::npos; - bool padWithZero = options.find('0') != string::npos; - bool alwaysSign = options.find('+') != string::npos; - bool spaceOnSign = options.find(' ') != string::npos; - bool hexSmall = options.find('h') != string::npos; - bool hexLarge = options.find('H') != string::npos; + bool leftJustify = options.find("l") != string::npos; + bool padWithZero = options.find("0") != string::npos; + bool alwaysSign = options.find("+") != string::npos; + bool spaceOnSign = options.find(" ") != string::npos; + bool hexSmall = options.find("h") != string::npos; + bool hexLarge = options.find("H") != string::npos; string fmt = "%"; if( leftJustify ) fmt += "-"; @@ -505,12 +506,12 @@ static string formatInt(asINT64 value, const string &options, asUINT width) // string formatUInt(uint64 val, const string &in options, uint width) static string formatUInt(asQWORD value, const string &options, asUINT width) { - bool leftJustify = options.find('l') != string::npos; - bool padWithZero = options.find('0') != string::npos; - bool alwaysSign = options.find('+') != string::npos; - bool spaceOnSign = options.find(' ') != string::npos; - bool hexSmall = options.find('h') != string::npos; - bool hexLarge = options.find('H') != string::npos; + bool leftJustify = options.find("l") != string::npos; + bool padWithZero = options.find("0") != string::npos; + bool alwaysSign = options.find("+") != string::npos; + bool spaceOnSign = options.find(" ") != string::npos; + bool hexSmall = options.find("h") != string::npos; + bool hexLarge = options.find("H") != string::npos; string fmt = "%"; if( leftJustify ) fmt += "-"; @@ -549,12 +550,12 @@ static string formatUInt(asQWORD value, const string &options, asUINT width) // string formatFloat(double val, const string &in options, uint width, uint precision) static string formatFloat(double value, const string &options, asUINT width, asUINT precision) { - bool leftJustify = options.find('l') != string::npos; - bool padWithZero = options.find('0') != string::npos; - bool alwaysSign = options.find('+') != string::npos; - bool spaceOnSign = options.find(' ') != string::npos; - bool expSmall = options.find('e') != string::npos; - bool expLarge = options.find('E') != string::npos; + bool leftJustify = options.find("l") != string::npos; + bool padWithZero = options.find("0") != string::npos; + bool alwaysSign = options.find("+") != string::npos; + bool spaceOnSign = options.find(" ") != string::npos; + bool expSmall = options.find("e") != string::npos; + bool expLarge = options.find("E") != string::npos; string fmt = "%"; if( leftJustify ) fmt += "-"; @@ -734,7 +735,7 @@ static string StringSubString(asUINT start, int count, const string &str) // makro, so this wrapper was introduced as work around. static bool StringEquals(const std::string& lhs, const std::string& rhs) { - return lhs == rhs; + return lhs == rhs; } void RegisterStdString_Native(asIScriptEngine *engine) diff --git a/server/src/angelscript/extensions/scriptstdstring/scriptstdstring_utils.cpp b/server/src/angelscript/extensions/scriptstdstring/scriptstdstring_utils.cpp index 9b11243..54662aa 100644 --- a/server/src/angelscript/extensions/scriptstdstring/scriptstdstring_utils.cpp +++ b/server/src/angelscript/extensions/scriptstdstring/scriptstdstring_utils.cpp @@ -112,8 +112,7 @@ static void StringJoin_Generic(asIScriptGeneric *gen) // The string type must have been registered first. void RegisterStdStringUtils(asIScriptEngine *engine) { - [[maybe_unused]] - int r; + int r; if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) { diff --git a/server/src/angelscript/include/angelscript.h b/server/src/angelscript/include/angelscript.h index 9c6c351..4e6602b 100644 --- a/server/src/angelscript/include/angelscript.h +++ b/server/src/angelscript/include/angelscript.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2019 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -58,8 +58,8 @@ BEGIN_AS_NAMESPACE // AngelScript version -#define ANGELSCRIPT_VERSION 23400 -#define ANGELSCRIPT_VERSION_STRING "2.34.0" +#define ANGELSCRIPT_VERSION 23500 +#define ANGELSCRIPT_VERSION_STRING "2.35.0" // Data types @@ -195,6 +195,7 @@ enum asEObjTypeFlags asOBJ_APP_CLASS_A = (asOBJ_APP_CLASS + asOBJ_APP_CLASS_ASSIGNMENT), asOBJ_APP_CLASS_AK = (asOBJ_APP_CLASS + asOBJ_APP_CLASS_ASSIGNMENT + asOBJ_APP_CLASS_COPY_CONSTRUCTOR), asOBJ_APP_CLASS_K = (asOBJ_APP_CLASS + asOBJ_APP_CLASS_COPY_CONSTRUCTOR), + asOBJ_APP_CLASS_MORE_CONSTRUCTORS = (1<<31), asOBJ_APP_PRIMITIVE = (1<<13), asOBJ_APP_FLOAT = (1<<14), asOBJ_APP_ARRAY = (1<<15), @@ -203,7 +204,7 @@ enum asEObjTypeFlags asOBJ_NOCOUNT = (1<<18), asOBJ_APP_CLASS_ALIGN8 = (1<<19), asOBJ_IMPLICIT_HANDLE = (1<<20), - asOBJ_MASK_VALID_FLAGS = 0x1FFFFF, + asOBJ_MASK_VALID_FLAGS = 0x801FFFFF, // Internal flags asOBJ_SCRIPT_OBJECT = (1<<21), asOBJ_SHARED = (1<<22), @@ -385,7 +386,7 @@ typedef unsigned int asUINT; #endif // Is the target a 64bit system? -#if defined(__LP64__) || defined(__amd64__) || defined(__x86_64__) || defined(_M_X64) +#if defined(__LP64__) || defined(__amd64__) || defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) #ifndef AS_64BIT_PTR #define AS_64BIT_PTR #endif @@ -1015,7 +1016,7 @@ public: // Miscellaneous virtual asIScriptEngine *GetEngine() const = 0; - virtual int CopyFrom(asIScriptObject *other) = 0; + virtual int CopyFrom(const asIScriptObject *other) = 0; // User data virtual void *SetUserData(void *data, asPWORD type = 0) = 0; @@ -1238,7 +1239,7 @@ template struct asSMethodPtr { template - static asSFuncPtr Convert(M) + static asSFuncPtr Convert(M Mthd) { // This version of the function should never be executed, nor compiled, // as it would mean that the size of the method pointer cannot be determined. diff --git a/server/src/angelscript/source/as_builder.cpp b/server/src/angelscript/source/as_builder.cpp index a6e90b7..73c66e6 100644 --- a/server/src/angelscript/source/as_builder.cpp +++ b/server/src/angelscript/source/as_builder.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2019 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -386,7 +386,7 @@ int asCBuilder::CompileGlobalVar(const char *sectionName, const char *code, int node = node->firstChild; node->DisconnectParent(); - RegisterGlobalVar(node, script, module->defaultNamespace); + RegisterGlobalVar(node, script, module->m_defaultNamespace); CompileGlobalVariables(); @@ -410,10 +410,10 @@ int asCBuilder::CompileGlobalVar(const char *sectionName, const char *code, int for( asUINT n = 0; n < functions.GetLength(); n++ ) { asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId]; - if( module->globalFunctions.GetIndex(func) >= 0 ) + if( module->m_globalFunctions.GetIndex(func) >= 0 ) { - module->globalFunctions.Erase(module->globalFunctions.GetIndex(func)); - module->scriptFunctions.RemoveValue(func); + module->m_globalFunctions.Erase(module->m_globalFunctions.GetIndex(func)); + module->m_scriptFunctions.RemoveValue(func); func->ReleaseInternal(); } } @@ -552,13 +552,13 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l if( func == 0 ) return asOUT_OF_MEMORY; - GetParsedFunctionDetails(node, scripts[0], 0, func->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, func->defaultArgs, funcTraits, module->defaultNamespace); + GetParsedFunctionDetails(node, scripts[0], 0, func->name, func->returnType, func->parameterNames, func->parameterTypes, func->inOutFlags, func->defaultArgs, funcTraits, module->m_defaultNamespace); func->id = engine->GetNextScriptFunctionId(); func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : ""); int row, col; scripts[0]->ConvertPosToRowCol(node->tokenPos, &row, &col); func->scriptData->declaredAt = (row & 0xFFFFF)|((col & 0xFFF)<<20); - func->nameSpace = module->defaultNamespace; + func->nameSpace = module->m_defaultNamespace; // Make sure the default args are declared correctly int r = ValidateDefaultArgs(script, node, func); @@ -571,14 +571,14 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l // Tell the engine that the function exists already so the compiler can access it if( compileFlags & asCOMP_ADD_TO_MODULE ) { - r = CheckNameConflict(func->name.AddressOf(), node, scripts[0], module->defaultNamespace, false, false); + r = CheckNameConflict(func->name.AddressOf(), node, scripts[0], module->m_defaultNamespace, false, false); if( r < 0 ) { func->ReleaseInternal(); return asERROR; } - module->globalFunctions.Put(func); + module->m_globalFunctions.Put(func); module->AddScriptFunction(func); } @@ -622,10 +622,10 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l for( asUINT n = 0; n < functions.GetLength(); n++ ) { asCScriptFunction *f = engine->scriptFunctions[functions[n]->funcId]; - if( module->globalFunctions.GetIndex(f) >= 0 ) + if( module->m_globalFunctions.GetIndex(f) >= 0 ) { - module->globalFunctions.Erase(module->globalFunctions.GetIndex(f)); - module->scriptFunctions.RemoveValue(f); + module->m_globalFunctions.Erase(module->m_globalFunctions.GetIndex(f)); + module->m_scriptFunctions.RemoveValue(f); f->ReleaseInternal(); } } @@ -1096,7 +1096,7 @@ asCObjectProperty *asCBuilder::GetObjectProperty(asCDataType &obj, const char *p { if( props[n]->name == prop ) { - if( module->accessMask & props[n]->accessMask ) + if( module->m_accessMask & props[n]->accessMask ) return props[n]; else return 0; @@ -1137,7 +1137,7 @@ bool asCBuilder::DoesGlobalPropertyExist(const char *prop, asSNameSpace *ns, asC // Check previously compiled global variables if( module ) { - globProp = module->scriptGlobals.GetFirst(ns, prop); + globProp = module->m_scriptGlobals.GetFirst(ns, prop); if( globProp ) { if( outProp ) *outProp = globProp; @@ -1172,7 +1172,7 @@ asCGlobalProperty *asCBuilder::GetGlobalProperty(const char *prop, asSNameSpace if( isAppProp ) { // Don't return the property if the module doesn't have access to it - if( !(module->accessMask & globProp->accessMask) ) + if( !(module->m_accessMask & globProp->accessMask) ) globProp = 0; } return globProp; @@ -1649,7 +1649,7 @@ int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScri for( n = 0; n < funcDefs.GetLength(); n++ ) { if( funcDefs[n]->name == name && - module->funcDefs[funcDefs[n]->idx]->nameSpace == ns ) + module->m_funcDefs[funcDefs[n]->idx]->nameSpace == ns ) { if( code ) { @@ -1915,7 +1915,7 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef) asCArray defaultArgs; asSFunctionTraits funcTraits; - asCFuncdefType *fdt = module->funcDefs[funcDef->idx]; + asCFuncdefType *fdt = module->m_funcDefs[funcDef->idx]; asASSERT( fdt ); asCScriptFunction *func = fdt->funcdef; @@ -1972,7 +1972,7 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef) { // Replace our funcdef for the existing one funcDef->idx = fdt2->funcdef->id; - module->funcDefs[module->funcDefs.IndexOf(fdt)] = fdt2; + module->ReplaceFuncDef(fdt, fdt2); fdt2->AddRefInternal(); engine->funcDefs.RemoveValue(fdt); @@ -1994,7 +1994,7 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef) // Remember if the type was declared as external so the saved bytecode can be flagged accordingly if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && found) - module->externalTypes.PushLast(engine->scriptFunctions[funcDef->idx]->funcdefType); + module->m_externalTypes.PushLast(engine->scriptFunctions[funcDef->idx]->funcdefType); } int asCBuilder::RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file, asSNameSpace *ns) @@ -2259,7 +2259,7 @@ int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameS // We'll use the existing type decl->isExistingShared = true; decl->typeInfo = st; - module->classTypes.PushLast(st); + module->AddClassType(st); st->AddRefInternal(); break; } @@ -2276,7 +2276,7 @@ int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameS // Remember if the class was declared as external so the saved bytecode can be flagged accordingly if (isExternal) - module->externalTypes.PushLast(st); + module->m_externalTypes.PushLast(st); if (!decl->isExistingShared) { @@ -2310,7 +2310,7 @@ int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameS st->name = name; st->nameSpace = ns; st->module = module; - module->classTypes.PushLast(st); + module->AddClassType(st); if (isShared) { engine->sharedScriptTypes.PushLast(st); @@ -2429,12 +2429,12 @@ int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSN // We'll use the existing type decl->isExistingShared = true; decl->typeInfo = st; - module->classTypes.PushLast(st); + module->AddClassType(st); st->AddRefInternal(); // Remember if the interface was declared as external so the saved bytecode can be flagged accordingly if (isExternal) - module->externalTypes.PushLast(st); + module->m_externalTypes.PushLast(st); return 0; } @@ -2463,7 +2463,7 @@ int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSN st->name = name; st->nameSpace = ns; st->module = module; - module->classTypes.PushLast(st); + module->AddClassType(st); if( isShared ) { engine->sharedScriptTypes.PushLast(st); @@ -2751,8 +2751,8 @@ void asCBuilder::CompileGlobalVariables() // If the length of the arrays are not the same, then this is the compilation // of a single variable, in which case the initialization order of the previous // variables must be preserved. - if( module->scriptGlobals.GetSize() == initOrder.GetSize() ) - module->scriptGlobals.SwapWith(initOrder); + if( module->m_scriptGlobals.GetSize() == initOrder.GetSize() ) + module->m_scriptGlobals.SwapWith(initOrder); } CleanupEnumValues(); @@ -4320,7 +4320,7 @@ int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSp // Remember if the type was declared as external so the saved bytecode can be flagged accordingly if (isExternal && existingSharedType) - module->externalTypes.PushLast(existingSharedType); + module->m_externalTypes.PushLast(existingSharedType); // Check the name and add the enum int r = CheckNameConflict(name.AddressOf(), tmp->firstChild, file, ns, true, false); @@ -4347,7 +4347,7 @@ int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSp st->nameSpace = ns; st->module = module; } - module->enumTypes.PushLast(st); + module->AddEnumType(st); if( !existingSharedType && isShared ) { @@ -4513,7 +4513,7 @@ int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNam st->aliasForType = dataType; st->module = module; - module->typeDefs.PushLast(st); + module->AddTypeDef(st); // Store the location of this declaration for reference in name collisions sClassDeclaration *decl = asNEW(sClassDeclaration); @@ -4968,7 +4968,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, // Remember if the function was declared as external so the saved bytecode can be flagged accordingly if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && func->isExistingShared) - module->externalFunctions.PushLast(engine->scriptFunctions[func->funcId]); + module->m_externalFunctions.PushLast(engine->scriptFunctions[func->funcId]); if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && !func->isExistingShared) { @@ -5099,7 +5099,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, module->AddScriptFunction(f); // TODO: clean up: This should be done by AddScriptFunction() itself - module->globalFunctions.Put(f); + module->m_globalFunctions.Put(f); } else { @@ -5136,7 +5136,9 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file, else { // The copy constructor needs to be marked for easy finding - if (parameterTypes.GetLength() == 1 && parameterTypes[0].GetTypeInfo() == objType) + if( parameterTypes.GetLength() == 1 && + parameterTypes[0].GetTypeInfo() == objType && + (parameterTypes[0].IsReference() || parameterTypes[0].IsObjectHandle()) ) { // Verify that there are not multiple options matching the copy constructor // TODO: Need a better message, since the parameters can be slightly different, e.g. & vs @ @@ -5423,21 +5425,21 @@ void asCBuilder::GetFunctionDescriptions(const char *name, asCArray &funcs, asUINT n; // Get the script declared global functions - const asCArray &idxs = module->globalFunctions.GetIndexes(ns, name); + const asCArray &idxs = module->m_globalFunctions.GetIndexes(ns, name); for( n = 0; n < idxs.GetLength(); n++ ) { - const asCScriptFunction *f = module->globalFunctions.Get(idxs[n]); + const asCScriptFunction *f = module->m_globalFunctions.Get(idxs[n]); asASSERT( f->objectType == 0 ); funcs.PushLast(f->id); } // Add the imported functions // TODO: optimize: Linear search: This is probably not that critial. Also bindInformation will probably be removed in near future - for( n = 0; n < module->bindInformations.GetLength(); n++ ) + for( n = 0; n < module->m_bindInformations.GetLength(); n++ ) { - if( module->bindInformations[n]->importedFunctionSignature->name == name && - module->bindInformations[n]->importedFunctionSignature->nameSpace == ns ) - funcs.PushLast(module->bindInformations[n]->importedFunctionSignature->id); + if( module->m_bindInformations[n]->importedFunctionSignature->name == name && + module->m_bindInformations[n]->importedFunctionSignature->nameSpace == ns ) + funcs.PushLast(module->m_bindInformations[n]->importedFunctionSignature->id); } // Add the registered global functions @@ -5447,7 +5449,7 @@ void asCBuilder::GetFunctionDescriptions(const char *name, asCArray &funcs, asCScriptFunction *f = engine->registeredGlobalFuncs.Get(idxs2[n]); // Verify if the module has access to the function - if( module->accessMask & f->accessMask ) + if( module->m_accessMask & f->accessMask ) { funcs.PushLast(f->id); } @@ -5508,7 +5510,7 @@ void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *ob asCScriptFunction *func = engine->scriptFunctions[objectType->methods[n]]; if( func->name == name && (!objIsConst || func->IsReadOnly()) && - (func->accessMask & module->accessMask) ) + (func->accessMask & module->m_accessMask) ) { // When the scope is defined the returned methods should be the true methods, not the virtual method stubs if( scope == "" ) @@ -5845,7 +5847,7 @@ asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCod isImplicitHandle = true; // Make sure the module has access to the object type - if( !module || (module->accessMask & ti->accessMask) ) + if( !module || (module->m_accessMask & ti->accessMask) ) { if( asOBJ_TYPEDEF == (ti->flags & asOBJ_TYPEDEF) ) { @@ -6266,24 +6268,24 @@ bool asCBuilder::DoesTypeExist(const asCString &type) if (module) { // Add script classes and interfaces - for (n = 0; n < module->classTypes.GetLength(); n++) - if (!knownTypes.MoveTo(0, module->classTypes[n]->name)) - knownTypes.Insert(module->classTypes[n]->name, true); + for (n = 0; n < module->m_classTypes.GetLength(); n++) + if (!knownTypes.MoveTo(0, module->m_classTypes[n]->name)) + knownTypes.Insert(module->m_classTypes[n]->name, true); // Add script enums - for (n = 0; n < module->enumTypes.GetLength(); n++) - if (!knownTypes.MoveTo(0, module->enumTypes[n]->name)) - knownTypes.Insert(module->enumTypes[n]->name, true); + for (n = 0; n < module->m_enumTypes.GetLength(); n++) + if (!knownTypes.MoveTo(0, module->m_enumTypes[n]->name)) + knownTypes.Insert(module->m_enumTypes[n]->name, true); // Add script typedefs - for (n = 0; n < module->typeDefs.GetLength(); n++) - if (!knownTypes.MoveTo(0, module->typeDefs[n]->name)) - knownTypes.Insert(module->typeDefs[n]->name, true); + for (n = 0; n < module->m_typeDefs.GetLength(); n++) + if (!knownTypes.MoveTo(0, module->m_typeDefs[n]->name)) + knownTypes.Insert(module->m_typeDefs[n]->name, true); // Add script funcdefs - for (n = 0; n < module->funcDefs.GetLength(); n++) - if (!knownTypes.MoveTo(0, module->funcDefs[n]->name)) - knownTypes.Insert(module->funcDefs[n]->name, true); + for (n = 0; n < module->m_funcDefs.GetLength(); n++) + if (!knownTypes.MoveTo(0, module->m_funcDefs[n]->name)) + knownTypes.Insert(module->m_funcDefs[n]->name, true); } } @@ -6346,9 +6348,9 @@ asCFuncdefType *asCBuilder::GetFuncDef(const char *type, asSNameSpace *ns, asCOb if (module) { - for (asUINT n = 0; n < module->funcDefs.GetLength(); n++) + for (asUINT n = 0; n < module->m_funcDefs.GetLength(); n++) { - asCFuncdefType *funcDef = module->funcDefs[n]; + asCFuncdefType *funcDef = module->m_funcDefs[n]; if (funcDef && funcDef->nameSpace == ns && funcDef->name == type) return funcDef; } @@ -6405,7 +6407,7 @@ int asCBuilder::GetEnumValue(const char *name, asCDataType &outDt, asDWORD &outV if( ns != et->nameSpace ) continue; // Don't bother with types the module doesn't have access to - if( (et->accessMask & module->accessMask) == 0 ) + if( (et->accessMask & module->m_accessMask) == 0 ) continue; if( GetEnumValueFromType(et, name, outDt, outValue) ) @@ -6420,9 +6422,9 @@ int asCBuilder::GetEnumValue(const char *name, asCDataType &outDt, asDWORD &outV } } - for( t = 0; t < module->enumTypes.GetLength(); t++ ) + for( t = 0; t < module->m_enumTypes.GetLength(); t++ ) { - asCEnumType *et = module->enumTypes[t]; + asCEnumType *et = module->m_enumTypes[t]; if( ns != et->nameSpace ) continue; if( GetEnumValueFromType(et, name, outDt, outValue) ) diff --git a/server/src/angelscript/source/as_callfunc.cpp b/server/src/angelscript/source/as_callfunc.cpp index 9b68174..a365614 100644 --- a/server/src/angelscript/source/as_callfunc.cpp +++ b/server/src/angelscript/source/as_callfunc.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2019 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -135,7 +135,7 @@ int DetectCallingConvention(bool isMethod, const asSFuncPtr &ptr, int callConv, internal->callConv = (internalCallConv)(thisCallConv + 2); #endif internal->baseOffset = ( int )MULTI_BASE_OFFSET(ptr); -#if (defined(AS_ARM) || defined(AS_MIPS)) && (defined(__GNUC__) || defined(AS_PSVITA)) +#if (defined(AS_ARM64) || defined(AS_ARM) || defined(AS_MIPS)) && (defined(__GNUC__) || defined(AS_PSVITA)) // As the least significant bit in func is used to switch to THUMB mode // on ARM processors, the LSB in the __delta variable is used instead of // the one in __pfn on ARM processors. @@ -619,7 +619,7 @@ int CallSystemFunction(int id, asCContext *context) } // Add the base offset for multiple inheritance -#if (defined(__GNUC__) && (defined(AS_ARM) || defined(AS_MIPS))) || defined(AS_PSVITA) +#if (defined(__GNUC__) && (defined(AS_ARM64) || defined(AS_ARM) || defined(AS_MIPS))) || defined(AS_PSVITA) // On GNUC + ARM the lsb of the offset is used to indicate a virtual function // and the whole offset is thus shifted one bit left to keep the original // offset resolution @@ -653,7 +653,7 @@ int CallSystemFunction(int id, asCContext *context) if( obj ) { // Add the base offset for multiple inheritance -#if (defined(__GNUC__) && (defined(AS_ARM) || defined(AS_MIPS))) || defined(AS_PSVITA) +#if (defined(__GNUC__) && (defined(AS_ARM64) || defined(AS_ARM) || defined(AS_MIPS))) || defined(AS_PSVITA) // On GNUC + ARM the lsb of the offset is used to indicate a virtual function // and the whole offset is thus shifted one bit left to keep the original // offset resolution @@ -680,7 +680,7 @@ int CallSystemFunction(int id, asCContext *context) } // Add the base offset for multiple inheritance -#if (defined(__GNUC__) && (defined(AS_ARM) || defined(AS_MIPS))) || defined(AS_PSVITA) +#if (defined(__GNUC__) && (defined(AS_ARM64) || defined(AS_ARM) || defined(AS_MIPS))) || defined(AS_PSVITA) // On GNUC + ARM the lsb of the offset is used to indicate a virtual function // and the whole offset is thus shifted one bit left to keep the original // offset resolution diff --git a/server/src/angelscript/source/as_callfunc.h b/server/src/angelscript/source/as_callfunc.h index 836c0aa..7e96361 100644 --- a/server/src/angelscript/source/as_callfunc.h +++ b/server/src/angelscript/source/as_callfunc.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2017 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -100,7 +100,6 @@ struct asSSystemFunctionInterface asFUNCTION_t func; int baseOffset; internalCallConv callConv; - int scriptReturnSize; bool hostReturnInMemory; bool hostReturnFloat; int hostReturnSize; @@ -120,7 +119,7 @@ struct asSSystemFunctionInterface }; asCArray cleanArgs; - asSSystemFunctionInterface() : func(0), baseOffset(0), callConv(ICC_GENERIC_FUNC), scriptReturnSize(0), hostReturnInMemory(false), hostReturnFloat(false), hostReturnSize(0), paramSize(0), takesObjByVal(false), returnAutoHandle(false), compositeOffset(0), isCompositeIndirect(false), auxiliary(0) {} + asSSystemFunctionInterface() : func(0), baseOffset(0), callConv(ICC_GENERIC_FUNC), hostReturnInMemory(false), hostReturnFloat(false), hostReturnSize(0), paramSize(0), takesObjByVal(false), returnAutoHandle(false), compositeOffset(0), isCompositeIndirect(false), auxiliary(0) {} asSSystemFunctionInterface(const asSSystemFunctionInterface &in) { @@ -132,7 +131,6 @@ struct asSSystemFunctionInterface func = in.func; baseOffset = in.baseOffset; callConv = in.callConv; - scriptReturnSize = in.scriptReturnSize; hostReturnInMemory = in.hostReturnInMemory; hostReturnFloat = in.hostReturnFloat; hostReturnSize = in.hostReturnSize; diff --git a/server/src/angelscript/source/as_callfunc_arm64.cpp b/server/src/angelscript/source/as_callfunc_arm64.cpp new file mode 100644 index 0000000..3e0944d --- /dev/null +++ b/server/src/angelscript/source/as_callfunc_arm64.cpp @@ -0,0 +1,329 @@ +/* + AngelCode Scripting Library + Copyright (c) 2020-2020 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 + andreas@angelcode.com +*/ + + +// +// as_callfunc_arm64.cpp +// +// These functions handle the actual calling of system functions on the arm64 platform +// +// Written by Max Waine in July 2020, based on as_callfunc_arm.cpp +// + + +#include "as_config.h" + +#ifndef AS_MAX_PORTABILITY +#ifdef AS_ARM64 + +#include "as_callfunc.h" +#include "as_scriptengine.h" +#include "as_texts.h" +#include "as_tokendef.h" +#include "as_context.h" + +// ARM64 targets use has no software floating-point ABI, it's all hardware (or totally disabled) + +#define HFA_RET_REGISTERS 4 // s0-s3/d0-d3 +#define GP_ARG_REGISTERS 8 // x0-x7 +#define FLOAT_ARG_REGISTERS 8 // v0-v7 + +BEGIN_AS_NAMESPACE + +// x0-7: Argument registers (pass params or return results. OK as volatile local variables) +// x8: Indirect result register (e.g. address of large returned struct) +// x9-15: Volatile local variable registers +// x16-17: Intra-procedure-call temporary registers +// x18: Platform register (reserved for use of platform ABIs) +// x19-29: Non-volatile variable registers (must be saved and restored if modified) +// x29: Frame pointer register +// x30: Link register (where to return to) + +extern "C" void GetHFAReturnDouble(asQWORD *out1, asQWORD *out2, asQWORD returnSize); +extern "C" void GetHFAReturnFloat(asQWORD *out1, asQWORD *out2, asQWORD returnSize); + +extern "C" asQWORD CallARM64RetInMemory( + const asQWORD *gpRegArgs, asQWORD numGPRegArgs, + const asQWORD *floatRegArgs, asQWORD numFloatRegArgs, + const asQWORD *stackArgs, asQWORD numStackArgs, + void *retPointer, asFUNCTION_t func +); +extern "C" double CallARM64Double( + const asQWORD *gpRegArgs, asQWORD numGPRegArgs, + const asQWORD *floatRegArgs, asQWORD numFloatRegArgs, + const asQWORD *stackArgs, asQWORD numStackArgs, + asFUNCTION_t func +); +extern "C" float CallARM64Float( + const asQWORD *gpRegArgs, asQWORD numGPRegArgs, + const asQWORD *floatRegArgs, asQWORD numFloatRegArgs, + const asQWORD *stackArgs, asQWORD numStackArgs, + asFUNCTION_t func +); +extern "C" asQWORD CallARM64( + const asQWORD *gpRegArgs, asQWORD numGPRegArgs, + const asQWORD *floatRegArgs, asQWORD numFloatRegArgs, + const asQWORD *stackArgs, asQWORD numStackArgs, + asFUNCTION_t func +); +extern "C" asQWORD CallARM64Ret128( + const asQWORD *gpRegArgs, asQWORD numGPRegArgs, + const asQWORD *floatRegArgs, asQWORD numFloatRegArgs, + const asQWORD *stackArgs, asQWORD numStackArgs, + asQWORD *higherQWORD, asFUNCTION_t func +); + +// +// If it's possible to fit in registers, +// there may not be enough float register space even if true is returned +// +static inline bool IsRegisterHFA(const asCDataType &type) +{ + const asCTypeInfo *const typeInfo = type.GetTypeInfo(); + + if( typeInfo == nullptr || + (typeInfo->flags & asOBJ_APP_CLASS_ALLFLOATS) == 0 || + type.IsObjectHandle() && type.IsReference() ) + return false; + + const bool doubles = (typeInfo->flags & asOBJ_APP_CLASS_ALIGN8) != 0; + const int maxAllowedSize = doubles ? sizeof(double) * HFA_RET_REGISTERS : sizeof(float) * HFA_RET_REGISTERS; + + return type.GetSizeInMemoryBytes() <= maxAllowedSize; +} + +// +// If it's possible to fit it in registers, +// if true is returned there is enough space to fit +// +static inline bool IsRegisterHFAParameter(const asCDataType &type, const asQWORD numFloatRegArgs) +{ + if( !IsRegisterHFA(type) ) + return false; + + const bool doubles = (type.GetTypeInfo()->flags & asOBJ_APP_CLASS_ALIGN8) != 0; + const int registersUsed = type.GetSizeInMemoryDWords() / (doubles ? sizeof(double) : sizeof(float)); + + return numFloatRegArgs + registersUsed <= FLOAT_ARG_REGISTERS; +} + +asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &retQW2, void *secondObject) +{ + asCScriptEngine *engine = context->m_engine; + const asSSystemFunctionInterface *const sysFunc = descr->sysFuncIntf; + const asCDataType &retType = descr->returnType; + const asCTypeInfo *const retTypeInfo = retType.GetTypeInfo(); + asFUNCTION_t func = sysFunc->func; + int callConv = sysFunc->callConv; + asQWORD retQW = 0; + + asQWORD gpRegArgs[GP_ARG_REGISTERS]; + asQWORD floatRegArgs[FLOAT_ARG_REGISTERS]; + asQWORD stackArgs[64]; // It's how many x64 users can have + asQWORD numGPRegArgs = 0; + asQWORD numFloatRegArgs = 0; + asQWORD numStackArgs = 0; + + asFUNCTION_t *vftable; + + // Optimization to avoid check 12 values (all ICC_ that contains THISCALL) + if( (callConv >= ICC_THISCALL && callConv <= ICC_VIRTUAL_THISCALL_RETURNINMEM) || + (callConv >= ICC_THISCALL_OBJLAST && callConv <= ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM) ) + { + // Add the object pointer as the first parameter + gpRegArgs[numGPRegArgs++] = (asQWORD)obj; + } + + if( callConv == ICC_CDECL_OBJFIRST || callConv == ICC_CDECL_OBJFIRST_RETURNINMEM ) + { + // Add the object pointer as the first parameter + gpRegArgs[numGPRegArgs++] = (asQWORD)obj; + } + else if( callConv == ICC_THISCALL_OBJFIRST || callConv == ICC_THISCALL_OBJFIRST_RETURNINMEM || + callConv == ICC_VIRTUAL_THISCALL_OBJFIRST || callConv == ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM ) + { + // Add the object pointer as the first parameter + gpRegArgs[numGPRegArgs++] = (asQWORD)secondObject; + } + + if( callConv == ICC_VIRTUAL_THISCALL || callConv == ICC_VIRTUAL_THISCALL_RETURNINMEM || callConv == ICC_VIRTUAL_THISCALL_OBJFIRST || + callConv == ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM || callConv == ICC_VIRTUAL_THISCALL_OBJLAST || callConv == ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM ) + { + // Get virtual function table from the object pointer + vftable = *(asFUNCTION_t**)obj; + func = vftable[FuncPtrToUInt(func)/sizeof(void*)]; + } + + asUINT argsPos = 0; + for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ ) + { + const asCDataType &parmType = descr->parameterTypes[n]; + const asCTypeInfo *const parmTypeInfo = parmType.GetTypeInfo(); + + if( parmType.IsObject() && !parmType.IsObjectHandle() && !parmType.IsReference() ) + { + const asUINT parmDWords = parmType.GetSizeInMemoryDWords(); + const asUINT parmQWords = (parmDWords >> 1) + (parmDWords & 1); + + const bool passedAsPointer = parmQWords <= 2; + const bool fitsInRegisters = passedAsPointer ? (numGPRegArgs < GP_ARG_REGISTERS) : (numGPRegArgs + parmQWords <= GP_ARG_REGISTERS); + asQWORD *const argsArray = fitsInRegisters ? gpRegArgs : stackArgs; + asQWORD &numArgs = fitsInRegisters ? numGPRegArgs : numStackArgs; + + if( (parmTypeInfo->flags & COMPLEX_MASK) ) + { + argsArray[numArgs++] = *(asQWORD*)&args[argsPos]; + argsPos += AS_PTR_SIZE; + } + else if( IsRegisterHFAParameter(parmType, numFloatRegArgs) ) + { + if( (parmTypeInfo->flags & asOBJ_APP_CLASS_ALIGN8) != 0 ) + { + const asQWORD *const contents = *(asQWORD**)&args[argsPos]; + for( asUINT i = 0; i < parmQWords; i++ ) + floatRegArgs[numFloatRegArgs++] = *(asQWORD*)&contents[i]; + } + else + { + const asDWORD *const contents = *(asDWORD**)&args[argsPos]; + for( asUINT i = 0; i < parmDWords; i++ ) + floatRegArgs[numFloatRegArgs++] = *(asQWORD*)&contents[i]; + } + engine->CallFree(*(char**)(args+argsPos)); + argsPos += AS_PTR_SIZE; + } + else + { + // Copy the object's memory to the buffer + memcpy(&argsArray[numArgs], *(void**)(args+argsPos), parmType.GetSizeInMemoryBytes()); + + // Delete the original memory + engine->CallFree(*(char**)(args+argsPos)); + argsPos += AS_PTR_SIZE; + numArgs += parmQWords; + } + } + else if( parmType.IsFloatType() && !parmType.IsReference() ) + { + if( numFloatRegArgs >= FLOAT_ARG_REGISTERS ) + stackArgs[numStackArgs++] = args[argsPos]; + else + floatRegArgs[numFloatRegArgs++] = args[argsPos]; + argsPos++; + } + else if( parmType.IsDoubleType() && !parmType.IsReference() ) + { + if( numFloatRegArgs >= FLOAT_ARG_REGISTERS ) + stackArgs[numStackArgs++] = *(asQWORD*)&args[argsPos]; + else + floatRegArgs[numFloatRegArgs++] = *(asQWORD*)&args[argsPos]; + argsPos += 2; + } + else + { + // Copy the value directly + const asUINT parmDWords = parmType.GetSizeOnStackDWords(); + const asUINT parmQWords = (parmDWords >> 1) + (parmDWords & 1); + + const bool fitsInRegisters = numGPRegArgs + parmQWords <= GP_ARG_REGISTERS; + asQWORD *const argsArray = fitsInRegisters ? gpRegArgs : stackArgs; + asQWORD &numArgs = fitsInRegisters ? numGPRegArgs : numStackArgs; + + memcpy(&argsArray[numArgs], (void*)(args+argsPos), parmDWords * 4); + argsPos += parmDWords; + numArgs += parmQWords; + } + } + + if( callConv == ICC_CDECL_OBJLAST || callConv == ICC_CDECL_OBJLAST_RETURNINMEM ) + { + // Add the object pointer as the last parameter + if( numGPRegArgs < GP_ARG_REGISTERS ) + gpRegArgs[numGPRegArgs++] = (asQWORD)obj; + else + stackArgs[numStackArgs++] = (asQWORD)obj; + } + else if( callConv == ICC_THISCALL_OBJLAST || callConv == ICC_THISCALL_OBJLAST_RETURNINMEM || + callConv == ICC_VIRTUAL_THISCALL_OBJLAST || callConv == ICC_VIRTUAL_THISCALL_OBJLAST_RETURNINMEM ) + { + // Add the object pointer as the last parameter + if( numGPRegArgs < GP_ARG_REGISTERS ) + gpRegArgs[numGPRegArgs++] = (asQWORD)secondObject; + else + stackArgs[numStackArgs++] = (asQWORD)secondObject; + } + + if( IsRegisterHFA(retType) && !(retTypeInfo->flags & COMPLEX_MASK) ) + { + // This is to deal with HFAs (Homogeneous Floating-point Aggregates): + // ARM64 will place all-float composite types (of equal precision) + // with <= 4 members in the float return registers + + const int structSize = retType.GetSizeInMemoryBytes(); + + CallARM64(gpRegArgs, numGPRegArgs, floatRegArgs, numFloatRegArgs, stackArgs, numStackArgs, func); + if( (retTypeInfo->flags & asOBJ_APP_CLASS_ALIGN8) != 0 ) + { + if( structSize <= sizeof(double) * 2 ) + GetHFAReturnDouble(&retQW, &retQW2, structSize); + else + GetHFAReturnDouble((asQWORD*)retPointer, ((asQWORD*)retPointer) + 1, structSize); + } + else + GetHFAReturnFloat(&retQW, &retQW2, structSize); + } + else if( sysFunc->hostReturnFloat ) + { + if( sysFunc->hostReturnSize == 1 ) + *(float*)&retQW = CallARM64Float(gpRegArgs, numGPRegArgs, floatRegArgs, numFloatRegArgs, stackArgs, numStackArgs, func); + else + *(double*)&retQW = CallARM64Double(gpRegArgs, numGPRegArgs, floatRegArgs, numFloatRegArgs, stackArgs, numStackArgs, func); + } + else if( sysFunc->hostReturnInMemory ) + retQW = CallARM64RetInMemory(gpRegArgs, numGPRegArgs, floatRegArgs, numFloatRegArgs, stackArgs, numStackArgs, retPointer, func); + else + { + if( retType.GetSizeInMemoryBytes() > sizeof(asQWORD) ) + retQW = CallARM64Ret128(gpRegArgs, numGPRegArgs, floatRegArgs, numFloatRegArgs, stackArgs, numStackArgs, &retQW2, func); + else + retQW = CallARM64(gpRegArgs, numGPRegArgs, floatRegArgs, numFloatRegArgs, stackArgs, numStackArgs, func); + } + + return retQW; +} + +END_AS_NAMESPACE + +#endif // AS_ARM64 +#endif // AS_MAX_PORTABILITY + + + + diff --git a/server/src/angelscript/source/as_callfunc_arm64_gcc.S b/server/src/angelscript/source/as_callfunc_arm64_gcc.S new file mode 100644 index 0000000..b5d5a5d --- /dev/null +++ b/server/src/angelscript/source/as_callfunc_arm64_gcc.S @@ -0,0 +1,219 @@ +// +// AngelCode Scripting Library +// Copyright (c) 2020-2020 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 +// andreas@angelcode.com +// + + +// Assembly routines for the ARM64/AArch64 call convention used for Linux +// Written by Max Waine in July 2020, based on as_callfunc_arm_msvc.asm, +// with assistance & guidance provided by Sir Kane + +// Compile with GCC/GAS + +.arch armv8-a +.text + +.global GetHFAReturnDouble +.global GetHFAReturnFloat +.global CallARM64Ret128 +.global CallARM64RetInMemory +.global CallARM64Double +.global CallARM64Float +.global CallARM64 + +.type GetHFAReturnDouble, %function +.type GetHFAReturnFloat, %function +.type CallARM64Ret128, %function +.type CallARM64RetInMemory, %function +.type CallARM64Double, %function +.type CallARM64Float, %function +.type CallARM64, %function + +.align 2 +GetHFAReturnDouble: + adr x9, populateDoubles + sub x9, x9, x1, lsr 1 // x9 -= returnSize >> 1; (/2 because double is 2x instruction size) + br x9 + + str d3, [x0, #0x18] + str d2, [x0, #0x10] + str d1, [x1] + str d0, [x0] +populateDoubles: + + ret + +.align 2 +GetHFAReturnFloat: + adr x9, populateFloats + sub x9, x9, x2 // x9 -= returnSize; (already 4 bytes per return) + br x9 + + str s3, [x1, #0x4] + str s2, [x1] + str s1, [x0, #0x4] + str s0, [x0] +populateFloats: + + ret + + +//[returnType] CallARM64[type]( +// const asQWORD *gpRegArgs, asQWORD numGPRegArgs, +// const asQWORD *floatRegArgs, asQWORD numFloatRegArgs, +// const asQWORD *stackArgs, asQWORD numStackArgs, +// asFUNCTION_t func +//) +.align 2 +CallARM64Double: +CallARM64Float: +CallARM64: + .cfi_startproc + stp fp, lr, [sp,#-0x20]! + str x20, [sp,#0x10] + .cfi_def_cfa_offset 0x20 + .cfi_offset 20, 0x10 + .cfi_offset fp, -0x20 + .cfi_offset lr, -0x18 + mov fp, sp + + mov x20, #0 + + cbz x5, stackArgsLoopEnd + + // Align count to 2, then multiply by 8, resulting in a size aligned to 16 + add x20, x5, #1 + lsl x20, x20, #3 + and x20, x20, #-0x10 + // Multiply count by 8 + lsl x10, x5, #3 + sub sp, sp, x20 +stackArgsLoopStart: + ldp x9,x11, [x4],#16 + stp x9,x11, [sp],#16 + subs x10, x10, #16 + bgt stackArgsLoopStart +stackArgsLoopEnd: + + // Calculate amount to jump forward, avoiding pointless instructions + adr x9, populateFloatRegisterArgsEnd + sub x9, x9, x3, lsl 2 // x9 -= numFloatRegArgs * 4 + br x9 + + ldr d7, [x2, #0x38] + ldr d6, [x2, #0x30] + ldr d5, [x2, #0x28] + ldr d4, [x2, #0x20] + ldr d3, [x2, #0x18] + ldr d2, [x2, #0x10] + ldr d1, [x2, #0x08] + ldr d0, [x2] +populateFloatRegisterArgsEnd: + + mov x15, x6 + // Calculate amount to jump forward, avoiding pointless instructions + adr x9, populateGPRegisterArgsEnd + sub x9, x9, x1, lsl 2 // x9 -= numGPRegArgs * 4 + br x9 + + ldr x7, [x0, #0x38] + ldr x6, [x0, #0x30] + ldr x5, [x0, #0x28] + ldr x4, [x0, #0x20] + ldr x3, [x0, #0x18] + ldr x2, [x0, #0x10] + ldr x1, [x0, #0x08] + ldr x0, [x0] +populateGPRegisterArgsEnd: + + // Actually call function + sub sp, sp, x20 + blr x15 + add sp, sp, x20 + + ldr x20, [sp,#0x10] + ldp fp, lr, [sp],#0x20 + + .cfi_restore lr + .cfi_restore fp + .cfi_restore 20 + .cfi_def_cfa_offset 0 + ret + .cfi_endproc + +.align 2 +CallARM64Ret128: + .cfi_startproc + stp fp, lr, [sp,#-0x20]! + str x20, [sp,#0x10] + .cfi_def_cfa_offset 0x20 + .cfi_offset 20, 0x10 + .cfi_offset fp, -0x20 + .cfi_offset lr, -0x18 + mov fp, sp + + mov x20, x6 + mov x6, x7 + mov x7, #0 + bl CallARM64 + + str x1, [x20] + + ldr x20, [sp,#0x10] + ldp fp, lr, [sp],#0x20 + + .cfi_restore lr + .cfi_restore fp + .cfi_restore 20 + .cfi_def_cfa_offset 0 + ret + .cfi_endproc + +.align 2 +CallARM64RetInMemory: + .cfi_startproc + stp fp, lr, [sp,#-0x10]! + mov fp, sp + .cfi_def_cfa_offset 0x10 + .cfi_offset fp, -0x10 + .cfi_offset lr, -0x08 + + mov x8, x6 + mov x6, x7 + mov x7, #0 + bl CallARM64 + + mov x0, x8 + + ldp fp, lr, [sp],#0x10 + + .cfi_restore lr + .cfi_restore fp + .cfi_def_cfa_offset 0 + ret + .cfi_endproc diff --git a/server/src/angelscript/source/as_callfunc_arm64_msvc.asm b/server/src/angelscript/source/as_callfunc_arm64_msvc.asm new file mode 100644 index 0000000..ce43c75 --- /dev/null +++ b/server/src/angelscript/source/as_callfunc_arm64_msvc.asm @@ -0,0 +1,205 @@ +; +; AngelCode Scripting Library +; Copyright (c) 2020-2020 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 +; andreas@angelcode.com +; + + +; Assembly routines for the ARM64/AArch64 call convention used for Windows 10 on ARM +; Written by Max Waine in July 2020, based on as_callfunc_arm_msvc.asm + +; MSVC currently doesn't support inline assembly for the ARM64 platform, +; and if they're treating it like x64 /won't/ ever support inline assembly, +; so this separate file is needed. + +; Compile with Microsoft ARM64 assembler (armasm64) +; http://msdn.microsoft.com/en-us/library/hh873190.aspx + + AREA |.rdata|, DATA, READONLY + EXPORT GetHFAReturnDouble + EXPORT GetHFAReturnFloat + EXPORT CallARM64Ret128 + EXPORT CallARM64RetInMemory + EXPORT CallARM64Double + EXPORT CallARM64Float + EXPORT CallARM64 + + AREA |.text|, CODE, ALIGN=2 + + ALIGN 4 +GetHFAReturnDouble PROC + adr x9, |populateDoubles| + sub x9, x9, x1, lsr 1 ; x9 -= returnSize >> 1; (/2 because double is 2x instruction size) + br x9 + + str d3, [x0, #0x18] + str d2, [x0, #0x10] + str d1, [x1] + str d0, [x0] +|populateDoubles| + + ret + ENDP ; GetHFAReturnDouble + + ALIGN 4 +GetHFAReturnFloat PROC + adr x9, |populateFloats| + sub x9, x9, x2 // x9 -= returnSize; (already 4 bytes per return) + br x9 + + str s3, [x1, #0x4] + str s2, [x1] + str s1, [x0, #0x4] + str s0, [x0] +|populateFloats| + + ret + ENDP ; GetHFAReturnFloat + + +;[returnType] CallARM64[type]( +; const asQWORD *gpRegArgs, asQWORD numGPRegArgs, +; const asQWORD *floatRegArgs, asQWORD numFloatRegArgs, +; const asQWORD *stackArgs, asQWORD numStackArgs, +; asFUNCTION_t func +;) + ALIGN 4 +CallARM64Double PROC + stp fp, lr, [sp,#-0x10]! + bl CallARM64 + ldp fp, lr, [sp,#-0x10]! + ret + ENDP ; CallARM64Double + + ALIGN 4 +CallARM64Float PROC + stp fp, lr, [sp,#-0x10]! + bl CallARM64 + ldp fp, lr, [sp,#-0x10]! + ret + ENDP ; CallARM64Float + + ALIGN 4 +CallARM64 PROC + stp fp, lr, [sp,#-0x20]! + str x20, [sp,#0x10] + + mov x20, #0; + + cbz x5, |stackArgsLoopEnd| + + ; Align count to 2, then multiply by 8, resulting in a size aligned to 16 + add x20, x5, #1 + lsl x20, x20, #3 + and x20, x20, #-0x10 + ; Multiply count by 8 + lsl x10, x5, #3 + sub sp, sp, x20 +|stackArgsLoopStart| + ldp x9,x11, [x4],#16 + stp x9,x11, [sp],#16 + subs x10, x10, #16 + bgt |stackArgsLoopStart| +|stackArgsLoopEnd| + + ; Calculate amount to jump forward, avoiding pointless instructions + adr x9, |populateFloatRegisterArgsEnd| + sub x9, x9, x3, lsl 2 ; x9 -= numFloatRegArgs * 4 + br x9 + + ldr d7, [x2, #0x38] + ldr d6, [x2, #0x30] + ldr d5, [x2, #0x28] + ldr d4, [x2, #0x20] + ldr d3, [x2, #0x18] + ldr d2, [x2, #0x10] + ldr d1, [x2, #0x08] + ldr d0, [x2] +|populateFloatRegisterArgsEnd| + + mov x15, x6 + ; Calculate amount to jump forward, avoiding pointless instructions + adr x9, |populateGPRegisterArgsEnd| + sub x9, x9, x1, lsl 2 ; x9 -= numGPRegArgs * 4 + br x9 + + ldr x7, [x0, #0x38] + ldr x6, [x0, #0x30] + ldr x5, [x0, #0x28] + ldr x4, [x0, #0x20] + ldr x3, [x0, #0x18] + ldr x2, [x0, #0x10] + ldr x1, [x0, #0x08] + ldr x0, [x0] +|populateGPRegisterArgsEnd| + + ; Actually call function + sub sp, sp, x20 + blr x15 + add sp, sp, x20 + + ldr x20, [sp,#0x10] + ldp fp, lr, [sp],#0x20 + + ret + ENDP ; CallARM64 + + ALIGN 4 +CallARM64Ret128 PROC + stp fp, lr, [sp,#-0x20]! + str x20, [sp,#0x10] + mov fp, sp + + mov x20, x6 + mov x6, x7 + mov x7, #0 + bl CallARM64 + + str x1, [x20] + + ldr x20, [sp,#0x10] + ldp fp, lr, [sp],#0x20 + + ret ; CallARM64Ret128 + + ALIGN 4 +CallARM64RetInMemory PROC + stp fp, lr, [sp,#-0x10]! + mov fp, sp + + mov x8, x6 + mov x6, x7 + mov x7, #0 + bl CallARM64 + + mov x0, x8 + + ldp fp, lr, [sp],#0x10 + + ret ; CallARM64RetInMemory + + END diff --git a/server/src/angelscript/source/as_callfunc_arm_gcc.S b/server/src/angelscript/source/as_callfunc_arm_gcc.S index f7a21dc..1dde510 100644 --- a/server/src/angelscript/source/as_callfunc_arm_gcc.S +++ b/server/src/angelscript/source/as_callfunc_arm_gcc.S @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2016 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -43,7 +43,7 @@ #if defined(__arm__) || defined(__ARM__) || defined(I3D_ARCH_ARM) -#if !defined(__linux__) || defined(__ANDROID__) || defined(ANDROID) || defined(__SOFTFP__) +#if !defined(__linux__) || defined(__ANDROID__) || defined(ANDROID) || defined(__SOFTFP__) || defined(__ARM_PCS) /* iOS, Android, Marmalade, and Linux with soft-float ABI goes here */ @@ -287,7 +287,7 @@ nomoreargsarmFuncR0R1: ldmia sp!, {r4-r8, pc} /* --------------------------------------------------------------------------------------------*/ -#elif defined(__linux__) && !defined(__SOFTFP__) +#elif defined(__linux__) && !defined(__SOFTFP__) && !defined(__ARM_PCS) /* The Linux with hard-float ABI code goes here */ diff --git a/server/src/angelscript/source/as_compiler.cpp b/server/src/angelscript/source/as_compiler.cpp index 1f70f91..12700c6 100644 --- a/server/src/angelscript/source/as_compiler.cpp +++ b/server/src/angelscript/source/as_compiler.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2019 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -102,6 +102,10 @@ asCCompiler::~asCCompiler() for (asUINT n = 0; n < usedStringConstants.GetLength(); n++) engine->stringFactory->ReleaseStringConstant(usedStringConstants[n]); usedStringConstants.SetLength(0); + + // Clean up the temporary script nodes that were allocated during compilation + for (asUINT n = 0; n < nodesToFreeUponComplete.GetLength(); n++) + nodesToFreeUponComplete[n]->Destroy(engine); } void asCCompiler::Reset(asCBuilder *in_builder, asCScriptCode *in_script, asCScriptFunction *in_outFunc) @@ -352,7 +356,9 @@ int asCCompiler::SetupParametersAndReturnVariable(asCArray ¶meter // Is the return type allowed? if( returnType != asCDataType::CreatePrimitive(ttVoid, false) && - !returnType.CanBeInstantiated() ) + !returnType.CanBeInstantiated() && + !returnType.IsReference() && + !returnType.IsObjectHandle() ) { // TODO: Hasn't this been validated by the builder already? asCString str; @@ -431,6 +437,7 @@ void asCCompiler::CompileMemberInitialization(asCByteCode *bc, bool onlyDefaults asCObjectProperty *prop = outFunc->objectType->properties[n]; // Check if the property has an initialization expression + asCParser parser(builder); asCScriptNode *declNode = 0; asCScriptNode *initNode = 0; asCScriptCode *initScript = 0; @@ -466,7 +473,6 @@ void asCCompiler::CompileMemberInitialization(asCByteCode *bc, bool onlyDefaults initScript = script; #else // Re-parse the initialization expression as the parser now knows the types, which it didn't earlier - asCParser parser(builder); int r = parser.ParseVarInit(initScript, initNode); if( r < 0 ) continue; @@ -2322,6 +2328,12 @@ int asCCompiler::CompileDefaultAndNamedArgs(asCScriptNode *node, asCArrayexprNode) + { + // Disconnect the node from the parser, and tell the compiler to free it when complete + args[n]->exprNode->DisconnectParent(); + nodesToFreeUponComplete.PushLast(args[n]->exprNode); + } } reservedVariables.SetLength(prevReservedVars); @@ -2655,6 +2667,8 @@ bool asCCompiler::CompileAutoType(asCDataType &type, asCExprContext &compiledCtx // Handle const qualifier on auto if (type.IsReadOnly()) newType.MakeReadOnly(true); + else if (type.IsHandleToConst()) + newType.MakeHandleToConst(true); else if (newType.IsPrimitive()) newType.MakeReadOnly(false); @@ -9253,7 +9267,7 @@ asCCompiler::SYMBOLTYPE asCCompiler::SymbolLookupMember(const asCString &name, a { asCScriptFunction *f = engine->scriptFunctions[ot->methods[n]]; if (f->name == name && - (builder->module->accessMask & f->accessMask)) + (builder->module->m_accessMask & f->accessMask)) { outResult->type.dataType.SetTypeInfo(objType); return SL_CLASSMETHOD; @@ -9835,7 +9849,7 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s { asCScriptFunction *f = engine->scriptFunctions[ot->methods[n]]; if (f->name == name && - (builder->module->accessMask & f->accessMask)) + (builder->module->m_accessMask & f->accessMask)) { func = f; break; @@ -10901,7 +10915,7 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asCExprContext *ctx) // It is possible that the name is really a constructor asCDataType dt; - dt = builder->CreateDataTypeFromNode(node->firstChild, script, outFunc->nameSpace); + dt = builder->CreateDataTypeFromNode(node->firstChild, script, outFunc->nameSpace, false, outFunc->objectType); if( dt.IsPrimitive() ) { // This is a cast to a primitive type @@ -10965,6 +10979,10 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asCExprContext *ctx) conv.Copy(args[0]); asUINT cost = ImplicitConversion(&conv, dt, node->lastChild, asIC_EXPLICIT_VAL_CAST, false); + // Clean the property_arg in the temporary copy so + // it isn't deleted when conv goes out of scope + conv.property_arg = 0; + // Don't use this if the cost is 0 because it would mean that nothing // is done and the script wants a new value to be constructed if( conv.type.dataType.IsEqualExceptRef(dt) && cost > 0 ) @@ -11409,7 +11427,7 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asCExprContext *ctx, a if (symbolType == SL_CLASSTYPE || symbolType == SL_GLOBALTYPE) { bool isValid = false; - asCDataType dt = builder->CreateDataTypeFromNode(node->firstChild, script, outFunc->nameSpace, false, 0, false, &isValid); + asCDataType dt = builder->CreateDataTypeFromNode(node->firstChild, script, outFunc->nameSpace, false, outFunc->objectType, false, &isValid); if (isValid) return CompileConstructCall(node, ctx); } @@ -13601,7 +13619,7 @@ int asCCompiler::CompileOverloadedDualOperator2(asCScriptNode *node, const char (!isConst || func->IsReadOnly()) ) { // Make sure the method is accessible by the module - if( builder->module->accessMask & func->accessMask ) + if( builder->module->m_accessMask & func->accessMask ) { funcs.PushLast(func->id); } diff --git a/server/src/angelscript/source/as_compiler.h b/server/src/angelscript/source/as_compiler.h index dc4c60a..2b5aa33 100644 --- a/server/src/angelscript/source/as_compiler.h +++ b/server/src/angelscript/source/as_compiler.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2019 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -424,6 +424,9 @@ protected: // so they can be released upon completion, whether the compilation was successful or not. asCArray usedStringConstants; + // This array holds the nodes that have been allocated temporarily + asCArray nodesToFreeUponComplete; + bool isCompilingDefaultArg; bool isProcessingDeferredParams; int noCodeOutput; diff --git a/server/src/angelscript/source/as_config.h b/server/src/angelscript/source/as_config.h index e57e8e9..b141b14 100644 --- a/server/src/angelscript/source/as_config.h +++ b/server/src/angelscript/source/as_config.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2019 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -177,6 +177,14 @@ // Oracle Solaris Studio (previously known as Sun CC compiler) // __SUNPRO_CC is defined +// Local (or Little) C Compiler +// __LCC__ is defined +// __e2k__ is not defined + +// MCST eLbrus C Compiler +// __LCC__ is defined +// __e2k__ is defined + // @@ -208,6 +216,9 @@ // AS_ARM // Use assembler code for the ARM CPU family +// AS_ARM64 +// Use assembler code for the ARM64/AArch64 CPU family + // AS_SOFTFP // Use to tell compiler that ARM soft-float ABI // should be used instead of ARM hard-float ABI @@ -227,6 +238,10 @@ // AS_SPARC // Define this for SPARC CPU family +// AS_E2K +// Define this for MCST Elbrus 2000 CPU family + + // @@ -359,6 +374,14 @@ #define AS_NO_THISCALL_FUNCTOR_METHOD +// Emscripten compiler toolchain +// ref: https://emscripten.org/ +#if defined(__EMSCRIPTEN__) + #define AS_MAX_PORTABILITY +#endif + + + // Embarcadero C++Builder #if defined(__BORLANDC__) #ifndef _Windows @@ -482,7 +505,7 @@ #define AS_CALLEE_DESTROY_OBJ_BY_VAL #define AS_LARGE_OBJS_PASSED_BY_REF #define AS_LARGE_OBJ_MIN_SIZE 3 - #define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY) + #define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY | asOBJ_APP_CLASS_MORE_CONSTRUCTORS) #define COMPLEX_MASK (asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY) #endif #endif @@ -502,12 +525,18 @@ #endif #endif + #if defined(_M_ARM64) + #define AS_ARM64 + + // TODO: MORE HERE + #endif + #ifndef COMPLEX_MASK #define COMPLEX_MASK (asOBJ_APP_ARRAY) #endif #ifndef COMPLEX_RETURN_MASK - #define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT | asOBJ_APP_ARRAY) + #define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_CONSTRUCTOR | asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_ASSIGNMENT | asOBJ_APP_ARRAY | asOBJ_APP_CLASS_MORE_CONSTRUCTORS) #endif #define UNREACHABLE_RETURN @@ -864,7 +893,7 @@ #elif defined(__ARMEL__) || defined(__arm__) || defined(__aarch64__) || defined(__AARCH64EL__) // arm - // The assembler code currently doesn't support arm v4, nor 64bit (v8) + // The assembler code currently doesn't support arm v4 #if !defined(__ARM_ARCH_4__) && !defined(__ARM_ARCH_4T__) && !defined(__LP64__) #define AS_ARM @@ -894,13 +923,35 @@ #endif // Verify if soft-float or hard-float ABI is used - #if defined(__SOFTFP__) && __SOFTFP__ == 1 + #if (defined(__SOFTFP__) && __SOFTFP__ == 1) || defined(__ARM_PCS) // -ffloat-abi=softfp or -ffloat-abi=soft #define AS_SOFTFP #endif // Tested with both hard float and soft float abi #undef AS_NO_THISCALL_FUNCTOR_METHOD + #elif defined(__LP64__) || defined(__aarch64__) + #define AS_ARM64 + + #undef STDCALL + #define STDCALL + + #undef GNU_STYLE_VIRTUAL_METHOD + #undef AS_NO_THISCALL_FUNCTOR_METHOD + + #define HAS_128_BIT_PRIMITIVES + + #define CDECL_RETURN_SIMPLE_IN_MEMORY + #define STDCALL_RETURN_SIMPLE_IN_MEMORY + #define THISCALL_RETURN_SIMPLE_IN_MEMORY + + #undef THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE + #undef CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE + #undef STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE + + #define THISCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 5 + #define CDECL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 5 + #define STDCALL_RETURN_SIMPLE_IN_MEMORY_MIN_SIZE 5 #endif #elif defined(__mips__) @@ -932,6 +983,17 @@ // although use 64bit PPC only uses 32bit pointers. // TODO: Add support for native calling conventions on Linux with PPC 64bit #define AS_MAX_PORTABILITY + #elif defined(__e2k__) + // 64bit MCST Elbrus 2000 + // ref: https://en.wikipedia.org/wiki/Elbrus_2000 + #define AS_E2K + // AngelScript currently doesn't support native calling + // for MCST Elbrus 2000 processor so it's necessary to turn on + // portability mode + #define AS_MAX_PORTABILITY + // STDCALL is not available on 64bit Linux + #undef STDCALL + #define STDCALL #else #define AS_MAX_PORTABILITY #endif @@ -1085,25 +1147,28 @@ // Haiku OS #elif __HAIKU__ #define AS_HAIKU - // Only x86-32 is currently supported by Haiku, but they do plan to support - // x86-64 and PowerPC in the future, so should go ahead and check the platform - // for future compatibility #if (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__) #define AS_X86 #define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK #define THISCALL_RETURN_SIMPLE_IN_MEMORY #define CDECL_RETURN_SIMPLE_IN_MEMORY #define STDCALL_RETURN_SIMPLE_IN_MEMORY + #elif defined(__x86_64__) + #define AS_X64_GCC + #define HAS_128_BIT_PRIMITIVES + #define SPLIT_OBJS_BY_MEMBER_TYPES + #undef COMPLEX_MASK + #define COMPLEX_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY) + #undef COMPLEX_RETURN_MASK + #define COMPLEX_RETURN_MASK (asOBJ_APP_CLASS_DESTRUCTOR | asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY) + #define AS_LARGE_OBJS_PASSED_BY_REF + #define AS_LARGE_OBJ_MIN_SIZE 5 + #undef STDCALL + #define STDCALL #else #define AS_MAX_PORTABILITY #endif - #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 - // Illumos #elif defined(__sun) #if (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__) @@ -1193,7 +1258,7 @@ // If there are no current support for native calling // conventions, then compile with AS_MAX_PORTABILITY -#if (!defined(AS_X86) && !defined(AS_SH4) && !defined(AS_MIPS) && !defined(AS_PPC) && !defined(AS_PPC_64) && !defined(AS_XENON) && !defined(AS_X64_GCC) && !defined(AS_X64_MSVC) && !defined(AS_ARM) && !defined(AS_X64_MINGW)) +#if (!defined(AS_X86) && !defined(AS_SH4) && !defined(AS_MIPS) && !defined(AS_PPC) && !defined(AS_PPC_64) && !defined(AS_XENON) && !defined(AS_X64_GCC) && !defined(AS_X64_MSVC) && !defined(AS_ARM) && !defined(AS_ARM64) && !defined(AS_X64_MINGW)) #ifndef AS_MAX_PORTABILITY #define AS_MAX_PORTABILITY #endif diff --git a/server/src/angelscript/source/as_configgroup.cpp b/server/src/angelscript/source/as_configgroup.cpp index d4021d8..3eac7d3 100644 --- a/server/src/angelscript/source/as_configgroup.cpp +++ b/server/src/angelscript/source/as_configgroup.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2017 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -130,7 +130,6 @@ void asCConfigGroup::RemoveConfiguration(asCScriptEngine *engine, bool notUsed) { globalProps[n]->Release(); - // TODO: global: Should compact the registeredGlobalProps array engine->registeredGlobalProps.Erase(index); } } diff --git a/server/src/angelscript/source/as_context.cpp b/server/src/angelscript/source/as_context.cpp index bcb3949..d578c3f 100644 --- a/server/src/angelscript/source/as_context.cpp +++ b/server/src/angelscript/source/as_context.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2019 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -4404,7 +4404,23 @@ void asCContext::ExecuteNext() // Call the method m_callingSystemFunction = m_engine->scriptFunctions[i]; - void *ptr = m_engine->CallObjectMethodRetPtr(obj, arg, m_callingSystemFunction); + void *ptr = 0; +#ifdef AS_NO_EXCEPTIONS + ptr = m_engine->CallObjectMethodRetPtr(obj, arg, m_callingSystemFunction); +#else + // This try/catch block is to catch potential exception that may + // be thrown by the registered function. + try + { + ptr = m_engine->CallObjectMethodRetPtr(obj, arg, m_callingSystemFunction); + } + catch (...) + { + // Convert the exception to a script exception so the VM can + // properly report the error to the application and then clean up + HandleAppException(); + } +#endif m_callingSystemFunction = 0; *(asPWORD*)&m_regs.valueRegister = (asPWORD)ptr; } @@ -4816,8 +4832,9 @@ void asCContext::DetermineLiveObjects(asCArray &liveObjects, asUINT stackLe } } break; - case asOBJ_VARDECL: - break; + case asOBJ_VARDECL: // A variable was declared + // We don't really care about the variable declarations at this moment + break; } } diff --git a/server/src/angelscript/source/as_memory.cpp b/server/src/angelscript/source/as_memory.cpp index bd46f37..13b8732 100644 --- a/server/src/angelscript/source/as_memory.cpp +++ b/server/src/angelscript/source/as_memory.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2016 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -38,7 +38,7 @@ #include -#if !defined(__APPLE__) && !defined(__SNC__) && !defined(__ghs__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) +#if !defined(__APPLE__) && !defined(__SNC__) && !defined(__ghs__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) #include #endif @@ -241,6 +241,11 @@ void asCMemoryMgr::FreeScriptNode(void *ptr) scriptNodePool.Allocate(100, 0); scriptNodePool.PushLast(ptr); + +#ifdef AS_DEBUG + // clear the memory to facilitate identification of use after free + memset(ptr, 0xCDCDCDCD, sizeof(asCScriptNode)); +#endif LEAVECRITICALSECTION(cs); } @@ -249,6 +254,8 @@ void asCMemoryMgr::FreeScriptNode(void *ptr) void *asCMemoryMgr::AllocByteInstruction() { + // This doesn't need a critical section because, only one compilation is allowed at a time + if( byteInstructionPool.GetLength() ) return byteInstructionPool.PopLast(); @@ -266,6 +273,11 @@ void asCMemoryMgr::FreeByteInstruction(void *ptr) byteInstructionPool.Allocate(100, 0); byteInstructionPool.PushLast(ptr); + +#ifdef AS_DEBUG + // clear the memory to facilitate identification of use after free + memset(ptr, 0xCDCDCDCD, sizeof(asCByteInstruction)); +#endif } #endif // AS_NO_COMPILER diff --git a/server/src/angelscript/source/as_module.cpp b/server/src/angelscript/source/as_module.cpp index 177edf7..f13bf2e 100644 --- a/server/src/angelscript/source/as_module.cpp +++ b/server/src/angelscript/source/as_module.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2019 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -50,16 +50,16 @@ BEGIN_AS_NAMESPACE // internal asCModule::asCModule(const char *name, asCScriptEngine *engine) { - this->name = name; - this->engine = engine; + m_name = name; + m_engine = engine; - userData = 0; - builder = 0; - isGlobalVarInitialized = false; + m_userData = 0; + m_builder = 0; + m_isGlobalVarInitialized = false; - accessMask = 1; + m_accessMask = 1; - defaultNamespace = engine->nameSpaces[0]; + m_defaultNamespace = engine->nameSpaces[0]; } // internal @@ -69,31 +69,31 @@ asCModule::~asCModule() // The builder is not removed by InternalReset because it holds the script // sections that will be built, so we need to explictly remove it now if it exists - if( builder ) + if( m_builder ) { - asDELETE(builder,asCBuilder); - builder = 0; + asDELETE(m_builder,asCBuilder); + m_builder = 0; } - if( engine ) + if( m_engine ) { // Clean the user data - for( asUINT n = 0; n < userData.GetLength(); n += 2 ) + for( asUINT n = 0; n < m_userData.GetLength(); n += 2 ) { - if( userData[n+1] ) + if( m_userData[n+1] ) { - for( asUINT c = 0; c < engine->cleanModuleFuncs.GetLength(); c++ ) - if( engine->cleanModuleFuncs[c].type == userData[n] ) - engine->cleanModuleFuncs[c].cleanFunc(this); + for( asUINT c = 0; c < m_engine->cleanModuleFuncs.GetLength(); c++ ) + if( m_engine->cleanModuleFuncs[c].type == m_userData[n] ) + m_engine->cleanModuleFuncs[c].cleanFunc(this); } } // Remove the module from the engine - ACQUIREEXCLUSIVE(engine->engineRWLock); + ACQUIREEXCLUSIVE(m_engine->engineRWLock); // The module must have been discarded before it is deleted - asASSERT( !engine->scriptModules.Exists(this) ); - engine->discardedModules.RemoveValue(this); - RELEASEEXCLUSIVE(engine->engineRWLock); + asASSERT( !m_engine->scriptModules.Exists(this) ); + m_engine->discardedModules.RemoveValue(this); + RELEASEEXCLUSIVE(m_engine->engineRWLock); } } @@ -108,29 +108,29 @@ void asCModule::Discard() // Keep a local copy of the engine pointer, because once the module is moved do the discarded // pile, it is possible that another thread might discard it while we are still in here. So no // further access to members may be done after that - asCScriptEngine *lEngine = engine; + asCScriptEngine *engine = m_engine; // Instead of deleting the module immediately, move it to the discarded pile // This will turn it invisible to the application, yet keep it alive until all // external references to its entities have been released. ACQUIREEXCLUSIVE(engine->engineRWLock); - if( lEngine->lastModule == this ) - lEngine->lastModule = 0; - lEngine->scriptModules.RemoveValue(this); - lEngine->discardedModules.PushLast(this); - RELEASEEXCLUSIVE(lEngine->engineRWLock); + if( engine->lastModule == this ) + engine->lastModule = 0; + engine->scriptModules.RemoveValue(this); + engine->discardedModules.PushLast(this); + RELEASEEXCLUSIVE(engine->engineRWLock); // Allow the engine to go over the list of discarded modules to see what can be cleaned up at this moment. // Don't do this if the engine is already shutting down, as it will be done explicitly by the engine itself with error reporting - if( !lEngine->shuttingDown ) + if( !engine->shuttingDown ) { - if( lEngine->ep.autoGarbageCollect ) - lEngine->GarbageCollect(); + if( engine->ep.autoGarbageCollect ) + engine->GarbageCollect(); else { // GarbageCollect calls DeleteDiscardedModules, so no need // to call it again if we already called GarbageCollect - lEngine->DeleteDiscardedModules(); + engine->DeleteDiscardedModules(); } } } @@ -140,28 +140,28 @@ void *asCModule::SetUserData(void *data, asPWORD type) { // As a thread might add a new new user data at the same time as another // it is necessary to protect both read and write access to the userData member - ACQUIREEXCLUSIVE(engine->engineRWLock); + ACQUIREEXCLUSIVE(m_engine->engineRWLock); // It is not intended to store a lot of different types of userdata, // so a more complex structure like a associative map would just have // more overhead than a simple array. - for( asUINT n = 0; n < userData.GetLength(); n += 2 ) + for( asUINT n = 0; n < m_userData.GetLength(); n += 2 ) { - if( userData[n] == type ) + if( m_userData[n] == type ) { - void *oldData = reinterpret_cast(userData[n+1]); - userData[n+1] = reinterpret_cast(data); + void *oldData = reinterpret_cast(m_userData[n+1]); + m_userData[n+1] = reinterpret_cast(data); - RELEASEEXCLUSIVE(engine->engineRWLock); + RELEASEEXCLUSIVE(m_engine->engineRWLock); return oldData; } } - userData.PushLast(type); - userData.PushLast(reinterpret_cast(data)); + m_userData.PushLast(type); + m_userData.PushLast(reinterpret_cast(data)); - RELEASEEXCLUSIVE(engine->engineRWLock); + RELEASEEXCLUSIVE(m_engine->engineRWLock); return 0; } @@ -171,19 +171,19 @@ void *asCModule::GetUserData(asPWORD type) const { // There may be multiple threads reading, but when // setting the user data nobody must be reading. - ACQUIRESHARED(engine->engineRWLock); + ACQUIRESHARED(m_engine->engineRWLock); - for( asUINT n = 0; n < userData.GetLength(); n += 2 ) + for( asUINT n = 0; n < m_userData.GetLength(); n += 2 ) { - if( userData[n] == type ) + if( m_userData[n] == type ) { - void *ud = reinterpret_cast(userData[n+1]); - RELEASESHARED(engine->engineRWLock); + void *ud = reinterpret_cast(m_userData[n+1]); + RELEASESHARED(m_engine->engineRWLock); return ud; } } - RELEASESHARED(engine->engineRWLock); + RELEASESHARED(m_engine->engineRWLock); return 0; } @@ -191,25 +191,25 @@ void *asCModule::GetUserData(asPWORD type) const // interface asIScriptEngine *asCModule::GetEngine() const { - return engine; + return m_engine; } // interface void asCModule::SetName(const char *in_name) { - name = in_name; + m_name = in_name; } // interface const char *asCModule::GetName() const { - return name.AddressOf(); + return m_name.AddressOf(); } // interface const char *asCModule::GetDefaultNamespace() const { - return defaultNamespace->name.AddressOf(); + return m_defaultNamespace->name.AddressOf(); } // interface @@ -230,7 +230,7 @@ int asCModule::SetDefaultNamespace(const char *nameSpace) for( ; pos < ns.GetLength(); pos += len ) { - t = engine->tok.GetToken(ns.AddressOf() + pos, ns.GetLength() - pos, &len); + t = m_engine->tok.GetToken(ns.AddressOf() + pos, ns.GetLength() - pos, &len); if( (expectIdentifier && t != ttIdentifier) || (!expectIdentifier && t != ttScope) ) return asINVALID_DECLARATION; @@ -242,7 +242,7 @@ int asCModule::SetDefaultNamespace(const char *nameSpace) ns.SetLength(ns.GetLength()-2); } - defaultNamespace = engine->AddNameSpace(ns.AddressOf()); + m_defaultNamespace = m_engine->AddNameSpace(ns.AddressOf()); return 0; } @@ -257,26 +257,26 @@ int asCModule::AddScriptSection(const char *in_name, const char *in_code, size_t UNUSED_VAR(in_lineOffset); return asNOT_SUPPORTED; #else - if( !builder ) + if( !m_builder ) { - builder = asNEW(asCBuilder)(engine, this); - if( builder == 0 ) + m_builder = asNEW(asCBuilder)(m_engine, this); + if( m_builder == 0 ) return asOUT_OF_MEMORY; } - return builder->AddCode(in_name, in_code, (int)in_codeLength, in_lineOffset, (int)engine->GetScriptSectionNameIndex(in_name ? in_name : ""), engine->ep.copyScriptSections); + return m_builder->AddCode(in_name, in_code, (int)in_codeLength, in_lineOffset, (int)m_engine->GetScriptSectionNameIndex(in_name ? in_name : ""), m_engine->ep.copyScriptSections); #endif } // internal void asCModule::JITCompile() { - asIJITCompiler *jit = engine->GetJITCompiler(); + asIJITCompiler *jit = m_engine->GetJITCompiler(); if( !jit ) return; - for (unsigned int i = 0; i < scriptFunctions.GetLength(); i++) - scriptFunctions[i]->JITCompile(); + for (unsigned int i = 0; i < m_scriptFunctions.GetLength(); i++) + m_scriptFunctions[i]->JITCompile(); } // interface @@ -292,64 +292,64 @@ int asCModule::Build() // TODO: interface: The asIScriptModule must have a method for querying if the module is used if( HasExternalReferences(false) ) { - engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_MODULE_IS_IN_USE); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_MODULE_IS_IN_USE); return asMODULE_IS_IN_USE; } // Only one thread may build at one time // TODO: It should be possible to have multiple threads perform compilations - int r = engine->RequestBuild(); + int r = m_engine->RequestBuild(); if( r < 0 ) return r; - engine->PrepareEngine(); - if( engine->configFailed ) + m_engine->PrepareEngine(); + if( m_engine->configFailed ) { - engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION); - engine->BuildCompleted(); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION); + m_engine->BuildCompleted(); return asINVALID_CONFIGURATION; } InternalReset(); - if( !builder ) + if( !m_builder ) { - engine->BuildCompleted(); + m_engine->BuildCompleted(); return asSUCCESS; } // Compile the script - r = builder->Build(); - asDELETE(builder,asCBuilder); - builder = 0; + r = m_builder->Build(); + asDELETE(m_builder,asCBuilder); + m_builder = 0; if( r < 0 ) { // Reset module again InternalReset(); - engine->BuildCompleted(); + m_engine->BuildCompleted(); return r; } JITCompile(); - engine->PrepareEngine(); + m_engine->PrepareEngine(); #ifdef AS_DEBUG // Verify that there are no unwanted gaps in the scriptFunctions array. - for( asUINT n = 1; n < engine->scriptFunctions.GetLength(); n++ ) + for( asUINT n = 1; n < m_engine->scriptFunctions.GetLength(); n++ ) { int id = n; - if( engine->scriptFunctions[n] == 0 && !engine->freeScriptFunctionIds.Exists(id) ) + if( m_engine->scriptFunctions[n] == 0 && !m_engine->freeScriptFunctionIds.Exists(id) ) asASSERT( false ); } #endif - engine->BuildCompleted(); + m_engine->BuildCompleted(); // Initialize global variables - if( r >= 0 && engine->ep.initGlobalVarsAfterBuild ) + if( r >= 0 && m_engine->ep.initGlobalVarsAfterBuild ) r = ResetGlobalVars(0); return r; @@ -359,7 +359,7 @@ int asCModule::Build() // interface int asCModule::ResetGlobalVars(asIScriptContext *ctx) { - if( isGlobalVarInitialized ) + if( m_isGlobalVarInitialized ) CallExit(); return CallInit(ctx); @@ -368,17 +368,17 @@ int asCModule::ResetGlobalVars(asIScriptContext *ctx) // interface asIScriptFunction *asCModule::GetFunctionByIndex(asUINT index) const { - return const_cast(globalFunctions.Get(index)); + return const_cast(m_globalFunctions.Get(index)); } // internal int asCModule::CallInit(asIScriptContext *myCtx) { - if( isGlobalVarInitialized ) + if( m_isGlobalVarInitialized ) return asERROR; // Each global variable needs to be cleared individually - asCSymbolTableIterator it = scriptGlobals.List(); + asCSymbolTableIterator it = m_scriptGlobals.List(); while( it ) { asCGlobalProperty *desc = *it; @@ -389,7 +389,7 @@ int asCModule::CallInit(asIScriptContext *myCtx) // Call the init function for each of the global variables asIScriptContext *ctx = myCtx; int r = asEXECUTION_FINISHED; - it = scriptGlobals.List(); + it = m_scriptGlobals.List(); while( it && r == asEXECUTION_FINISHED ) { asCGlobalProperty *desc = *it; @@ -398,47 +398,18 @@ int asCModule::CallInit(asIScriptContext *myCtx) { if( ctx == 0 ) { - ctx = engine->RequestContext(); + ctx = m_engine->RequestContext(); if( ctx == 0 ) break; } - r = ctx->Prepare(desc->GetInitFunc()); - if( r >= 0 ) - { - r = ctx->Execute(); - if( r != asEXECUTION_FINISHED ) - { - asCString msg; - msg.Format(TXT_FAILED_TO_INITIALIZE_s, desc->name.AddressOf()); - asCScriptFunction *func = desc->GetInitFunc(); - - engine->WriteMessage(func->scriptData->scriptSectionIdx >= 0 ? engine->scriptSectionNames[func->scriptData->scriptSectionIdx]->AddressOf() : "", - func->GetLineNumber(0, 0) & 0xFFFFF, - func->GetLineNumber(0, 0) >> 20, - asMSGTYPE_ERROR, - msg.AddressOf()); - - if( r == asEXECUTION_EXCEPTION ) - { - const asIScriptFunction *function = ctx->GetExceptionFunction(); - - msg.Format(TXT_EXCEPTION_s_IN_s, ctx->GetExceptionString(), function->GetDeclaration()); - - engine->WriteMessage(function->GetScriptSectionName(), - ctx->GetExceptionLineNumber(), - 0, - asMSGTYPE_INFORMATION, - msg.AddressOf()); - } - } - } + r = InitGlobalProp(desc, ctx); } } if( ctx && !myCtx ) { - engine->ReturnContext(ctx); + m_engine->ReturnContext(ctx); ctx = 0; } @@ -446,7 +417,73 @@ int asCModule::CallInit(asIScriptContext *myCtx) // flag that the variables have been initialized, otherwise // the module won't free those variables that really were // initialized. - isGlobalVarInitialized = true; + m_isGlobalVarInitialized = true; + + if( r != asEXECUTION_FINISHED ) + return asINIT_GLOBAL_VARS_FAILED; + + return asSUCCESS; +} + +// internal +// This function assumes the memory for the global property is already cleared +int asCModule::InitGlobalProp(asCGlobalProperty *prop, asIScriptContext *myCtx) +{ + // Call the init function for each of the global variables + asIScriptContext *ctx = myCtx; + int r = asEXECUTION_FINISHED; + if( prop->GetInitFunc() ) + { + if( ctx == 0 ) + { + ctx = m_engine->RequestContext(); + if( ctx == 0 ) + return asERROR; + } + + r = ctx->Prepare(prop->GetInitFunc()); + if( r >= 0 ) + { + r = ctx->Execute(); + if( r != asEXECUTION_FINISHED ) + { + asCString msg; + msg.Format(TXT_FAILED_TO_INITIALIZE_s, prop->name.AddressOf()); + asCScriptFunction *func = prop->GetInitFunc(); + + m_engine->WriteMessage(func->scriptData->scriptSectionIdx >= 0 ? m_engine->scriptSectionNames[func->scriptData->scriptSectionIdx]->AddressOf() : "", + func->GetLineNumber(0, 0) & 0xFFFFF, + func->GetLineNumber(0, 0) >> 20, + asMSGTYPE_ERROR, + msg.AddressOf()); + + if( r == asEXECUTION_EXCEPTION ) + { + const asIScriptFunction *function = ctx->GetExceptionFunction(); + + msg.Format(TXT_EXCEPTION_s_IN_s, ctx->GetExceptionString(), function->GetDeclaration()); + + m_engine->WriteMessage(function->GetScriptSectionName(), + ctx->GetExceptionLineNumber(), + 0, + asMSGTYPE_INFORMATION, + msg.AddressOf()); + } + } + } + } + + if( ctx && !myCtx ) + { + m_engine->ReturnContext(ctx); + ctx = 0; + } + + // Even if the initialization failed we need to set the + // flag that the variables have been initialized, otherwise + // the module won't free those variables that really were + // initialized. + m_isGlobalVarInitialized = true; if( r != asEXECUTION_FINISHED ) return asINIT_GLOBAL_VARS_FAILED; @@ -471,14 +508,14 @@ void asCModule::UninitializeGlobalProp(asCGlobalProperty *prop) { asASSERT((ot->flags & asOBJ_NOCOUNT) || ot->beh.release); if (ot->beh.release) - engine->CallObjectMethod(*obj, ot->beh.release); + m_engine->CallObjectMethod(*obj, ot->beh.release); } else { if (ot->beh.destruct) - engine->CallObjectMethod(*obj, ot->beh.destruct); + m_engine->CallObjectMethod(*obj, ot->beh.destruct); - engine->CallFree(*obj); + m_engine->CallFree(*obj); } // Set the address to 0 as someone might try to access the variable afterwards @@ -499,16 +536,16 @@ void asCModule::UninitializeGlobalProp(asCGlobalProperty *prop) // internal void asCModule::CallExit() { - if( !isGlobalVarInitialized ) return; + if( !m_isGlobalVarInitialized ) return; - asCSymbolTableIterator it = scriptGlobals.List(); + asCSymbolTableIterator it = m_scriptGlobals.List(); while( it ) { UninitializeGlobalProp(*it); it++; } - isGlobalVarInitialized = false; + m_isGlobalVarInitialized = false; } // internal @@ -517,7 +554,7 @@ bool asCModule::HasExternalReferences(bool shuttingDown) // Check all entities in the module for any external references. // If there are any external references the module cannot be deleted yet. - asCSymbolTableIterator it = scriptGlobals.List(); + asCSymbolTableIterator it = m_scriptGlobals.List(); while (it) { asCGlobalProperty *desc = *it; @@ -528,25 +565,25 @@ bool asCModule::HasExternalReferences(bool shuttingDown) else { asCString msg; - msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf()); - engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf()); + msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, m_name.AddressOf()); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf()); // TODO: Use a better error message asCString tmpName = "init " + desc->name; msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, tmpName.AddressOf(), desc->GetInitFunc()->GetFuncType()); - engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf()); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf()); } } it++; } - for (asUINT n = 0; n < scriptFunctions.GetLength(); n++) + for (asUINT n = 0; n < m_scriptFunctions.GetLength(); n++) { - asCScriptFunction *func = scriptFunctions[n]; + asCScriptFunction *func = m_scriptFunctions[n]; if (func && func->externalRefCount.get()) { // If the func is shared and can be moved to another module then this is not a reason to keep the module alive - if (func->IsShared() && engine->FindNewOwnerForSharedFunc(func, this) != this) + if (func->IsShared() && m_engine->FindNewOwnerForSharedFunc(func, this) != this) continue; if (!shuttingDown) @@ -554,22 +591,22 @@ bool asCModule::HasExternalReferences(bool shuttingDown) else { asCString msg; - msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf()); - engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf()); + msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, m_name.AddressOf()); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf()); - msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, scriptFunctions[n]->GetName(), scriptFunctions[n]->GetFuncType()); - engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf()); + msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, m_scriptFunctions[n]->GetName(), m_scriptFunctions[n]->GetFuncType()); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf()); } } } - for (asUINT n = 0; n < classTypes.GetLength(); n++) + for (asUINT n = 0; n < m_classTypes.GetLength(); n++) { - asCObjectType *obj = classTypes[n]; + asCObjectType *obj = m_classTypes[n]; if (obj && obj->externalRefCount.get()) { // If the obj is shared and can be moved to another module then this is not a reason to keep the module alive - if (obj->IsShared() && engine->FindNewOwnerForSharedType(obj, this) != this) + if (obj->IsShared() && m_engine->FindNewOwnerForSharedType(obj, this) != this) continue; if (!shuttingDown) @@ -577,22 +614,22 @@ bool asCModule::HasExternalReferences(bool shuttingDown) else { asCString msg; - msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf()); - engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf()); + msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, m_name.AddressOf()); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf()); - msg.Format(TXT_PREV_TYPE_IS_NAMED_s, classTypes[n]->GetName()); - engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf()); + msg.Format(TXT_PREV_TYPE_IS_NAMED_s, m_classTypes[n]->GetName()); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf()); } } } - for (asUINT n = 0; n < funcDefs.GetLength(); n++) + for (asUINT n = 0; n < m_funcDefs.GetLength(); n++) { - asCFuncdefType *func = funcDefs[n]; + asCFuncdefType *func = m_funcDefs[n]; if (func && func->externalRefCount.get()) { // If the funcdef is shared and can be moved to another module then this is not a reason to keep the module alive - if (func->IsShared() && engine->FindNewOwnerForSharedType(func, this) != this) + if (func->IsShared() && m_engine->FindNewOwnerForSharedType(func, this) != this) continue; if (!shuttingDown) @@ -600,22 +637,22 @@ bool asCModule::HasExternalReferences(bool shuttingDown) else { asCString msg; - msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf()); - engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf()); + msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, m_name.AddressOf()); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf()); - msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, funcDefs[n]->GetName(), funcDefs[n]->funcdef->GetFuncType()); - engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf()); + msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, m_funcDefs[n]->GetName(), m_funcDefs[n]->funcdef->GetFuncType()); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf()); } } } - for (asUINT n = 0; n < templateInstances.GetLength(); n++) + for (asUINT n = 0; n < m_templateInstances.GetLength(); n++) { - asCObjectType *obj = templateInstances[n]; + asCObjectType *obj = m_templateInstances[n]; if (obj && obj->externalRefCount.get()) { // If the template can be moved to another module then this is not a reason to keep the module alive - if (obj->IsShared() && engine->FindNewOwnerForSharedType(obj, this) != this) + if (obj->IsShared() && m_engine->FindNewOwnerForSharedType(obj, this) != this) continue; if (!shuttingDown) @@ -623,11 +660,11 @@ bool asCModule::HasExternalReferences(bool shuttingDown) else { asCString msg; - msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, name.AddressOf()); - engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf()); + msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, m_name.AddressOf()); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf()); - msg.Format(TXT_PREV_TYPE_IS_NAMED_s, templateInstances[n]->GetName()); - engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf()); + msg.Format(TXT_PREV_TYPE_IS_NAMED_s, m_templateInstances[n]->GetName()); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf()); } } } @@ -643,12 +680,12 @@ void asCModule::InternalReset() asUINT n; // Remove all global functions - globalFunctions.Clear(); + m_globalFunctions.Clear(); // Destroy the internals of the global properties here, but do not yet remove them from the // engine, because functions need the engine's varAddressMap to get to the property. If the // property is removed already, it may leak as the refCount doesn't reach 0. - asCSymbolTableIterator globIt = scriptGlobals.List(); + asCSymbolTableIterator globIt = m_scriptGlobals.List(); while( globIt ) { (*globIt)->DestroyInternal(); @@ -658,22 +695,22 @@ void asCModule::InternalReset() UnbindAllImportedFunctions(); // Free bind information - for( n = 0; n < bindInformations.GetLength(); n++ ) + for( n = 0; n < m_bindInformations.GetLength(); n++ ) { - if( bindInformations[n] ) + if( m_bindInformations[n] ) { - bindInformations[n]->importedFunctionSignature->ReleaseInternal(); + m_bindInformations[n]->importedFunctionSignature->ReleaseInternal(); - asDELETE(bindInformations[n], sBindInfo); + asDELETE(m_bindInformations[n], sBindInfo); } } - bindInformations.SetLength(0); + m_bindInformations.SetLength(0); // Free declared types, including classes, typedefs, and enums - for( n = 0; n < templateInstances.GetLength(); n++ ) + for( n = 0; n < m_templateInstances.GetLength(); n++ ) { - asCObjectType *type = templateInstances[n]; - if( engine->FindNewOwnerForSharedType(type, this) != this ) + asCObjectType *type = m_templateInstances[n]; + if( m_engine->FindNewOwnerForSharedType(type, this) != this ) { // The type is owned by another module, just release our reference type->ReleaseInternal(); @@ -684,17 +721,17 @@ void asCModule::InternalReset() type->module = 0; // No other module is holding the template type - engine->RemoveTemplateInstanceType(type); + m_engine->RemoveTemplateInstanceType(type); type->ReleaseInternal(); } - templateInstances.SetLength(0); - for( n = 0; n < classTypes.GetLength(); n++ ) + m_templateInstances.SetLength(0); + for( n = 0; n < m_classTypes.GetLength(); n++ ) { - asCObjectType *type = classTypes[n]; + asCObjectType *type = m_classTypes[n]; if( type->IsShared() ) { // The type is shared, so transfer ownership to another module that also uses it - if( engine->FindNewOwnerForSharedType(type, this) != this ) + if( m_engine->FindNewOwnerForSharedType(type, this) != this ) { // The type is owned by another module, just release our reference type->ReleaseInternal(); @@ -708,7 +745,7 @@ void asCModule::InternalReset() // Remove the type from the engine if( type->IsShared() ) { - engine->sharedScriptTypes.RemoveValue(type); + m_engine->sharedScriptTypes.RemoveValue(type); type->ReleaseInternal(); } @@ -716,14 +753,14 @@ void asCModule::InternalReset() type->module = 0; type->ReleaseInternal(); } - classTypes.SetLength(0); - for( n = 0; n < enumTypes.GetLength(); n++ ) + m_classTypes.SetLength(0); + for( n = 0; n < m_enumTypes.GetLength(); n++ ) { - asCEnumType *type = enumTypes[n]; + asCEnumType *type = m_enumTypes[n]; if( type->IsShared() ) { // The type is shared, so transfer ownership to another module that also uses it - if( engine->FindNewOwnerForSharedType(type, this) != this ) + if( m_engine->FindNewOwnerForSharedType(type, this) != this ) { // The type is owned by another module, just release our reference type->ReleaseInternal(); @@ -734,7 +771,7 @@ void asCModule::InternalReset() // Remove the type from the engine if( type->IsShared() ) { - engine->sharedScriptTypes.RemoveValue(type); + m_engine->sharedScriptTypes.RemoveValue(type); type->ReleaseInternal(); } @@ -742,10 +779,10 @@ void asCModule::InternalReset() type->module = 0; type->ReleaseInternal(); } - enumTypes.SetLength(0); - for( n = 0; n < typeDefs.GetLength(); n++ ) + m_enumTypes.SetLength(0); + for( n = 0; n < m_typeDefs.GetLength(); n++ ) { - asCTypedefType *type = typeDefs[n]; + asCTypedefType *type = m_typeDefs[n]; // The type should be destroyed now type->DestroyInternal(); @@ -754,17 +791,17 @@ void asCModule::InternalReset() type->module = 0; type->ReleaseInternal(); } - typeDefs.SetLength(0); + m_typeDefs.SetLength(0); // Free funcdefs - for( n = 0; n < funcDefs.GetLength(); n++ ) + for( n = 0; n < m_funcDefs.GetLength(); n++ ) { - asCFuncdefType *func = funcDefs[n]; + asCFuncdefType *func = m_funcDefs[n]; asASSERT(func); if( func->funcdef && func->funcdef->IsShared() ) { // The funcdef is shared, so transfer ownership to another module that also uses it - if( engine->FindNewOwnerForSharedType(func, this) != this ) + if( m_engine->FindNewOwnerForSharedType(func, this) != this ) { // The funcdef is owned by another module, just release our reference func->ReleaseInternal(); @@ -773,20 +810,20 @@ void asCModule::InternalReset() } func->DestroyInternal(); - engine->RemoveFuncdef(func); + m_engine->RemoveFuncdef(func); func->module = 0; func->ReleaseInternal(); } - funcDefs.SetLength(0); + m_funcDefs.SetLength(0); // Then release the functions - for( n = 0; n < scriptFunctions.GetLength(); n++ ) + for( n = 0; n < m_scriptFunctions.GetLength(); n++ ) { - asCScriptFunction *func = scriptFunctions[n]; + asCScriptFunction *func = m_scriptFunctions[n]; if( func->IsShared() ) { // The func is shared, so transfer ownership to another module that also uses it - if( engine->FindNewOwnerForSharedFunc(func, this) != this ) + if( m_engine->FindNewOwnerForSharedFunc(func, this) != this ) { // The func is owned by another module, just release our reference func->ReleaseInternal(); @@ -798,18 +835,22 @@ void asCModule::InternalReset() func->module = 0; func->ReleaseInternal(); } - scriptFunctions.SetLength(0); + m_scriptFunctions.SetLength(0); // Now remove and release the global properties as there are no more references to them - globIt = scriptGlobals.List(); + globIt = m_scriptGlobals.List(); while( globIt ) { - engine->RemoveGlobalProperty(*globIt); + m_engine->RemoveGlobalProperty(*globIt); asASSERT( (*globIt)->refCount.get() == 1 ); (*globIt)->Release(); globIt++; } - scriptGlobals.Clear(); + m_scriptGlobals.Clear(); + + // Clear the type lookup + // The references were already released as the types were removed from the respective arrays + m_typeLookup.EraseAll(); asASSERT( IsEmpty() ); } @@ -817,19 +858,24 @@ void asCModule::InternalReset() // interface asIScriptFunction *asCModule::GetFunctionByName(const char *in_name) const { - asSNameSpace *ns = defaultNamespace; + asCString name; + asSNameSpace *ns = 0; + if( m_engine->DetermineNameAndNamespace(in_name, m_defaultNamespace, name, ns) < 0 ) + return 0; + + // Search recursively in the given namespace, moving up to parent namespace until the function is found while( ns ) { - const asCArray &idxs = globalFunctions.GetIndexes(ns, in_name); + const asCArray &idxs = m_globalFunctions.GetIndexes(ns, name); if( idxs.GetLength() != 1 ) return 0; - const asIScriptFunction *func = globalFunctions.Get(idxs[0]); + const asIScriptFunction *func = m_globalFunctions.Get(idxs[0]); if( func ) return const_cast(func); // Recursively search parent namespaces - ns = engine->GetParentNameSpace(ns); + ns = m_engine->GetParentNameSpace(ns); } return 0; @@ -838,33 +884,33 @@ asIScriptFunction *asCModule::GetFunctionByName(const char *in_name) const // interface asUINT asCModule::GetImportedFunctionCount() const { - return (asUINT)bindInformations.GetLength(); + return (asUINT)m_bindInformations.GetLength(); } // interface int asCModule::GetImportedFunctionIndexByDecl(const char *decl) const { - asCBuilder bld(engine, const_cast(this)); + asCBuilder bld(m_engine, const_cast(this)); // Don't write parser errors to the message callback bld.silent = true; - asCScriptFunction func(engine, const_cast(this), asFUNC_DUMMY); - bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace); + asCScriptFunction func(m_engine, const_cast(this), asFUNC_DUMMY); + bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, m_defaultNamespace); // TODO: optimize: Improve linear search // Search script functions for matching interface int id = -1; - for( asUINT n = 0; n < bindInformations.GetLength(); ++n ) + for( asUINT n = 0; n < m_bindInformations.GetLength(); ++n ) { - if( func.name == bindInformations[n]->importedFunctionSignature->name && - func.returnType == bindInformations[n]->importedFunctionSignature->returnType && - func.parameterTypes.GetLength() == bindInformations[n]->importedFunctionSignature->parameterTypes.GetLength() ) + if( func.name == m_bindInformations[n]->importedFunctionSignature->name && + func.returnType == m_bindInformations[n]->importedFunctionSignature->returnType && + func.parameterTypes.GetLength() == m_bindInformations[n]->importedFunctionSignature->parameterTypes.GetLength() ) { bool match = true; for( asUINT p = 0; p < func.parameterTypes.GetLength(); ++p ) { - if( func.parameterTypes[p] != bindInformations[n]->importedFunctionSignature->parameterTypes[p] ) + if( func.parameterTypes[p] != m_bindInformations[n]->importedFunctionSignature->parameterTypes[p] ) { match = false; break; @@ -889,19 +935,19 @@ int asCModule::GetImportedFunctionIndexByDecl(const char *decl) const // interface asUINT asCModule::GetFunctionCount() const { - return (asUINT)globalFunctions.GetSize(); + return (asUINT)m_globalFunctions.GetSize(); } // interface asIScriptFunction *asCModule::GetFunctionByDecl(const char *decl) const { - asCBuilder bld(engine, const_cast(this)); + asCBuilder bld(m_engine, const_cast(this)); // Don't write parser errors to the message callback bld.silent = true; - asCScriptFunction func(engine, const_cast(this), asFUNC_DUMMY); - int r = bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, defaultNamespace); + asCScriptFunction func(m_engine, const_cast(this), asFUNC_DUMMY); + int r = bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, m_defaultNamespace); if( r < 0 ) { // Invalid declaration @@ -910,16 +956,16 @@ asIScriptFunction *asCModule::GetFunctionByDecl(const char *decl) const } // Use the defaultNamespace implicitly unless an explicit namespace has been provided - asSNameSpace *ns = func.nameSpace == engine->nameSpaces[0] ? defaultNamespace : func.nameSpace; + asSNameSpace *ns = func.nameSpace == m_engine->nameSpaces[0] ? m_defaultNamespace : func.nameSpace; // Search script functions for matching interface while( ns ) { asIScriptFunction *f = 0; - const asCArray &idxs = globalFunctions.GetIndexes(ns, func.name); + const asCArray &idxs = m_globalFunctions.GetIndexes(ns, func.name); for( unsigned int n = 0; n < idxs.GetLength(); n++ ) { - const asCScriptFunction *funcPtr = globalFunctions.Get(idxs[n]); + const asCScriptFunction *funcPtr = m_globalFunctions.Get(idxs[n]); if( funcPtr->objectType == 0 && func.returnType == funcPtr->returnType && func.parameterTypes.GetLength() == funcPtr->parameterTypes.GetLength() @@ -951,7 +997,7 @@ asIScriptFunction *asCModule::GetFunctionByDecl(const char *decl) const else { // Search for matching functions in the parent namespace - ns = engine->GetParentNameSpace(ns); + ns = m_engine->GetParentNameSpace(ns); } } @@ -961,22 +1007,25 @@ asIScriptFunction *asCModule::GetFunctionByDecl(const char *decl) const // interface asUINT asCModule::GetGlobalVarCount() const { - return (asUINT)scriptGlobals.GetSize(); + return (asUINT)m_scriptGlobals.GetSize(); } // interface int asCModule::GetGlobalVarIndexByName(const char *in_name) const { - asSNameSpace *ns = defaultNamespace; - + asCString name; + asSNameSpace *ns = 0; + if( m_engine->DetermineNameAndNamespace(in_name, m_defaultNamespace, name, ns) < 0 ) + return asINVALID_ARG; + // Find the global var id while( ns ) { - int id = scriptGlobals.GetFirstIndex(ns, in_name); + int id = m_scriptGlobals.GetFirstIndex(ns, name); if( id >= 0 ) return id; // Recursively search parent namespaces - ns = engine->GetParentNameSpace(ns); + ns = m_engine->GetParentNameSpace(ns); } return asNO_GLOBAL_VAR; @@ -985,13 +1034,13 @@ int asCModule::GetGlobalVarIndexByName(const char *in_name) const // interface int asCModule::RemoveGlobalVar(asUINT index) { - asCGlobalProperty *prop = scriptGlobals.Get(index); + asCGlobalProperty *prop = m_scriptGlobals.Get(index); if( !prop ) return asINVALID_ARG; // If the global variables have already been initialized // then uninitialize the variable before it is removed - if (isGlobalVarInitialized) + if (m_isGlobalVarInitialized) UninitializeGlobalProp(prop); // Destroy the internal of the global variable (removes the initialization function) @@ -1000,10 +1049,10 @@ int asCModule::RemoveGlobalVar(asUINT index) // Check if the module is the only one referring to the property, if so remove it from the engine too // If the property is not removed now, it will be removed later when the module is discarded if( prop->refCount.get() == 2 ) - engine->RemoveGlobalProperty(prop); + m_engine->RemoveGlobalProperty(prop); // Remove the global variable from the module - scriptGlobals.Erase(index); + m_scriptGlobals.Erase(index); prop->Release(); return 0; @@ -1012,7 +1061,7 @@ int asCModule::RemoveGlobalVar(asUINT index) // interface int asCModule::GetGlobalVarIndexByDecl(const char *decl) const { - asCBuilder bld(engine, const_cast(this)); + asCBuilder bld(m_engine, const_cast(this)); // Don't write parser errors to the message callback bld.silent = true; @@ -1020,19 +1069,19 @@ int asCModule::GetGlobalVarIndexByDecl(const char *decl) const asCString declName; asSNameSpace *nameSpace; asCDataType dt; - int r = bld.ParseVariableDeclaration(decl, defaultNamespace, declName, nameSpace, dt); + int r = bld.ParseVariableDeclaration(decl, m_defaultNamespace, declName, nameSpace, dt); if( r < 0 ) return r; // Search global variables for a match while( nameSpace ) { - int id = scriptGlobals.GetFirstIndex(nameSpace, declName, asCCompGlobPropType(dt)); + int id = m_scriptGlobals.GetFirstIndex(nameSpace, declName, asCCompGlobPropType(dt)); if( id != -1 ) return id; // Recursively search parent namespace - nameSpace = engine->GetParentNameSpace(nameSpace); + nameSpace = m_engine->GetParentNameSpace(nameSpace); } return asNO_GLOBAL_VAR; @@ -1041,7 +1090,7 @@ int asCModule::GetGlobalVarIndexByDecl(const char *decl) const // interface void *asCModule::GetAddressOfGlobalVar(asUINT index) { - asCGlobalProperty *prop = scriptGlobals.Get(index); + asCGlobalProperty *prop = m_scriptGlobals.Get(index); if( !prop ) return 0; @@ -1056,11 +1105,11 @@ void *asCModule::GetAddressOfGlobalVar(asUINT index) // interface const char *asCModule::GetGlobalVarDeclaration(asUINT index, bool includeNamespace) const { - const asCGlobalProperty *prop = scriptGlobals.Get(index); + const asCGlobalProperty *prop = m_scriptGlobals.Get(index); if (!prop) return 0; asCString *tempString = &asCThreadManager::GetLocalData()->string; - *tempString = prop->type.Format(defaultNamespace); + *tempString = prop->type.Format(m_defaultNamespace); *tempString += " "; if( includeNamespace && prop->nameSpace->name != "" ) *tempString += prop->nameSpace->name + "::"; @@ -1072,15 +1121,15 @@ const char *asCModule::GetGlobalVarDeclaration(asUINT index, bool includeNamespa // interface int asCModule::GetGlobalVar(asUINT index, const char **out_name, const char **out_nameSpace, int *out_typeId, bool *out_isConst) const { - const asCGlobalProperty *prop = scriptGlobals.Get(index); - if (!prop) return 0; + const asCGlobalProperty *prop = m_scriptGlobals.Get(index); + if (!prop) return asINVALID_ARG; if( out_name ) *out_name = prop->name.AddressOf(); if( out_nameSpace ) *out_nameSpace = prop->nameSpace->name.AddressOf(); if( out_typeId ) - *out_typeId = engine->GetTypeIdFromDataType(prop->type); + *out_typeId = m_engine->GetTypeIdFromDataType(prop->type); if( out_isConst ) *out_isConst = prop->type.IsReadOnly(); @@ -1090,50 +1139,36 @@ int asCModule::GetGlobalVar(asUINT index, const char **out_name, const char **ou // interface asUINT asCModule::GetObjectTypeCount() const { - return (asUINT)classTypes.GetLength(); + return (asUINT)m_classTypes.GetLength(); } // interface asITypeInfo *asCModule::GetObjectTypeByIndex(asUINT index) const { - if( index >= classTypes.GetLength() ) + if( index >= m_classTypes.GetLength() ) return 0; - return classTypes[index]; + return m_classTypes[index]; } // interface asITypeInfo *asCModule::GetTypeInfoByName(const char *in_name) const { - asSNameSpace *ns = defaultNamespace; + asCString name; + asSNameSpace *ns = 0; + if( m_engine->DetermineNameAndNamespace(in_name, m_defaultNamespace, name, ns) < 0 ) + return 0; + while (ns) { - for (asUINT n = 0; n < classTypes.GetLength(); n++) + asITypeInfo* info = GetType(name, ns); + if(info) { - if (classTypes[n] && - classTypes[n]->name == in_name && - classTypes[n]->nameSpace == ns) - return classTypes[n]; - } - - for (asUINT n = 0; n < enumTypes.GetLength(); n++) - { - if (enumTypes[n] && - enumTypes[n]->name == in_name && - enumTypes[n]->nameSpace == ns) - return enumTypes[n]; - } - - for (asUINT n = 0; n < typeDefs.GetLength(); n++) - { - if (typeDefs[n] && - typeDefs[n]->name == in_name && - typeDefs[n]->nameSpace == ns) - return typeDefs[n]; + return info; } // Recursively search parent namespace - ns = engine->GetParentNameSpace(ns); + ns = m_engine->GetParentNameSpace(ns); } return 0; @@ -1145,16 +1180,16 @@ int asCModule::GetTypeIdByDecl(const char *decl) const asCDataType dt; // This const cast is safe since we know the engine won't be modified - asCBuilder bld(engine, const_cast(this)); + asCBuilder bld(m_engine, const_cast(this)); // Don't write parser errors to the message callback bld.silent = true; - int r = bld.ParseDataType(decl, &dt, defaultNamespace); + int r = bld.ParseDataType(decl, &dt, m_defaultNamespace); if( r < 0 ) return asINVALID_TYPE; - return engine->GetTypeIdFromDataType(dt); + return m_engine->GetTypeIdFromDataType(dt); } // interface @@ -1163,12 +1198,12 @@ asITypeInfo *asCModule::GetTypeInfoByDecl(const char *decl) const asCDataType dt; // This const cast is safe since we know the engine won't be modified - asCBuilder bld(engine, const_cast(this)); + asCBuilder bld(m_engine, const_cast(this)); // Don't write parser errors to the message callback bld.silent = true; - int r = bld.ParseDataType(decl, &dt, defaultNamespace); + int r = bld.ParseDataType(decl, &dt, m_defaultNamespace); if (r < 0) return 0; @@ -1178,41 +1213,41 @@ asITypeInfo *asCModule::GetTypeInfoByDecl(const char *decl) const // interface asUINT asCModule::GetEnumCount() const { - return enumTypes.GetLength(); + return m_enumTypes.GetLength(); } // interface asITypeInfo *asCModule::GetEnumByIndex(asUINT index) const { - if( index >= enumTypes.GetLength() ) + if( index >= m_enumTypes.GetLength() ) return 0; - return enumTypes[index]; + return m_enumTypes[index]; } // interface asUINT asCModule::GetTypedefCount() const { - return (asUINT)typeDefs.GetLength(); + return (asUINT)m_typeDefs.GetLength(); } // interface asITypeInfo *asCModule::GetTypedefByIndex(asUINT index) const { - if( index >= typeDefs.GetLength() ) + if( index >= m_typeDefs.GetLength() ) return 0; - return typeDefs[index]; + return m_typeDefs[index]; } // 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]; + if( m_engine->freeImportedFunctionIdxs.GetLength() ) + return FUNC_IMPORTED | (asUINT)m_engine->freeImportedFunctionIdxs[m_engine->freeImportedFunctionIdxs.GetLength()-1]; - return FUNC_IMPORTED | (asUINT)engine->importedFunctions.GetLength(); + return FUNC_IMPORTED | (asUINT)m_engine->importedFunctions.GetLength(); } #ifndef AS_NO_COMPILER @@ -1222,7 +1257,7 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a asASSERT(id >= 0); // Store the function information - asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, isInterface ? asFUNC_INTERFACE : asFUNC_SCRIPT); + asCScriptFunction *func = asNEW(asCScriptFunction)(m_engine, this, isInterface ? asFUNC_INTERFACE : asFUNC_SCRIPT); if( func == 0 ) { // Free the default args @@ -1234,7 +1269,7 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a } if( ns == 0 ) - ns = engine->nameSpaces[0]; + ns = m_engine->nameSpaces[0]; // All methods of shared objects are also shared if( objType && objType->IsShared() ) @@ -1265,8 +1300,8 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a asASSERT( !(!objType && funcTraits.GetTrait(asTRAIT_OVERRIDE)) ); // The internal ref count was already set by the constructor - scriptFunctions.PushLast(func); - engine->AddScriptFunction(func); + m_scriptFunctions.PushLast(func); + m_engine->AddScriptFunction(func); // Compute the signature id if( objType ) @@ -1274,7 +1309,7 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a // Add reference if( isGlobalFunction ) - globalFunctions.Put(func); + m_globalFunctions.Put(func); return 0; } @@ -1282,9 +1317,9 @@ int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const a // internal int asCModule::AddScriptFunction(asCScriptFunction *func) { - scriptFunctions.PushLast(func); + m_scriptFunctions.PushLast(func); func->AddRefInternal(); - engine->AddScriptFunction(func); + m_engine->AddScriptFunction(func); // If the function that is being added is an already compiled shared function // then it is necessary to look for anonymous functions that may be declared @@ -1306,7 +1341,7 @@ int asCModule::AddScriptFunction(asCScriptFunction *func) if( f && f->name[0] == '$' ) { AddScriptFunction(f); - globalFunctions.Put(f); + m_globalFunctions.Put(f); } } n += asBCTypeSize[asBCInfo[c].type]; @@ -1322,7 +1357,7 @@ int asCModule::AddImportedFunction(int id, const asCString &funcName, const asCD asASSERT(id >= 0); // Store the function information - asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, asFUNC_IMPORTED); + asCScriptFunction *func = asNEW(asCScriptFunction)(m_engine, this, asFUNC_IMPORTED); if( func == 0 ) { // Free the default args @@ -1353,13 +1388,13 @@ int asCModule::AddImportedFunction(int id, const asCString &funcName, const asCD info->importedFunctionSignature = func; info->boundFunctionId = -1; info->importFromModule = moduleName; - bindInformations.PushLast(info); + m_bindInformations.PushLast(info); // Add the info to the array in the engine - if( engine->freeImportedFunctionIdxs.GetLength() ) - engine->importedFunctions[engine->freeImportedFunctionIdxs.PopLast()] = info; + if( m_engine->freeImportedFunctionIdxs.GetLength() ) + m_engine->importedFunctions[m_engine->freeImportedFunctionIdxs.PopLast()] = info; else - engine->importedFunctions.PushLast(info); + m_engine->importedFunctions.PushLast(info); return 0; } @@ -1368,7 +1403,7 @@ int asCModule::AddImportedFunction(int id, const asCString &funcName, const asCD // internal asCScriptFunction *asCModule::GetImportedFunction(int index) const { - return bindInformations[index]->importedFunctionSignature; + return m_bindInformations[index]->importedFunctionSignature; } // interface @@ -1385,7 +1420,7 @@ int asCModule::BindImportedFunction(asUINT index, asIScriptFunction *func) if( func == 0 ) return asINVALID_ARG; - asCScriptFunction *src = engine->GetScriptFunction(func->GetId()); + asCScriptFunction *src = m_engine->GetScriptFunction(func->GetId()); if( src == 0 ) return asNO_FUNCTION; @@ -1402,7 +1437,7 @@ int asCModule::BindImportedFunction(asUINT index, asIScriptFunction *func) return asINVALID_INTERFACE; } - bindInformations[index]->boundFunctionId = src->GetId(); + m_bindInformations[index]->boundFunctionId = src->GetId(); src->AddRefInternal(); return asSUCCESS; @@ -1411,17 +1446,17 @@ int asCModule::BindImportedFunction(asUINT index, asIScriptFunction *func) // interface int asCModule::UnbindImportedFunction(asUINT index) { - if( index >= bindInformations.GetLength() ) + if( index >= m_bindInformations.GetLength() ) return asINVALID_ARG; // Remove reference to old module - if( bindInformations[index] ) + if( m_bindInformations[index] ) { - int oldFuncID = bindInformations[index]->boundFunctionId; + int oldFuncID = m_bindInformations[index]->boundFunctionId; if( oldFuncID != -1 ) { - bindInformations[index]->boundFunctionId = -1; - engine->scriptFunctions[oldFuncID]->ReleaseInternal(); + m_bindInformations[index]->boundFunctionId = -1; + m_engine->scriptFunctions[oldFuncID]->ReleaseInternal(); } } @@ -1443,10 +1478,10 @@ const char *asCModule::GetImportedFunctionDeclaration(asUINT index) const // interface const char *asCModule::GetImportedFunctionSourceModule(asUINT index) const { - if( index >= bindInformations.GetLength() ) + if( index >= m_bindInformations.GetLength() ) return 0; - return bindInformations[index]->importFromModule.AddressOf(); + return m_bindInformations[index]->importFromModule.AddressOf(); } // inteface @@ -1467,7 +1502,7 @@ int asCModule::BindAllImportedFunctions() const char *moduleName = GetImportedFunctionSourceModule(n); if( moduleName == 0 ) return asERROR; - asCModule *srcMod = engine->GetModule(moduleName, false); + asCModule *srcMod = m_engine->GetModule(moduleName, false); asIScriptFunction *func = 0; if( srcMod ) func = srcMod->GetFunctionByDecl(str.AddressOf()); @@ -1498,52 +1533,78 @@ int asCModule::UnbindAllImportedFunctions() } // internal -asCTypeInfo *asCModule::GetType(const char *type, asSNameSpace *ns) +void asCModule::AddClassType(asCObjectType* type) { - asUINT n; + m_classTypes.PushLast(type); + m_typeLookup.Insert({type->nameSpace, type->name}, type); +} - // TODO: optimize: Improve linear search - for (n = 0; n < classTypes.GetLength(); n++) - if (classTypes[n]->name == type && - classTypes[n]->nameSpace == ns) - return classTypes[n]; +// internal +void asCModule::AddEnumType(asCEnumType* type) +{ + m_enumTypes.PushLast(type); + m_typeLookup.Insert({type->nameSpace, type->name}, type); +} - for (n = 0; n < enumTypes.GetLength(); n++) - if (enumTypes[n]->name == type && - enumTypes[n]->nameSpace == ns) - return enumTypes[n]; +// internal +void asCModule::AddTypeDef(asCTypedefType* type) +{ + m_typeDefs.PushLast(type); + m_typeLookup.Insert({type->nameSpace, type->name}, type); +} - for (n = 0; n < typeDefs.GetLength(); n++) - if (typeDefs[n]->name == type && - typeDefs[n]->nameSpace == ns) - return typeDefs[n]; +// internal +void asCModule::AddFuncDef(asCFuncdefType* type) +{ + m_funcDefs.PushLast(type); + m_typeLookup.Insert({type->nameSpace, type->name}, type); +} - for (n = 0; n < funcDefs.GetLength(); n++) - if (funcDefs[n]->name == type && - funcDefs[n]->nameSpace == ns) - return funcDefs[n]; +// internal +void asCModule::ReplaceFuncDef(asCFuncdefType* type, asCFuncdefType* newType) +{ + int i = m_funcDefs.IndexOf(type); + if( i >= 0 ) + { + m_funcDefs[i] = newType; + + // Replace it in the lookup map too + asSMapNode* result = nullptr; + if(m_typeLookup.MoveTo(&result, {type->nameSpace, type->name})) + { + asASSERT( result->value == type ); + result->value = newType; + } + } +} +// internal +asCTypeInfo *asCModule::GetType(const asCString &type, asSNameSpace *ns) const +{ + asSMapNode* result = nullptr; + if(m_typeLookup.MoveTo(&result, {ns, type})) + { + return result->value; + } return 0; } // internal -asCObjectType *asCModule::GetObjectType(const char *type, asSNameSpace *ns) +asCObjectType *asCModule::GetObjectType(const char *type, asSNameSpace *ns) const { - asUINT n; - - // TODO: optimize: Improve linear search - for( n = 0; n < classTypes.GetLength(); n++ ) - if( classTypes[n]->name == type && - classTypes[n]->nameSpace == ns ) - return classTypes[n]; - + asSMapNode* result = nullptr; + if(m_typeLookup.MoveTo(&result, {ns, type})) + { + return CastToObjectType(result->value); + } + return 0; } // internal asCGlobalProperty *asCModule::AllocateGlobalProperty(const char *propName, const asCDataType &dt, asSNameSpace *ns) { - asCGlobalProperty *prop = engine->AllocateGlobalProperty(); + asCGlobalProperty *prop = m_engine->AllocateGlobalProperty(); prop->name = propName; prop->nameSpace = ns; @@ -1552,10 +1613,10 @@ asCGlobalProperty *asCModule::AllocateGlobalProperty(const char *propName, const prop->AllocateMemory(); // Make an entry in the address to variable map - engine->varAddressMap.Insert(prop->GetAddressOfValue(), prop); + m_engine->varAddressMap.Insert(prop->GetAddressOfValue(), prop); // Store the variable in the module scope - scriptGlobals.Put(prop); + m_scriptGlobals.Put(prop); prop->AddRef(); return prop; @@ -1564,14 +1625,14 @@ asCGlobalProperty *asCModule::AllocateGlobalProperty(const char *propName, const // internal bool asCModule::IsEmpty() const { - if( scriptFunctions.GetLength() ) return false; - if( globalFunctions.GetSize() ) return false; - if( bindInformations.GetLength() ) return false; - if( scriptGlobals.GetSize() ) return false; - if( classTypes.GetLength() ) return false; - if( enumTypes.GetLength() ) return false; - if( typeDefs.GetLength() ) return false; - if( funcDefs.GetLength() ) return false; + if( m_scriptFunctions.GetLength() ) return false; + if( m_globalFunctions.GetSize() ) return false; + if( m_bindInformations.GetLength() ) return false; + if( m_scriptGlobals.GetSize() ) return false; + if( m_classTypes.GetLength() ) return false; + if( m_enumTypes.GetLength() ) return false; + if( m_typeDefs.GetLength() ) return false; + if( m_funcDefs.GetLength() ) return false; return true; } @@ -1590,7 +1651,7 @@ int asCModule::SaveByteCode(asIBinaryStream *out, bool stripDebugInfo) const if( IsEmpty() ) return asERROR; - asCWriter write(const_cast(this), out, engine, stripDebugInfo); + asCWriter write(const_cast(this), out, m_engine, stripDebugInfo); return write.Write(); #endif } @@ -1604,21 +1665,21 @@ int asCModule::LoadByteCode(asIBinaryStream *in, bool *wasDebugInfoStripped) // external references that will need the previous code if( HasExternalReferences(false) ) { - engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_MODULE_IS_IN_USE); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_MODULE_IS_IN_USE); return asMODULE_IS_IN_USE; } // Only permit loading bytecode if no other thread is currently compiling // TODO: It should be possible to have multiple threads perform compilations - int r = engine->RequestBuild(); + int r = m_engine->RequestBuild(); if( r < 0 ) return r; - asCReader read(this, in, engine); + asCReader read(this, in, m_engine); r = read.Read(wasDebugInfoStripped); if (r < 0) { - engine->BuildCompleted(); + m_engine->BuildCompleted(); return r; } @@ -1626,15 +1687,15 @@ int asCModule::LoadByteCode(asIBinaryStream *in, bool *wasDebugInfoStripped) #ifdef AS_DEBUG // Verify that there are no unwanted gaps in the scriptFunctions array. - for( asUINT n = 1; n < engine->scriptFunctions.GetLength(); n++ ) + for( asUINT n = 1; n < m_engine->scriptFunctions.GetLength(); n++ ) { int id = n; - if( engine->scriptFunctions[n] == 0 && !engine->freeScriptFunctionIds.Exists(id) ) + if( m_engine->scriptFunctions[n] == 0 && !m_engine->freeScriptFunctionIds.Exists(id) ) asASSERT( false ); } #endif - engine->BuildCompleted(); + m_engine->BuildCompleted(); return r; } @@ -1654,49 +1715,42 @@ int asCModule::CompileGlobalVar(const char *sectionName, const char *code, int l // Only one thread may build at one time // TODO: It should be possible to have multiple threads perform compilations - int r = engine->RequestBuild(); + int r = m_engine->RequestBuild(); if( r < 0 ) return r; // Prepare the engine - engine->PrepareEngine(); - if( engine->configFailed ) + m_engine->PrepareEngine(); + if( m_engine->configFailed ) { - engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION); - engine->BuildCompleted(); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION); + m_engine->BuildCompleted(); return asINVALID_CONFIGURATION; } // Compile the global variable and add it to the module scope - asCBuilder varBuilder(engine, this); + asCBuilder varBuilder(m_engine, this); asCString str = code; r = varBuilder.CompileGlobalVar(sectionName, str.AddressOf(), lineOffset); - engine->BuildCompleted(); + m_engine->BuildCompleted(); // Initialize the variable - if( r >= 0 && engine->ep.initGlobalVarsAfterBuild ) + if( r >= 0 ) { // Clear the memory - asCGlobalProperty *prop = scriptGlobals.GetLast(); + asCGlobalProperty *prop = m_scriptGlobals.GetLast(); if( prop ) { memset(prop->GetAddressOfValue(), 0, sizeof(asDWORD)*prop->type.GetSizeOnStackDWords()); + } - if( prop->GetInitFunc() ) - { - // Call the init function for the global variable - asIScriptContext *ctx = 0; - r = engine->CreateContext(&ctx, true); - if( r < 0 ) - return r; + if( prop && m_engine->ep.initGlobalVarsAfterBuild ) + { + // Flag that there are initialized global variables + m_isGlobalVarInitialized = true; - r = ctx->Prepare(prop->GetInitFunc()); - if( r >= 0 ) - r = ctx->Execute(); - - ctx->Release(); - } + r = InitGlobalProp(prop, 0); } } @@ -1726,26 +1780,26 @@ int asCModule::CompileFunction(const char *sectionName, const char *code, int li // Only one thread may build at one time // TODO: It should be possible to have multiple threads perform compilations - int r = engine->RequestBuild(); + int r = m_engine->RequestBuild(); if( r < 0 ) return r; // Prepare the engine - engine->PrepareEngine(); - if( engine->configFailed ) + m_engine->PrepareEngine(); + if( m_engine->configFailed ) { - engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION); - engine->BuildCompleted(); + m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION); + m_engine->BuildCompleted(); return asINVALID_CONFIGURATION; } // Compile the single function - asCBuilder funcBuilder(engine, this); + asCBuilder funcBuilder(m_engine, this); asCString str = code; asCScriptFunction *func = 0; r = funcBuilder.CompileFunction(sectionName, str.AddressOf(), lineOffset, compileFlags, &func); - engine->BuildCompleted(); + m_engine->BuildCompleted(); if( r >= 0 && outFunc && func ) { @@ -1767,11 +1821,11 @@ int asCModule::RemoveFunction(asIScriptFunction *func) { // Find the global function asCScriptFunction *f = static_cast(func); - int idx = globalFunctions.GetIndex(f); + int idx = m_globalFunctions.GetIndex(f); if( idx >= 0 ) { - globalFunctions.Erase(idx); - scriptFunctions.RemoveValue(f); + m_globalFunctions.Erase(idx); + m_scriptFunctions.RemoveValue(f); f->ReleaseInternal(); return 0; } @@ -1786,7 +1840,7 @@ int asCModule::AddFuncDef(const asCString &funcName, asSNameSpace *ns, asCObject // namespace and parent are mutually exclusive asASSERT((ns == 0 && parent) || (ns && parent == 0)); - asCScriptFunction *func = asNEW(asCScriptFunction)(engine, 0, asFUNC_FUNCDEF); + asCScriptFunction *func = asNEW(asCScriptFunction)(m_engine, 0, asFUNC_FUNCDEF); if (func == 0) return asOUT_OF_MEMORY; @@ -1794,12 +1848,12 @@ int asCModule::AddFuncDef(const asCString &funcName, asSNameSpace *ns, asCObject func->nameSpace = ns; func->module = this; - asCFuncdefType *fdt = asNEW(asCFuncdefType)(engine, func); - funcDefs.PushLast(fdt); // The constructor set the refcount to 1 + asCFuncdefType *fdt = asNEW(asCFuncdefType)(m_engine, func); + AddFuncDef(fdt); // The constructor set the refcount to 1 - engine->funcDefs.PushLast(fdt); // doesn't increase refcount - func->id = engine->GetNextScriptFunctionId(); - engine->AddScriptFunction(func); + m_engine->funcDefs.PushLast(fdt); // doesn't increase refcount + func->id = m_engine->GetNextScriptFunctionId(); + m_engine->AddScriptFunction(func); if (parent) { @@ -1807,15 +1861,15 @@ int asCModule::AddFuncDef(const asCString &funcName, asSNameSpace *ns, asCObject fdt->parentClass = parent; } - return (int)funcDefs.GetLength()-1; + return (int)m_funcDefs.GetLength()-1; } #endif // interface asDWORD asCModule::SetAccessMask(asDWORD mask) { - asDWORD old = accessMask; - accessMask = mask; + asDWORD old = m_accessMask; + m_accessMask = mask; return old; } diff --git a/server/src/angelscript/source/as_module.h b/server/src/angelscript/source/as_module.h index 10cedbe..bd4d55e 100644 --- a/server/src/angelscript/source/as_module.h +++ b/server/src/angelscript/source/as_module.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2019 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -182,6 +182,7 @@ public: int CallInit(asIScriptContext *ctx); void CallExit(); + int InitGlobalProp(asCGlobalProperty *prop, asIScriptContext *ctx); void JITCompile(); @@ -194,47 +195,61 @@ public: int GetNextImportedFunctionId(); asCScriptFunction *GetImportedFunction(int funcId) const; - asCTypeInfo *GetType(const char *type, asSNameSpace *ns); - asCObjectType *GetObjectType(const char *type, asSNameSpace *ns); + asCTypeInfo *GetType(const asCString &type, asSNameSpace *ns) const; + asCObjectType *GetObjectType(const char *type, asSNameSpace *ns) const; asCGlobalProperty *AllocateGlobalProperty(const char *name, const asCDataType &dt, asSNameSpace *ns); void UninitializeGlobalProp(asCGlobalProperty *prop); + + // Adds the class type to the module. The module assumes ownership of the reference without increasing it + void AddClassType(asCObjectType*); + // Adds the enum type to the module. The module assumes ownership of the reference without increasing it + void AddEnumType(asCEnumType*); + // Adds the typedef to the module. The module assumes ownership of the reference without increasing it + void AddTypeDef(asCTypedefType*); + // Adds the funcdef to the module. The module assumes ownership of the reference without increasing it + void AddFuncDef(asCFuncdefType*); + // Replaces an existing funcdef with another (used for shared funcdefs). Doesn't add or release refCounts + void ReplaceFuncDef(asCFuncdefType *oldType, asCFuncdefType *newType); - asCString name; - - asCScriptEngine *engine; - asCBuilder *builder; - asCArray userData; - asDWORD accessMask; - asSNameSpace *defaultNamespace; + asCString m_name; + asCScriptEngine *m_engine; + asCBuilder *m_builder; + asCArray m_userData; + asDWORD m_accessMask; + asSNameSpace *m_defaultNamespace; // This array holds all functions, class members, factories, etc that were compiled with the module. // These references hold an internal reference to the function object. - asCArray scriptFunctions; // increases ref count + asCArray m_scriptFunctions; // increases ref count // This array holds global functions declared in the module. These references are not counted, // as the same pointer is always present in the scriptFunctions array too. - asCSymbolTable globalFunctions; // doesn't increase ref count + asCSymbolTable m_globalFunctions; // doesn't increase ref count // This array holds imported functions in the module. - asCArray bindInformations; // increases ref count + asCArray m_bindInformations; // increases ref count // This array holds template instance types created for the module's object types - asCArray templateInstances; // increases ref count + asCArray m_templateInstances; // increases ref count // This array holds the global variables declared in the script - asCSymbolTable scriptGlobals; // increases ref count - bool isGlobalVarInitialized; + asCSymbolTable m_scriptGlobals; // increases ref count + bool m_isGlobalVarInitialized; // This array holds class and interface types - asCArray classTypes; // increases ref count + asCArray m_classTypes; // increases ref count // This array holds enum types - asCArray enumTypes; // increases ref count + asCArray m_enumTypes; // increases ref count // This array holds typedefs - asCArray typeDefs; // increases ref count + asCArray m_typeDefs; // increases ref count // This array holds the funcdefs declared in the module - asCArray funcDefs; // increases ref count + asCArray m_funcDefs; // increases ref count + + // This map contains all the types (also contained in the arrays above) for quick lookup + // TODO: memory: Can we eliminate the arrays above? + asCMap m_typeLookup; // doesn't increase ref count // This array holds types that have been explicitly declared with 'external' - asCArray externalTypes; // doesn't increase ref count + asCArray m_externalTypes; // doesn't increase ref count // This array holds functions that have been explicitly declared with 'external' - asCArray externalFunctions; // doesn't increase ref count + asCArray m_externalFunctions; // doesn't increase ref count }; END_AS_NAMESPACE diff --git a/server/src/angelscript/source/as_restore.cpp b/server/src/angelscript/source/as_restore.cpp index ea8926b..a6b9abc 100644 --- a/server/src/angelscript/source/as_restore.cpp +++ b/server/src/angelscript/source/as_restore.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2019 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -90,12 +90,12 @@ int asCReader::Read(bool *wasDebugInfoStripped) // Make sure none of the loaded functions attempt to release // references that have not yet been increased asUINT i; - for( i = 0; i < module->scriptFunctions.GetLength(); i++ ) - if( !dontTranslate.MoveTo(0, module->scriptFunctions[i]) ) - if( module->scriptFunctions[i]->scriptData ) - module->scriptFunctions[i]->scriptData->byteCode.SetLength(0); + for( i = 0; i < module->m_scriptFunctions.GetLength(); i++ ) + if( !dontTranslate.MoveTo(0, module->m_scriptFunctions[i]) ) + if( module->m_scriptFunctions[i]->scriptData ) + module->m_scriptFunctions[i]->scriptData->byteCode.SetLength(0); - asCSymbolTable::iterator it = module->scriptGlobals.List(); + asCSymbolTable::iterator it = module->m_scriptGlobals.List(); for( ; it; it++ ) if( (*it)->GetInitFunc() ) if( (*it)->GetInitFunc()->scriptData ) @@ -156,7 +156,7 @@ int asCReader::ReadInner() // Read enums count = ReadEncodedUInt(); - module->enumTypes.Allocate(count, false); + module->m_enumTypes.Allocate(count, false); for( i = 0; i < count && !error; i++ ) { asCEnumType *et = asNEW(asCEnumType)(engine); @@ -216,10 +216,10 @@ int asCReader::ReadInner() // Set this module as the owner et->module = module; } - module->enumTypes.PushLast(et); + module->AddEnumType(et); if (isExternal) - module->externalTypes.PushLast(et); + module->m_externalTypes.PushLast(et); ReadTypeDeclaration(et, 2); } @@ -229,7 +229,7 @@ int asCReader::ReadInner() // classTypes[] // First restore the structure names, then the properties count = ReadEncodedUInt(); - module->classTypes.Allocate(count, false); + module->m_classTypes.Allocate(count, false); for( i = 0; i < count && !error; ++i ) { asCObjectType *ot = asNEW(asCObjectType)(engine); @@ -290,17 +290,17 @@ int asCReader::ReadInner() // Set this module as the owner ot->module = module; } - module->classTypes.PushLast(ot); + module->AddClassType(ot); if (isExternal) - module->externalTypes.PushLast(ot); + module->m_externalTypes.PushLast(ot); } if( error ) return asERROR; // Read func defs count = ReadEncodedUInt(); - module->funcDefs.Allocate(count, false); + module->m_funcDefs.Allocate(count, false); for( i = 0; i < count && !error; i++ ) { bool isNew, isExternal; @@ -312,7 +312,7 @@ int asCReader::ReadInner() asCFuncdefType *fdt = funcDef->funcdefType; fdt->module = module; - module->funcDefs.PushLast(fdt); + module->AddFuncDef(fdt); engine->funcDefs.PushLast(fdt); // TODO: clean up: This is also done by the builder. It should probably be moved to a method in the module @@ -334,11 +334,11 @@ int asCReader::ReadInner() f2->funcdef->IsSignatureExceptNameEqual(funcDef) ) { // Replace our funcdef for the existing one - module->funcDefs[module->funcDefs.IndexOf(fdt)] = f2; + module->ReplaceFuncDef(fdt, f2); f2->AddRefInternal(); if (isExternal) - module->externalTypes.PushLast(f2); + module->m_externalTypes.PushLast(f2); engine->funcDefs.RemoveValue(fdt); @@ -378,31 +378,31 @@ int asCReader::ReadInner() } // Read interface methods - for( i = 0; i < module->classTypes.GetLength() && !error; i++ ) + for( i = 0; i < module->m_classTypes.GetLength() && !error; i++ ) { - if( module->classTypes[i]->IsInterface() ) - ReadTypeDeclaration(module->classTypes[i], 2); + if( module->m_classTypes[i]->IsInterface() ) + ReadTypeDeclaration(module->m_classTypes[i], 2); } // Read class methods and behaviours - for( i = 0; i < module->classTypes.GetLength() && !error; ++i ) + for( i = 0; i < module->m_classTypes.GetLength() && !error; ++i ) { - if( !module->classTypes[i]->IsInterface() ) - ReadTypeDeclaration(module->classTypes[i], 2); + if( !module->m_classTypes[i]->IsInterface() ) + ReadTypeDeclaration(module->m_classTypes[i], 2); } // Read class properties - for( i = 0; i < module->classTypes.GetLength() && !error; ++i ) + for( i = 0; i < module->m_classTypes.GetLength() && !error; ++i ) { - if( !module->classTypes[i]->IsInterface() ) - ReadTypeDeclaration(module->classTypes[i], 3); + if( !module->m_classTypes[i]->IsInterface() ) + ReadTypeDeclaration(module->m_classTypes[i], 3); } if( error ) return asERROR; // Read typedefs count = ReadEncodedUInt(); - module->typeDefs.Allocate(count, false); + module->m_typeDefs.Allocate(count, false); for( i = 0; i < count && !error; i++ ) { asCTypedefType *td = asNEW(asCTypedefType)(engine); @@ -415,7 +415,7 @@ int asCReader::ReadInner() bool isExternal = false; ReadTypeDeclaration(td, 1, &isExternal); td->module = module; - module->typeDefs.PushLast(td); + module->AddTypeDef(td); ReadTypeDeclaration(td, 2); } @@ -428,7 +428,7 @@ int asCReader::ReadInner() engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_GLOBAL_VARS_NOT_ALLOWED); Error(TXT_INVALID_BYTECODE_d); } - module->scriptGlobals.Allocate(count, false); + module->m_scriptGlobals.Allocate(count, false); for( i = 0; i < count && !error; ++i ) { ReadGlobalProperty(); @@ -438,7 +438,7 @@ int asCReader::ReadInner() count = ReadEncodedUInt(); for( i = 0; i < count && !error; ++i ) { - size_t len = module->scriptFunctions.GetLength(); + size_t len = module->m_scriptFunctions.GetLength(); bool isNew, isExternal; func = ReadFunction(isNew, true, true, true, &isExternal); if( func == 0 ) @@ -448,7 +448,7 @@ int asCReader::ReadInner() } // Is the function shared and was it created now? - if( func->IsShared() && len != module->scriptFunctions.GetLength() ) + if( func->IsShared() && len != module->m_scriptFunctions.GetLength() ) { // If the function already existed in another module, then // we need to replace it with previously existing one @@ -462,7 +462,7 @@ int asCReader::ReadInner() realFunc->IsSignatureEqual(func) ) { // Replace the recently created function with the pre-existing function - module->scriptFunctions[module->scriptFunctions.GetLength()-1] = realFunc; + module->m_scriptFunctions[module->m_scriptFunctions.GetLength()-1] = realFunc; realFunc->AddRefInternal(); savedFunctions[savedFunctions.GetLength()-1] = realFunc; engine->RemoveScriptFunction(func); @@ -471,7 +471,7 @@ int asCReader::ReadInner() dontTranslate.Insert(realFunc, true); if (isExternal) - module->externalFunctions.PushLast(realFunc); + module->m_externalFunctions.PushLast(realFunc); // Release the function, but make sure nothing else is released func->id = 0; @@ -507,7 +507,7 @@ int asCReader::ReadInner() // we're just re-reading the references to know which goes into the globalFunctions array asASSERT( !isNew ); - module->globalFunctions.Put(func); + module->m_globalFunctions.Put(func); } else Error(TXT_INVALID_BYTECODE_d); @@ -517,7 +517,7 @@ int asCReader::ReadInner() // bindInformations[] count = ReadEncodedUInt(); - module->bindInformations.Allocate(count, false); + module->m_bindInformations.Allocate(count, false); for( i = 0; i < count && !error; ++i ) { sBindInfo *info = asNEW(sBindInfo); @@ -548,7 +548,7 @@ int asCReader::ReadInner() } ReadString(&info->importFromModule); info->boundFunctionId = -1; - module->bindInformations.PushLast(info); + module->m_bindInformations.PushLast(info); } if( error ) return asERROR; @@ -622,11 +622,11 @@ int asCReader::ReadInner() // Update the loaded bytecode to point to the correct types, property offsets, // function ids, etc. This is basically a linking stage. - for( i = 0; i < module->scriptFunctions.GetLength() && !error; i++ ) - if( module->scriptFunctions[i]->funcType == asFUNC_SCRIPT ) - TranslateFunction(module->scriptFunctions[i]); + for( i = 0; i < module->m_scriptFunctions.GetLength() && !error; i++ ) + if( module->m_scriptFunctions[i]->funcType == asFUNC_SCRIPT ) + TranslateFunction(module->m_scriptFunctions[i]); - asCSymbolTable::iterator globIt = module->scriptGlobals.List(); + asCSymbolTable::iterator globIt = module->m_scriptGlobals.List(); while( globIt && !error ) { asCScriptFunction *initFunc = (*globIt)->GetInitFunc(); @@ -638,11 +638,11 @@ int asCReader::ReadInner() if( error ) return asERROR; // Add references for all functions (except for the pre-existing shared code) - for( i = 0; i < module->scriptFunctions.GetLength(); i++ ) - if( !dontTranslate.MoveTo(0, module->scriptFunctions[i]) ) - module->scriptFunctions[i]->AddReferences(); + for( i = 0; i < module->m_scriptFunctions.GetLength(); i++ ) + if( !dontTranslate.MoveTo(0, module->m_scriptFunctions[i]) ) + module->m_scriptFunctions[i]->AddReferences(); - globIt = module->scriptGlobals.List(); + globIt = module->m_scriptGlobals.List(); while( globIt ) { asCScriptFunction *initFunc = (*globIt)->GetInitFunc(); @@ -721,9 +721,9 @@ void asCReader::ReadUsedFunctions() { if( func.funcType == asFUNC_IMPORTED ) { - for( asUINT i = 0; i < module->bindInformations.GetLength(); i++ ) + for( asUINT i = 0; i < module->m_bindInformations.GetLength(); i++ ) { - asCScriptFunction *f = module->bindInformations[i]->importedFunctionSignature; + asCScriptFunction *f = module->m_bindInformations[i]->importedFunctionSignature; if( func.objectType != f->objectType || func.funcType != f->funcType || func.nameSpace != f->nameSpace || @@ -736,7 +736,7 @@ void asCReader::ReadUsedFunctions() } else if( func.funcType == asFUNC_FUNCDEF ) { - const asCArray &funcs = module->funcDefs; + const asCArray &funcs = module->m_funcDefs; for( asUINT i = 0; i < funcs.GetLength(); i++ ) { asCScriptFunction *f = funcs[i]->funcdef; @@ -757,9 +757,9 @@ void asCReader::ReadUsedFunctions() // TODO: optimize: Global functions should be searched for in module->globalFunctions // TODO: optimize: funcdefs should be searched for in module->funcDefs // TODO: optimize: object methods should be searched for directly in the object type - for( asUINT i = 0; i < module->scriptFunctions.GetLength(); i++ ) + for( asUINT i = 0; i < module->m_scriptFunctions.GetLength(); i++ ) { - asCScriptFunction *f = module->scriptFunctions[i]; + asCScriptFunction *f = module->m_scriptFunctions[i]; if( func.objectType != f->objectType || func.funcType != f->funcType || func.nameSpace != f->nameSpace || @@ -922,17 +922,6 @@ void asCReader::ReadUsedFunctions() usedFunctions[n] = f; } } - else if( func.name == "$beh4" ) - { - // This is a list factory, so check the return type's list factory - asCObjectType *objType = CastToObjectType(func.returnType.GetTypeInfo()); - if( objType ) - { - asCScriptFunction *f = engine->scriptFunctions[objType->beh.listFactory]; - if( f && func.IsSignatureExceptNameAndObjectTypeEqual(f) ) - usedFunctions[n] = f; - } - } else if( func.name == "$dlgte" ) { // This is the delegate factory @@ -940,6 +929,11 @@ void asCReader::ReadUsedFunctions() asASSERT( f && func.IsSignatureEqual(f) ); usedFunctions[n] = f; } + else + { + // Must match one of the above cases + asASSERT(false); + } } else if( func.objectType == 0 ) { @@ -1205,7 +1199,7 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a if( func->funcType == asFUNC_SCRIPT ) { // Skip this for external shared entities - if (module->externalTypes.IndexOf(func->objectType) >= 0) + if (module->m_externalTypes.IndexOf(func->objectType) >= 0) { // Replace with the real function from the existing entity isNew = false; @@ -1429,10 +1423,110 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a fdt->parentClass = parentClass; } + // Methods loaded for shared objects, owned by other modules should not be created as new functions + if( func->objectType && func->objectType->module != module ) + { + // Return the real function from the object + asCScriptFunction *realFunc = 0; + bool found = false; + if( func->funcType == asFUNC_SCRIPT ) + { + realFunc = engine->scriptFunctions[func->objectType->beh.destruct]; + if( realFunc && realFunc->funcType != asFUNC_VIRTUAL && func->IsSignatureEqual(realFunc) ) + { + found = true; + } + for( asUINT n = 0; !found && n < func->objectType->beh.constructors.GetLength(); n++ ) + { + realFunc = engine->scriptFunctions[func->objectType->beh.constructors[n]]; + if( realFunc && realFunc->funcType != asFUNC_VIRTUAL && func->IsSignatureEqual(realFunc) ) + { + found = true; + break; + } + } + for( asUINT n = 0; !found && n < func->objectType->beh.factories.GetLength(); n++ ) + { + realFunc = engine->scriptFunctions[func->objectType->beh.factories[n]]; + if( realFunc && realFunc->funcType != asFUNC_VIRTUAL && func->IsSignatureEqual(realFunc) ) + { + found = true; + break; + } + } + for( asUINT n = 0; !found && n < func->objectType->methods.GetLength(); n++ ) + { + realFunc = engine->scriptFunctions[func->objectType->methods[n]]; + if( realFunc && realFunc->funcType == func->funcType && func->IsSignatureEqual(realFunc) ) + { + found = true; + break; + } + } + for( asUINT n = 0; !found && n < func->objectType->virtualFunctionTable.GetLength(); n++ ) + { + realFunc = func->objectType->virtualFunctionTable[n]; + if( realFunc && realFunc->funcType == func->funcType && func->IsSignatureEqual(realFunc) ) + { + found = true; + break; + } + } + } + else if( func->funcType == asFUNC_VIRTUAL || func->funcType == asFUNC_INTERFACE ) + { + // If the loaded function is a virtual function, then look for the identical virtual function in the methods array + for( asUINT n = 0; n < func->objectType->methods.GetLength(); n++ ) + { + realFunc = engine->scriptFunctions[func->objectType->methods[n]]; + if( realFunc && realFunc->funcType == func->funcType && func->IsSignatureEqual(realFunc) ) + { + asASSERT( func->vfTableIdx == realFunc->vfTableIdx ); + found = true; + break; + } + } + } + + if( found ) + { + // as this is an existing function it shouldn't be translated as if just loaded + dontTranslate.Insert(realFunc, true); + + // update the saved functions for future references + savedFunctions[savedFunctions.GetLength() - 1] = realFunc; + + if( realFunc->funcType == asFUNC_VIRTUAL && addToModule ) + { + // Virtual methods must be added to the module's script functions array, + // even if they are not owned by the module + module->m_scriptFunctions.PushLast(realFunc); + realFunc->AddRefInternal(); + } + } + else + { + asCString str; + str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, func->objectType->GetName()); + engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf()); + + Error(TXT_INVALID_BYTECODE_d); + savedFunctions.PopLast(); + realFunc = 0; + } + + // Destroy the newly created function instance since it has been replaced by an existing function + isNew = false; + func->DestroyHalfCreated(); + + // As it is an existing function it shouldn't be added to the module or the engine + return realFunc; + } + if( addToModule ) { // The refCount is already 1 - module->scriptFunctions.PushLast(func); + module->m_scriptFunctions.PushLast(func); func->module = module; } if( addToEngine ) @@ -1513,7 +1607,7 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern else if( phase == 2 ) { // external shared types doesn't store this - if ((type->flags & asOBJ_SHARED) && module->externalTypes.IndexOf(type) >= 0) + if ((type->flags & asOBJ_SHARED) && module->m_externalTypes.IndexOf(type) >= 0) return; if( type->flags & asOBJ_ENUM ) @@ -1668,8 +1762,6 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern func->scriptData->byteCode.SetLength(0); func->ReleaseInternal(); } - module->scriptFunctions.PushLast(realFunc); - realFunc->AddRefInternal(); dontTranslate.Insert(realFunc, true); } } @@ -1703,8 +1795,6 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern if( savedFunctions[savedFunctions.GetLength()-1] == func ) savedFunctions[savedFunctions.GetLength()-1] = realFunc; found = true; - module->scriptFunctions.PushLast(realFunc); - realFunc->AddRefInternal(); dontTranslate.Insert(realFunc, true); break; } @@ -1754,8 +1844,6 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern if( savedFunctions[savedFunctions.GetLength()-1] == func ) savedFunctions[savedFunctions.GetLength()-1] = realFunc; found = true; - module->scriptFunctions.PushLast(realFunc); - realFunc->AddRefInternal(); dontTranslate.Insert(realFunc, true); break; } @@ -1813,8 +1901,6 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern if( savedFunctions[savedFunctions.GetLength()-1] == func ) savedFunctions[savedFunctions.GetLength()-1] = realFunc; found = true; - module->scriptFunctions.PushLast(realFunc); - realFunc->AddRefInternal(); dontTranslate.Insert(realFunc, true); break; } @@ -1880,8 +1966,6 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern if( savedFunctions[savedFunctions.GetLength()-1] == func ) savedFunctions[savedFunctions.GetLength()-1] = realFunc; found = true; - module->scriptFunctions.PushLast(realFunc); - realFunc->AddRefInternal(); dontTranslate.Insert(realFunc, true); break; } @@ -1918,7 +2002,7 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern else if( phase == 3 ) { // external shared types doesn't store this - if ((type->flags & asOBJ_SHARED) && module->externalTypes.IndexOf(type) >= 0) + if ((type->flags & asOBJ_SHARED) && module->m_externalTypes.IndexOf(type) >= 0) return; asCObjectType *ot = CastToObjectType(type); @@ -2614,7 +2698,7 @@ void asCReader::ReadUsedGlobalProps() // Find the real property asCGlobalProperty *globProp = 0; if( moduleProp ) - globProp = module->scriptGlobals.GetFirst(nameSpace, name); + globProp = module->m_scriptGlobals.GetFirst(nameSpace, name); else globProp = engine->registeredGlobalProps.GetFirst(nameSpace, name); @@ -2873,9 +2957,9 @@ void asCReader::TranslateFunction(asCScriptFunction *func) { // Translate the function id asUINT *fid = (asUINT*)&bc[n+1]; - if( *fid < module->bindInformations.GetLength() ) + if( *fid < module->m_bindInformations.GetLength() ) { - sBindInfo *bi = module->bindInformations[*fid]; + sBindInfo *bi = module->m_bindInformations[*fid]; if( bi ) *fid = bi->importedFunctionSignature->id; else @@ -3819,12 +3903,12 @@ int asCWriter::Write() { TimeIt("store enums"); - count = (asUINT)module->enumTypes.GetLength(); + count = (asUINT)module->m_enumTypes.GetLength(); WriteEncodedInt64(count); for( i = 0; i < count; i++ ) { - WriteTypeDeclaration(module->enumTypes[i], 1); - WriteTypeDeclaration(module->enumTypes[i], 2); + WriteTypeDeclaration(module->m_enumTypes[i], 1); + WriteTypeDeclaration(module->m_enumTypes[i], 2); } } @@ -3832,12 +3916,12 @@ int asCWriter::Write() { TimeIt("type declarations"); - count = (asUINT)module->classTypes.GetLength(); + count = (asUINT)module->m_classTypes.GetLength(); WriteEncodedInt64(count); for( i = 0; i < count; i++ ) { // Store only the name of the class/interface types - WriteTypeDeclaration(module->classTypes[i], 1); + WriteTypeDeclaration(module->m_classTypes[i], 1); } } @@ -3845,21 +3929,21 @@ int asCWriter::Write() { TimeIt("func defs"); - count = (asUINT)module->funcDefs.GetLength(); + count = (asUINT)module->m_funcDefs.GetLength(); WriteEncodedInt64(count); for( i = 0; i < count; i++ ) - WriteFunction(module->funcDefs[i]->funcdef); + WriteFunction(module->m_funcDefs[i]->funcdef); } // Now store all interface methods { TimeIt("interface methods"); - count = (asUINT)module->classTypes.GetLength(); + count = (asUINT)module->m_classTypes.GetLength(); for( i = 0; i < count; i++ ) { - if( module->classTypes[i]->IsInterface() ) - WriteTypeDeclaration(module->classTypes[i], 2); + if( module->m_classTypes[i]->IsInterface() ) + WriteTypeDeclaration(module->m_classTypes[i], 2); } } @@ -3869,8 +3953,8 @@ int asCWriter::Write() for( i = 0; i < count; ++i ) { - if( !module->classTypes[i]->IsInterface() ) - WriteTypeDeclaration(module->classTypes[i], 2); + if( !module->m_classTypes[i]->IsInterface() ) + WriteTypeDeclaration(module->m_classTypes[i], 2); } } @@ -3880,8 +3964,8 @@ int asCWriter::Write() for( i = 0; i < count; ++i ) { - if( !module->classTypes[i]->IsInterface() ) - WriteTypeDeclaration(module->classTypes[i], 3); + if( !module->m_classTypes[i]->IsInterface() ) + WriteTypeDeclaration(module->m_classTypes[i], 3); } } @@ -3889,12 +3973,12 @@ int asCWriter::Write() { TimeIt("type defs"); - count = (asUINT)module->typeDefs.GetLength(); + count = (asUINT)module->m_typeDefs.GetLength(); WriteEncodedInt64(count); for( i = 0; i < count; i++ ) { - WriteTypeDeclaration(module->typeDefs[i], 1); - WriteTypeDeclaration(module->typeDefs[i], 2); + WriteTypeDeclaration(module->m_typeDefs[i], 1); + WriteTypeDeclaration(module->m_typeDefs[i], 2); } } @@ -3902,9 +3986,9 @@ int asCWriter::Write() { TimeIt("script globals"); - count = (asUINT)module->scriptGlobals.GetSize(); + count = (asUINT)module->m_scriptGlobals.GetSize(); WriteEncodedInt64(count); - asCSymbolTable::iterator it = module->scriptGlobals.List(); + asCSymbolTable::iterator it = module->m_scriptGlobals.List(); for( ; it; it++ ) WriteGlobalProperty(*it); } @@ -3914,21 +3998,21 @@ int asCWriter::Write() TimeIt("scriptFunctions"); count = 0; - for( i = 0; i < module->scriptFunctions.GetLength(); i++ ) - if( module->scriptFunctions[i]->objectType == 0 ) + for( i = 0; i < module->m_scriptFunctions.GetLength(); i++ ) + if( module->m_scriptFunctions[i]->objectType == 0 ) count++; WriteEncodedInt64(count); - for( i = 0; i < module->scriptFunctions.GetLength(); ++i ) - if( module->scriptFunctions[i]->objectType == 0 ) - WriteFunction(module->scriptFunctions[i]); + for( i = 0; i < module->m_scriptFunctions.GetLength(); ++i ) + if( module->m_scriptFunctions[i]->objectType == 0 ) + WriteFunction(module->m_scriptFunctions[i]); } // globalFunctions[] { TimeIt("globalFunctions"); - count = (int)module->globalFunctions.GetSize(); - asCSymbolTable::iterator funcIt = module->globalFunctions.List(); + count = (int)module->m_globalFunctions.GetSize(); + asCSymbolTable::iterator funcIt = module->m_globalFunctions.List(); WriteEncodedInt64(count); while( funcIt ) { @@ -3941,12 +4025,12 @@ int asCWriter::Write() { TimeIt("bindInformations"); - count = (asUINT)module->bindInformations.GetLength(); + count = (asUINT)module->m_bindInformations.GetLength(); WriteEncodedInt64(count); for( i = 0; i < count; ++i ) { - WriteFunction(module->bindInformations[i]->importedFunctionSignature); - WriteString(&module->bindInformations[i]->importFromModule); + WriteFunction(module->m_bindInformations[i]->importedFunctionSignature); + WriteString(&module->m_bindInformations[i]->importFromModule); } } @@ -4026,9 +4110,9 @@ void asCWriter::WriteUsedFunctions() // Is the function from the module or the application? c = func->module ? 'm' : 'a'; - // Functions and methods that are shared and not owned by the module can be - // stored as 's' to tell the reader that these are received from other modules. - if (c == 'm' && func->IsShared() && module->scriptFunctions.IndexOf(func) < 0 ) + // Functions and methods that are shared should be stored as 's' as the bytecode + // may be imported from other modules (even if the current module have received ownership) + if (c == 'm' && func->IsShared() ) c = 's'; WriteData(&c, 1); @@ -4164,13 +4248,13 @@ void asCWriter::WriteFunction(asCScriptFunction* func) if( func->funcType == asFUNC_SCRIPT ) { // Skip this for external shared entities - if (module->externalTypes.IndexOf(func->objectType) >= 0) + if (module->m_externalTypes.IndexOf(func->objectType) >= 0) return; char bits = 0; bits += func->IsShared() ? 1 : 0; bits += func->dontCleanUpOnException ? 2 : 0; - if (module->externalFunctions.IndexOf(func) >= 0) + if (module->m_externalFunctions.IndexOf(func) >= 0) bits += 4; if (func->scriptData->objVariablePos.GetLength() || func->scriptData->objVariableInfo.GetLength()) bits += 8; @@ -4305,7 +4389,7 @@ void asCWriter::WriteFunction(asCScriptFunction* func) { char bits = 0; bits += func->IsShared() ? 1 : 0; - if (module->externalTypes.IndexOf(func->funcdefType) >= 0) + if (module->m_externalTypes.IndexOf(func->funcdefType) >= 0) bits += 2; WriteData(&bits,1); } @@ -4343,7 +4427,7 @@ void asCWriter::WriteTypeDeclaration(asCTypeInfo *type, int phase) if ((type->flags & asOBJ_SHARED)) { char c = ' '; - if (module->externalTypes.IndexOf(type) >= 0) + if (module->m_externalTypes.IndexOf(type) >= 0) c = 'e'; WriteData(&c, 1); } @@ -4351,7 +4435,7 @@ void asCWriter::WriteTypeDeclaration(asCTypeInfo *type, int phase) else if( phase == 2 ) { // external shared types doesn't need to save this - if ((type->flags & asOBJ_SHARED) && module->externalTypes.IndexOf(type) >= 0) + if ((type->flags & asOBJ_SHARED) && module->m_externalTypes.IndexOf(type) >= 0) return; if(type->flags & asOBJ_ENUM ) @@ -4429,7 +4513,7 @@ void asCWriter::WriteTypeDeclaration(asCTypeInfo *type, int phase) else if( phase == 3 ) { // external shared types doesn't need to save this - if ((type->flags & asOBJ_SHARED) && module->externalTypes.IndexOf(type) >= 0) + if ((type->flags & asOBJ_SHARED) && module->m_externalTypes.IndexOf(type) >= 0) return; // properties[] @@ -5046,8 +5130,8 @@ void asCWriter::WriteByteCode(asCScriptFunction *func) { // Translate the function id int funcId = tmpBC[1]; - for( asUINT n = 0; n < module->bindInformations.GetLength(); n++ ) - if( module->bindInformations[n]->importedFunctionSignature->id == funcId ) + for( asUINT n = 0; n < module->m_bindInformations.GetLength(); n++ ) + if( module->m_bindInformations[n]->importedFunctionSignature->id == funcId ) { funcId = n; break; diff --git a/server/src/angelscript/source/as_scriptengine.cpp b/server/src/angelscript/source/as_scriptengine.cpp index 56e11fb..d8aa274 100644 --- a/server/src/angelscript/source/as_scriptengine.cpp +++ b/server/src/angelscript/source/as_scriptengine.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2019 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -218,6 +218,9 @@ AS_API const char * asGetLibraryOptions() #endif #ifdef AS_SPARC "AS_SPARC " +#endif +#ifdef AS_ARM64 + "AS_ARM64 " #endif ; @@ -919,15 +922,15 @@ asCModule *asCScriptEngine::FindNewOwnerForSharedType(asCTypeInfo *in_type, asCM asCModule *mod = scriptModules[n]; if( mod == in_type->module ) continue; if( in_type->flags & asOBJ_ENUM ) - foundIdx = mod->enumTypes.IndexOf(CastToEnumType(in_type)); + foundIdx = mod->m_enumTypes.IndexOf(CastToEnumType(in_type)); else if (in_type->flags & asOBJ_TYPEDEF) - foundIdx = mod->typeDefs.IndexOf(CastToTypedefType(in_type)); + foundIdx = mod->m_typeDefs.IndexOf(CastToTypedefType(in_type)); else if (in_type->flags & asOBJ_FUNCDEF) - foundIdx = mod->funcDefs.IndexOf(CastToFuncdefType(in_type)); + foundIdx = mod->m_funcDefs.IndexOf(CastToFuncdefType(in_type)); else if (in_type->flags & asOBJ_TEMPLATE) - foundIdx = mod->templateInstances.IndexOf(CastToObjectType(in_type)); + foundIdx = mod->m_templateInstances.IndexOf(CastToObjectType(in_type)); else - foundIdx = mod->classTypes.IndexOf(CastToObjectType(in_type)); + foundIdx = mod->m_classTypes.IndexOf(CastToObjectType(in_type)); if( foundIdx >= 0 ) { @@ -948,13 +951,30 @@ asCModule *asCScriptEngine::FindNewOwnerForSharedFunc(asCScriptFunction *in_func if( in_func->module != in_mod) return in_func->module; + if (in_func->objectType && in_func->objectType->module && + in_func->objectType->module != in_func->module) + { + // The object type for the method has already been transferred to + // another module, so transfer the method to the same module + in_func->module = in_func->objectType->module; + + // Make sure the function is listed in the module + // The compiler may not have done this earlier, since the object + // type is shared and originally compiled from another module + if (in_func->module->m_scriptFunctions.IndexOf(in_func) < 0) + { + in_func->module->m_scriptFunctions.PushLast(in_func); + in_func->AddRefInternal(); + } + } + for( asUINT n = 0; n < scriptModules.GetLength(); n++ ) { // TODO: optimize: If the modules already stored the shared types separately, this would be quicker int foundIdx = -1; asCModule *mod = scriptModules[n]; if( mod == in_func->module ) continue; - foundIdx = mod->scriptFunctions.IndexOf(in_func); + foundIdx = mod->m_scriptFunctions.IndexOf(in_func); if( foundIdx >= 0 ) { @@ -1495,7 +1515,9 @@ int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declara prop->isCompositeIndirect = isCompositeIndirect; prop->accessMask = defaultAccessMask; - CastToObjectType(dt.GetTypeInfo())->properties.PushLast(prop); + asCObjectType *ot = CastToObjectType(dt.GetTypeInfo()); + asUINT idx = ot->properties.GetLength(); + ot->properties.PushLast(prop); // Add references to types so they are not released too early if( type.GetTypeInfo() ) @@ -1509,7 +1531,8 @@ int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declara currentGroup->AddReferencesForType(this, type.GetTypeInfo()); - return asSUCCESS; + // Return the index of the property to signal success + return idx; } // interface @@ -2111,6 +2134,8 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as } else if( behaviour == asBEHAVE_LIST_CONSTRUCT ) { + func.name = "$list"; + // Verify that the return type is void if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) ) { @@ -2166,6 +2191,9 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as } else if( behaviour == asBEHAVE_FACTORY || behaviour == asBEHAVE_LIST_FACTORY ) { + if( behaviour == asBEHAVE_LIST_FACTORY ) + func.name = "$list"; + // Must be a ref type and must not have asOBJ_NOHANDLE if( !(objectType->flags & asOBJ_REF) || (objectType->flags & asOBJ_NOHANDLE) ) { @@ -2565,13 +2593,14 @@ int asCScriptEngine::RegisterGlobalProperty(const char *declaration, void *point prop->SetRegisteredAddress(pointer); varAddressMap.Insert(prop->GetAddressOfValue(), prop); - registeredGlobalProps.Put(prop); + asUINT idx = registeredGlobalProps.Put(prop); prop->AddRef(); currentGroup->globalProps.PushLast(prop); currentGroup->AddReferencesForType(this, type.GetTypeInfo()); - return asSUCCESS; + // Return the index of the property to signal success + return int(idx); } // internal @@ -2650,10 +2679,13 @@ int asCScriptEngine::GetGlobalPropertyByIndex(asUINT index, const char **name, c } // interface -int asCScriptEngine::GetGlobalPropertyIndexByName(const char *name) const +int asCScriptEngine::GetGlobalPropertyIndexByName(const char *in_name) const { - asSNameSpace *ns = defaultNamespace; - + asCString name; + asSNameSpace *ns = 0; + if( DetermineNameAndNamespace(in_name, defaultNamespace, name, ns) < 0 ) + return asINVALID_ARG; + // Find the global var id while( ns ) { @@ -3254,13 +3286,13 @@ asCModule *asCScriptEngine::GetModule(const char *name, bool create) asCModule *retModule = 0; ACQUIRESHARED(engineRWLock); - if( lastModule && lastModule->name == name ) + if( lastModule && lastModule->m_name == name ) retModule = lastModule; else { // TODO: optimize: Improve linear search for( asUINT n = 0; n < scriptModules.GetLength(); ++n ) - if( scriptModules[n] && scriptModules[n]->name == name ) + if( scriptModules[n] && scriptModules[n]->m_name == name ) { retModule = scriptModules[n]; break; @@ -3376,9 +3408,9 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT // It may be without ownership if it was previously created from application with for example GetTypeInfoByDecl type->module = requestingModule; } - if( !requestingModule->templateInstances.Exists(type) ) + if( !requestingModule->m_templateInstances.Exists(type) ) { - requestingModule->templateInstances.PushLast(type); + requestingModule->m_templateInstances.PushLast(type); type->AddRefInternal(); } } @@ -3418,7 +3450,7 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT { // Set the ownership of this template type ot->module = requestingModule; - requestingModule->templateInstances.PushLast(ot); + requestingModule->m_templateInstances.PushLast(ot); ot->AddRefInternal(); } else @@ -3434,7 +3466,7 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT ot->module = subTypes[n].GetTypeInfo()->module; if( ot->module ) { - ot->module->templateInstances.PushLast(ot); + ot->module->m_templateInstances.PushLast(ot); ot->AddRefInternal(); break; } @@ -3458,7 +3490,7 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT ot->templateSubTypes.SetLength(0); if( ot->module ) { - ot->module->templateInstances.RemoveValue(ot); + ot->module->m_templateInstances.RemoveValue(ot); ot->ReleaseInternal(); } ot->ReleaseInternal(); @@ -5778,7 +5810,7 @@ asCFuncdefType *asCScriptEngine::FindMatchingFuncdef(asCScriptFunction *func, as // Add the new funcdef to the module so it will // be available when saving the bytecode funcDef->module = module; - module->funcDefs.PushLast(funcDef); // the refCount was already accounted for in the constructor + module->AddFuncDef(funcDef); // the refCount was already accounted for in the constructor } // Observe, if the funcdef is created without informing a module a reference will be stored in the @@ -5790,9 +5822,9 @@ asCFuncdefType *asCScriptEngine::FindMatchingFuncdef(asCScriptFunction *func, as { // Unless this is a registered funcDef the returned funcDef must // be stored as part of the module for saving/loading bytecode - if (!module->funcDefs.Exists(funcDef)) + if (!module->m_funcDefs.Exists(funcDef)) { - module->funcDefs.PushLast(funcDef); + module->AddFuncDef(funcDef); funcDef->AddRefInternal(); } else @@ -6026,9 +6058,13 @@ asITypeInfo *asCScriptEngine::GetObjectTypeByIndex(asUINT index) const } // interface -asITypeInfo *asCScriptEngine::GetTypeInfoByName(const char *name) const +asITypeInfo *asCScriptEngine::GetTypeInfoByName(const char *in_name) const { - asSNameSpace *ns = defaultNamespace; + asCString name; + asSNameSpace *ns = 0; + if( DetermineNameAndNamespace(in_name, defaultNamespace, name, ns) < 0 ) + return 0; + while (ns) { // Check the object types @@ -6071,6 +6107,49 @@ asITypeInfo *asCScriptEngine::GetTypeInfoByName(const char *name) const return 0; } +// internal +int asCScriptEngine::DetermineNameAndNamespace(const char *in_name, asSNameSpace *implicitNs, asCString &out_name, asSNameSpace *&out_ns) const +{ + if( in_name == 0 ) + return asINVALID_ARG; + + asCString name = in_name; + asCString scope; + asSNameSpace *ns = implicitNs; + + // Check if the given name contains a scope + int pos = name.FindLast("::"); + if( pos >= 0 ) + { + scope = name.SubString(0, pos); + name = name.SubString(pos+2); + if( pos == 0 ) + { + // The scope is '::' so the search must start in the global namespace + ns = nameSpaces[0]; + } + else if( scope.SubString(0, 2) == "::" ) + { + // The scope starts with '::' so the given scope is fully qualified + ns = FindNameSpace(scope.SubString(2).AddressOf()); + } + else + { + // The scope doesn't start with '::' so it is relative to the current namespace + if( implicitNs->name == "" ) + ns = FindNameSpace(scope.AddressOf()); + else + ns = FindNameSpace((implicitNs->name + "::" + scope).AddressOf()); + } + } + + out_name = name; + out_ns = ns; + + return 0; +} + + // interface asITypeInfo *asCScriptEngine::GetTypeInfoById(int typeId) const { diff --git a/server/src/angelscript/source/as_scriptengine.h b/server/src/angelscript/source/as_scriptengine.h index 98cbf48..18441fd 100644 --- a/server/src/angelscript/source/as_scriptengine.h +++ b/server/src/angelscript/source/as_scriptengine.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2018 Andreas Jonsson + Copyright (c) 2003-2019 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 @@ -305,6 +305,8 @@ public: asCFuncdefType *FindMatchingFuncdef(asCScriptFunction *func, asCModule *mod); + int DetermineNameAndNamespace(const char *in_name, asSNameSpace *implicitNs, asCString &out_name, asSNameSpace *&out_ns) const; + // Global property management asCGlobalProperty *AllocateGlobalProperty(); void RemoveGlobalProperty(asCGlobalProperty *prop); diff --git a/server/src/angelscript/source/as_scriptfunction.cpp b/server/src/angelscript/source/as_scriptfunction.cpp index 160541b..02dd9a5 100644 --- a/server/src/angelscript/source/as_scriptfunction.cpp +++ b/server/src/angelscript/source/as_scriptfunction.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2019 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -584,9 +584,7 @@ bool asCScriptFunction::IsCompatibleWithTypeId(int typeId) const const char *asCScriptFunction::GetModuleName() const { if( module ) - { - return module->name.AddressOf(); - } + return module->GetName(); return 0; } diff --git a/server/src/angelscript/source/as_scriptobject.cpp b/server/src/angelscript/source/as_scriptobject.cpp index cbb6a12..5c2654c 100644 --- a/server/src/angelscript/source/as_scriptobject.cpp +++ b/server/src/angelscript/source/as_scriptobject.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2018 Andreas Jonsson + Copyright (c) 2003-2019 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 @@ -888,30 +888,43 @@ asCScriptObject &ScriptObject_Assignment(asCScriptObject *other, asCScriptObject asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other) { - if( &other != this ) + CopyFromAs(&other, objType); + return *this; +} + +// internal +int asCScriptObject::CopyFromAs(const asCScriptObject *other, asCObjectType *in_objType) +{ + if( other != this ) { - if( !other.objType->DerivesFrom(objType) ) + if( !other->objType->DerivesFrom(in_objType) ) { // We cannot allow a value assignment from a type that isn't the same or // derives from this type as the member properties may not have the same layout asIScriptContext *ctx = asGetActiveContext(); ctx->SetException(TXT_MISMATCH_IN_VALUE_ASSIGN); - return *this; + return asERROR; } // If the script class implements the opAssign method, it should be called - asCScriptEngine *engine = objType->engine; - asCScriptFunction *func = engine->scriptFunctions[objType->beh.copy]; + asCScriptEngine *engine = in_objType->engine; + asCScriptFunction *func = engine->scriptFunctions[in_objType->beh.copy]; if( func->funcType == asFUNC_SYSTEM ) { - // Copy all properties - for( asUINT n = 0; n < objType->properties.GetLength(); n++ ) + // If derived, use the base class' assignment operator to copy the inherited + // properties. Then only copy new properties for the derived class + if( in_objType->derivedFrom ) + CopyFromAs(other, in_objType->derivedFrom); + + for( asUINT n = in_objType->derivedFrom ? in_objType->derivedFrom->properties.GetLength() : 0; + n < in_objType->properties.GetLength(); + n++ ) { - asCObjectProperty *prop = objType->properties[n]; + asCObjectProperty *prop = in_objType->properties[n]; if( prop->type.IsObject() ) { void **dst = (void**)(((char*)this) + prop->byteOffset); - void **src = (void**)(((char*)&other) + prop->byteOffset); + void **src = (void**)(((char*)other) + prop->byteOffset); if( !prop->type.IsObjectHandle() ) { if( prop->type.IsReference() || (prop->type.GetTypeInfo()->flags & asOBJ_REF) ) @@ -925,7 +938,7 @@ asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other) else if (prop->type.IsFuncdef()) { asCScriptFunction **dst = (asCScriptFunction**)(((char*)this) + prop->byteOffset); - asCScriptFunction **src = (asCScriptFunction**)(((char*)&other) + prop->byteOffset); + asCScriptFunction **src = (asCScriptFunction**)(((char*)other) + prop->byteOffset); if (*dst) (*dst)->Release(); *dst = *src; @@ -935,7 +948,7 @@ asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other) else { void *dst = ((char*)this) + prop->byteOffset; - void *src = ((char*)&other) + prop->byteOffset; + void *src = ((char*)other) + prop->byteOffset; memcpy(dst, src, prop->type.GetSizeInMemoryBytes()); } } @@ -961,24 +974,20 @@ asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other) // Request a context from the engine ctx = engine->RequestContext(); if( ctx == 0 ) - { - // TODO: How to best report this failure? - return *this; - } + return asERROR; } - r = ctx->Prepare(engine->scriptFunctions[objType->beh.copy]); + r = ctx->Prepare(engine->scriptFunctions[in_objType->beh.copy]); if( r < 0 ) { if( isNested ) ctx->PopState(); else engine->ReturnContext(ctx); - // TODO: How to best report this failure? - return *this; + return r; } - r = ctx->SetArgAddress(0, const_cast(&other)); + r = ctx->SetArgAddress(0, const_cast(other)); asASSERT( r >= 0 ); r = ctx->SetObject(this); asASSERT( r >= 0 ); @@ -1014,7 +1023,7 @@ asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other) // Return the context to the engine engine->ReturnContext(ctx); } - return *this; + return asERROR; } if( isNested ) @@ -1027,10 +1036,10 @@ asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other) } } - return *this; + return asSUCCESS; } -int asCScriptObject::CopyFrom(asIScriptObject *other) +int asCScriptObject::CopyFrom(const asIScriptObject *other) { if( other == 0 ) return asINVALID_ARG; @@ -1039,7 +1048,7 @@ int asCScriptObject::CopyFrom(asIScriptObject *other) *this = *(asCScriptObject*)other; - return 0; + return asSUCCESS; } void *asCScriptObject::AllocateUninitializedObject(asCObjectType *in_objType, asCScriptEngine *engine) @@ -1089,19 +1098,19 @@ void asCScriptObject::FreeObject(void *ptr, asCObjectType *in_objType, asCScript } } -void asCScriptObject::CopyObject(void *src, void *dst, asCObjectType *in_objType, asCScriptEngine *engine) +void asCScriptObject::CopyObject(const void *src, void *dst, asCObjectType *in_objType, asCScriptEngine *engine) { int funcIndex = in_objType->beh.copy; if( funcIndex ) { asCScriptFunction *func = engine->scriptFunctions[in_objType->beh.copy]; if( func->funcType == asFUNC_SYSTEM ) - engine->CallObjectMethod(dst, src, funcIndex); + engine->CallObjectMethod(dst, const_cast(src), funcIndex); else { // Call the script class' opAssign method asASSERT(in_objType->flags & asOBJ_SCRIPT_OBJECT ); - reinterpret_cast(dst)->CopyFrom(reinterpret_cast(src)); + reinterpret_cast(dst)->CopyFrom(reinterpret_cast(src)); } } else if( in_objType->size && (in_objType->flags & asOBJ_POD) ) diff --git a/server/src/angelscript/source/as_scriptobject.h b/server/src/angelscript/source/as_scriptobject.h index cf6e134..ca30993 100644 --- a/server/src/angelscript/source/as_scriptobject.h +++ b/server/src/angelscript/source/as_scriptobject.h @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2018 Andreas Jonsson + Copyright (c) 2003-2019 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 @@ -94,7 +94,7 @@ public: // Miscellaneous asIScriptEngine *GetEngine() const; - int CopyFrom(asIScriptObject *other); + int CopyFrom(const asIScriptObject *other); // User data void *SetUserData(void *data, asPWORD type = 0); @@ -119,8 +119,9 @@ public: // Used for properties void *AllocateUninitializedObject(asCObjectType *objType, asCScriptEngine *engine); void FreeObject(void *ptr, asCObjectType *objType, asCScriptEngine *engine); - void CopyObject(void *src, void *dst, asCObjectType *objType, asCScriptEngine *engine); + void CopyObject(const void *src, void *dst, asCObjectType *objType, asCScriptEngine *engine); void CopyHandle(asPWORD *src, asPWORD *dst, asCObjectType *objType, asCScriptEngine *engine); + int CopyFromAs(const asCScriptObject *other, asCObjectType *objType); void CallDestructor(); diff --git a/server/src/angelscript/source/as_symboltable.h b/server/src/angelscript/source/as_symboltable.h index 86babed..64aa6cc 100644 --- a/server/src/angelscript/source/as_symboltable.h +++ b/server/src/angelscript/source/as_symboltable.h @@ -141,7 +141,7 @@ public: private: // Don't allow assignment - asCSymbolTable& operator=(const asCSymbolTable &) { return *this; } + asCSymbolTable& operator=(const asCSymbolTable &other) { return *this; } friend class asCSymbolTableIterator; friend class asCSymbolTableIterator; diff --git a/server/src/angelscript/source/as_typeinfo.cpp b/server/src/angelscript/source/as_typeinfo.cpp index 3f6124e..469f856 100644 --- a/server/src/angelscript/source/as_typeinfo.cpp +++ b/server/src/angelscript/source/as_typeinfo.cpp @@ -1,6 +1,6 @@ /* AngelCode Scripting Library - Copyright (c) 2003-2017 Andreas Jonsson + Copyright (c) 2003-2020 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 @@ -416,7 +416,8 @@ asCFuncdefType::asCFuncdefType(asCScriptEngine *en, asCScriptFunction *func) : a asASSERT(func->funcdefType == 0); // A function pointer is special kind of reference type - flags = asOBJ_REF | asOBJ_FUNCDEF | (func->IsShared() ? asOBJ_SHARED : 0); + // It must be possible to garbage collect, as funcdefs can form circular references if used as delegates + flags = asOBJ_REF | asOBJ_GC | asOBJ_FUNCDEF | (func->IsShared() ? asOBJ_SHARED : 0); name = func->name; nameSpace = func->nameSpace; module = func->module; diff --git a/server/src/server.ts b/server/src/server.ts index 7953edd..bde2166 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -57,7 +57,6 @@ function registerFiles(directoryName: string) { const filepath = directoryName + path.sep + file; var uri = "file://" + filepath; if (!allFiles.get(uri)) { - connection.console.log("Loaded new file at uri " + uri); let td = TextDocument.create(uri, "Angelscript", 0, fs.readFileSync(filepath, 'utf8')); allFiles.set(uri, td); } @@ -168,9 +167,9 @@ function loadScript(textDocument: TextDocument): void { async function validateBuild(): Promise { var r = database.build(); if (r < -1) { - connection.console.log(r.toString()); + console.log(r.toString()); } - connection.console.log("Building"); + console.log("Building"); var messages = database.messages(); let diagnostics: Map = new Map();