Update to angelscript 2.35

This commit is contained in:
Deukhoofd 2021-08-30 10:50:47 +02:00
parent 18e71dfe13
commit fac54acbc9
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
34 changed files with 2187 additions and 1072 deletions

View File

@ -18,6 +18,6 @@
"vscode-languageserver-textdocument": "^1.0.1" "vscode-languageserver-textdocument": "^1.0.1"
}, },
"scripts": { "scripts": {
"install": "cmake-js compile -d src -O build" "install": "cmake-js compile -d src -O build; tsc"
} }
} }

View File

@ -3,6 +3,7 @@ cmake_policy(SET CMP0042 NEW)
project(aslsp-native) project(aslsp-native)
set (CMAKE_CXX_STANDARD 20) set (CMAKE_CXX_STANDARD 20)
set(BUILD_SHARED_LIBS OFF)
include_directories(${CMAKE_JS_INC} angelscript/include) include_directories(${CMAKE_JS_INC} angelscript/include)
message(info ${CMAKE_JS_INC}) message(info ${CMAKE_JS_INC})

View File

@ -4,6 +4,7 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> // sprintf #include <stdio.h> // sprintf
#include <string> #include <string>
#include <algorithm> // std::sort
#include "scriptarray.h" #include "scriptarray.h"
@ -998,7 +999,7 @@ void CScriptArray::Destruct(SArrayBuffer *buf, asUINT start, asUINT end)
// internal // 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 ) if( !asc )
{ {
@ -1027,42 +1028,6 @@ bool CScriptArray::Less(const void *a, const void *b, bool asc, asIScriptContext
#undef COMPARE #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; return false;
} }
@ -1475,12 +1440,11 @@ void CScriptArray::Sort(asUINT startAt, asUINT count, bool asc)
return; return;
} }
asBYTE tmp[16];
asIScriptContext *cmpContext = 0;
bool isNested = false;
if( subTypeId & ~asTYPEID_MASK_SEQNBR ) if( subTypeId & ~asTYPEID_MASK_SEQNBR )
{ {
asIScriptContext *cmpContext = 0;
bool isNested = false;
// Try to reuse the active context // Try to reuse the active context
cmpContext = asGetActiveContext(); cmpContext = asGetActiveContext();
if( cmpContext ) if( cmpContext )
@ -1491,38 +1455,83 @@ void CScriptArray::Sort(asUINT startAt, asUINT count, bool asc)
cmpContext = 0; cmpContext = 0;
} }
if( cmpContext == 0 ) if( cmpContext == 0 )
{
cmpContext = objType->GetEngine()->RequestContext(); 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);
} }
} }
else
// Insertion sort
for( int i = start + 1; i < end; i++ )
{ {
Copy(tmp, GetArrayItemPointer(i)); // TODO: Use std::sort for primitive types too
int j = i - 1; // Insertion sort
asBYTE tmp[16];
while( j >= start && Less(GetDataPointer(tmp), At(j), asc, cmpContext, cache) ) for( int i = start + 1; i < end; i++ )
{ {
Copy(GetArrayItemPointer(j + 1), GetArrayItemPointer(j)); Copy(tmp, GetArrayItemPointer(i));
j--;
}
Copy(GetArrayItemPointer(j + 1), tmp); int j = i - 1;
}
if( cmpContext ) while( j >= start && Less(GetDataPointer(tmp), At(j), asc) )
{ {
if( isNested ) Copy(GetArrayItemPointer(j + 1), GetArrayItemPointer(j));
{ j--;
asEContextState state = cmpContext->GetState(); }
cmpContext->PopState();
if( state == asEXECUTION_ABORTED ) Copy(GetArrayItemPointer(j + 1), tmp);
cmpContext->Abort();
} }
else
objType->GetEngine()->ReturnContext(cmpContext);
} }
} }
@ -1550,7 +1559,6 @@ void CScriptArray::Sort(asIScriptFunction *func, asUINT startAt, asUINT count)
return; return;
} }
asBYTE tmp[16];
asIScriptContext *cmpContext = 0; asIScriptContext *cmpContext = 0;
bool isNested = false; bool isNested = false;
@ -1567,6 +1575,7 @@ void CScriptArray::Sort(asIScriptFunction *func, asUINT startAt, asUINT count)
cmpContext = objType->GetEngine()->RequestContext(); cmpContext = objType->GetEngine()->RequestContext();
// Insertion sort // Insertion sort
asBYTE tmp[16];
for (asUINT i = start + 1; i < end; i++) for (asUINT i = start + 1; i < end; i++)
{ {
Copy(tmp, GetArrayItemPointer(i)); Copy(tmp, GetArrayItemPointer(i));

View File

@ -120,7 +120,7 @@ protected:
CScriptArray(const CScriptArray &other); CScriptArray(const CScriptArray &other);
virtual ~CScriptArray(); 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 *GetArrayItemPointer(int index);
void *GetDataPointer(void *buffer); void *GetDataPointer(void *buffer);
void Copy(void *dst, void *src); void Copy(void *dst, void *src);

View File

@ -14,6 +14,8 @@
// TODO: Implement flags for turning on/off include directives and conditional programming // TODO: Implement flags for turning on/off include directives and conditional programming
//--------------------------- //---------------------------
// Declaration // Declaration
// //
@ -23,9 +25,10 @@
#include <angelscript.h> #include <angelscript.h>
#endif #endif
#if defined(_MSC_VER) && _MSC_VER <= 1200 #if defined(_MSC_VER) && _MSC_VER <= 1200
// disable the annoying warnings on MSVC 6 // disable the annoying warnings on MSVC 6
#pragma warning(disable : 4786) #pragma warning (disable:4786)
#endif #endif
#include <string> #include <string>
@ -197,7 +200,7 @@ protected:
{ {
bool operator()(const std::string &a, const std::string &b) const 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<std::string, ci_less> includedScripts; std::set<std::string, ci_less> includedScripts;

View File

@ -1,367 +1,360 @@
#include "scripthandle.h" #include "scripthandle.h"
#include <assert.h>
#include <new> #include <new>
#include <assert.h>
#include <string.h> #include <string.h>
BEGIN_AS_NAMESPACE BEGIN_AS_NAMESPACE
static void Construct(CScriptHandle* self) { new (self) CScriptHandle(); } 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, const CScriptHandle &o) { new(self) CScriptHandle(o); }
// This one is not static because it needs to be friend with the CScriptHandle class // 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); } void Construct(CScriptHandle *self, void *ref, int typeId) { new(self) CScriptHandle(ref, typeId); }
static void Destruct(CScriptHandle* self) { self->~CScriptHandle(); } static void Destruct(CScriptHandle *self) { self->~CScriptHandle(); }
CScriptHandle::CScriptHandle() { CScriptHandle::CScriptHandle()
m_ref = 0; {
m_type = 0; m_ref = 0;
m_type = 0;
} }
CScriptHandle::CScriptHandle(const CScriptHandle& other) { CScriptHandle::CScriptHandle(const CScriptHandle &other)
m_ref = other.m_ref; {
m_type = other.m_type; m_ref = other.m_ref;
m_type = other.m_type;
AddRefHandle(); AddRefHandle();
} }
CScriptHandle::CScriptHandle(void* ref, asITypeInfo* type) { CScriptHandle::CScriptHandle(void *ref, asITypeInfo *type)
m_ref = ref; {
m_type = 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 // directly as it requires an active script context
CScriptHandle::CScriptHandle(void* ref, int typeId) { CScriptHandle::CScriptHandle(void *ref, int typeId)
m_ref = 0; {
m_type = 0; m_ref = 0;
m_type = 0;
Assign(ref, typeId); Assign(ref, typeId);
} }
CScriptHandle::~CScriptHandle() { ReleaseHandle(); } CScriptHandle::~CScriptHandle()
{
void CScriptHandle::ReleaseHandle() { 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;
}
} }
void CScriptHandle::AddRefHandle() { void CScriptHandle::ReleaseHandle()
if (m_ref && m_type) { {
asIScriptEngine* engine = m_type->GetEngine(); if( m_ref && m_type )
engine->AddRefScriptObject(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 engine->Release();
// a reference to a script object is still held
engine->AddRef(); m_ref = 0;
} m_type = 0;
}
} }
CScriptHandle& CScriptHandle::operator=(const CScriptHandle& other) { void CScriptHandle::AddRefHandle()
Set(other.m_ref, other.m_type); {
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) { CScriptHandle &CScriptHandle::operator =(const CScriptHandle &other)
if (m_ref == ref) {
return; Set(other.m_ref, other.m_type);
ReleaseHandle(); return *this;
m_ref = ref;
m_type = type;
AddRefHandle();
} }
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 { m_ref = ref;
if (m_type == 0) m_type = type;
return 0;
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 // directly as it requires an active script context
CScriptHandle& CScriptHandle::Assign(void* ref, int typeId) { CScriptHandle &CScriptHandle::Assign(void *ref, int typeId)
// When receiving a null handle we just clear our memory {
if (typeId == 0) { // When receiving a null handle we just clear our memory
Set(0, 0); if( typeId == 0 )
return *this; {
} Set(0, 0);
return *this;
}
// Dereference received handles to get the object // Dereference received handles to get the object
if (typeId & asTYPEID_OBJHANDLE) { if( typeId & asTYPEID_OBJHANDLE )
// Store the actual reference {
ref = *(void**)ref; // Store the actual reference
typeId &= ~asTYPEID_OBJHANDLE; ref = *(void**)ref;
} typeId &= ~asTYPEID_OBJHANDLE;
}
// Get the object type // Get the object type
asIScriptContext* ctx = asGetActiveContext(); asIScriptContext *ctx = asGetActiveContext();
asIScriptEngine* engine = ctx->GetEngine(); asIScriptEngine *engine = ctx->GetEngine();
asITypeInfo* type = engine->GetTypeInfoById(typeId); asITypeInfo *type = engine->GetTypeInfoById(typeId);
// If the argument is another CScriptHandle, we should copy the content instead // If the argument is another CScriptHandle, we should copy the content instead
if (type && strcmp(type->GetName(), "ref") == 0) { if( type && strcmp(type->GetName(), "ref") == 0 )
CScriptHandle* r = (CScriptHandle*)ref; {
ref = r->m_ref; CScriptHandle *r = (CScriptHandle*)ref;
type = r->m_type; 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 { bool CScriptHandle::operator==(const CScriptHandle &o) const
if (m_ref == o.m_ref && m_type == o.m_type) {
return true; 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, // TODO: If type is not the same, we should attempt to do a dynamic cast,
// which may change the pointer for application registered classes // 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 { bool CScriptHandle::Equals(void *ref, int typeId) const
// Null handles are received as reference to a null handle {
if (typeId == 0) // Null handles are received as reference to a null handle
ref = 0; if( typeId == 0 )
ref = 0;
// Dereference handles to get the object // Dereference handles to get the object
if (typeId & asTYPEID_OBJHANDLE) { if( typeId & asTYPEID_OBJHANDLE )
// Compare the actual reference {
ref = *(void**)ref; // Compare the actual reference
typeId &= ~asTYPEID_OBJHANDLE; ref = *(void**)ref;
} typeId &= ~asTYPEID_OBJHANDLE;
}
// TODO: If typeId is not the same, we should attempt to do a dynamic cast, // TODO: If typeId is not the same, we should attempt to do a dynamic cast,
// which may change the pointer for application registered classes // which may change the pointer for application registered classes
if (ref == m_ref) if( ref == m_ref ) return true;
return true;
return false; return false;
} }
// AngelScript: used as '@obj = cast<obj>(ref);' // AngelScript: used as '@obj = cast<obj>(ref);'
void CScriptHandle::Cast(void** outRef, int typeId) { void CScriptHandle::Cast(void **outRef, int typeId)
// If we hold a null handle, then just return null {
if (m_type == 0) { // If we hold a null handle, then just return null
*outRef = 0; if( m_type == 0 )
return; {
} *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 // Compare the type id of the actual object
assert(typeId & asTYPEID_OBJHANDLE); typeId &= ~asTYPEID_OBJHANDLE;
asIScriptEngine *engine = m_type->GetEngine();
asITypeInfo *type = engine->GetTypeInfoById(typeId);
// Compare the type id of the actual object *outRef = 0;
typeId &= ~asTYPEID_OBJHANDLE;
asIScriptEngine* engine = m_type->GetEngine();
asITypeInfo* type = engine->GetTypeInfoById(typeId);
*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) { void CScriptHandle::EnumReferences(asIScriptEngine *inEngine)
// If we're holding a reference, we'll notify the garbage collector of it {
if (m_ref) // If we're holding a reference, we'll notify the garbage collector of it
inEngine->GCEnumCallback(m_ref); if (m_ref)
inEngine->GCEnumCallback(m_ref);
// The object type itself is also garbage collected // The object type itself is also garbage collected
if (m_type) if( m_type)
inEngine->GCEnumCallback(m_type); inEngine->GCEnumCallback(m_type);
} }
void CScriptHandle::ReleaseReferences(asIScriptEngine*) { void CScriptHandle::ReleaseReferences(asIScriptEngine *inEngine)
// Simply clear the content to release the references {
Set(0, 0); // Simply clear the content to release the references
Set(0, 0);
} }
void RegisterScriptHandle_Native(asIScriptEngine* engine) { void RegisterScriptHandle_Native(asIScriptEngine *engine)
[[maybe_unused]] int r; {
int r;
#if AS_CAN_USE_CPP11 #if AS_CAN_USE_CPP11
// With C++11 it is possible to use asGetTypeTraits to automatically determine the flags that represent the C++ // With C++11 it is possible to use asGetTypeTraits to automatically determine the flags that represent the C++ class
// class r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asGetTypeTraits<CScriptHandle>()); assert( r >= 0 );
r = engine->RegisterObjectType("ref", sizeof(CScriptHandle),
asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asGetTypeTraits<CScriptHandle>());
assert(r >= 0);
#else #else
r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK); assert( r >= 0 );
asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK);
assert(r >= 0);
#endif #endif
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", asFUNCTIONPR(Construct, (CScriptHandle *), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
asFUNCTIONPR(Construct, (CScriptHandle*), void), asCALL_CDECL_OBJFIRST); r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ref &in)", asFUNCTIONPR(Construct, (CScriptHandle *, const CScriptHandle &), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
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_CONSTRUCT, "void f(const ref &in)", r = engine->RegisterObjectBehaviour("ref", asBEHAVE_DESTRUCT, "void f()", asFUNCTIONPR(Destruct, (CScriptHandle *), void), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
asFUNCTIONPR(Construct, (CScriptHandle*, const CScriptHandle&), void), r = engine->RegisterObjectBehaviour("ref", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(CScriptHandle,EnumReferences), asCALL_THISCALL); assert(r >= 0);
asCALL_CDECL_OBJFIRST); r = engine->RegisterObjectBehaviour("ref", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(CScriptHandle, ReleaseReferences), asCALL_THISCALL); assert(r >= 0);
assert(r >= 0); r = engine->RegisterObjectMethod("ref", "void opCast(?&out)", asMETHODPR(CScriptHandle, Cast, (void **, int), void), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ref &in)", asMETHOD(CScriptHandle, operator=), asCALL_THISCALL); assert( r >= 0 );
asFUNCTIONPR(Construct, (CScriptHandle*, void*, int), void), r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ?&in)", asMETHOD(CScriptHandle, Assign), asCALL_THISCALL); assert( r >= 0 );
asCALL_CDECL_OBJFIRST); r = engine->RegisterObjectMethod("ref", "bool opEquals(const ref &in) const", asMETHODPR(CScriptHandle, operator==, (const CScriptHandle &) const, bool), asCALL_THISCALL); assert( r >= 0 );
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_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) { void CScriptHandle_Construct_Generic(asIScriptGeneric *gen)
CScriptHandle* self = reinterpret_cast<CScriptHandle*>(gen->GetObject()); {
new (self) CScriptHandle(); CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
new(self) CScriptHandle();
} }
void CScriptHandle_ConstructCopy_Generic(asIScriptGeneric* gen) { void CScriptHandle_ConstructCopy_Generic(asIScriptGeneric *gen)
CScriptHandle* other = reinterpret_cast<CScriptHandle*>(gen->GetArgAddress(0)); {
CScriptHandle* self = reinterpret_cast<CScriptHandle*>(gen->GetObject()); CScriptHandle *other = reinterpret_cast<CScriptHandle*>(gen->GetArgAddress(0));
new (self) CScriptHandle(*other); CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
new(self) CScriptHandle(*other);
} }
void CScriptHandle_ConstructVar_Generic(asIScriptGeneric* gen) { void CScriptHandle_ConstructVar_Generic(asIScriptGeneric *gen)
void* ref = gen->GetArgAddress(0); {
int typeId = gen->GetArgTypeId(0); void *ref = gen->GetArgAddress(0);
CScriptHandle* self = reinterpret_cast<CScriptHandle*>(gen->GetObject()); int typeId = gen->GetArgTypeId(0);
Construct(self, ref, typeId); CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
Construct(self, ref, typeId);
} }
void CScriptHandle_Destruct_Generic(asIScriptGeneric* gen) { void CScriptHandle_Destruct_Generic(asIScriptGeneric *gen)
CScriptHandle* self = reinterpret_cast<CScriptHandle*>(gen->GetObject()); {
self->~CScriptHandle(); CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
self->~CScriptHandle();
} }
void CScriptHandle_Cast_Generic(asIScriptGeneric* gen) { void CScriptHandle_Cast_Generic(asIScriptGeneric *gen)
void** ref = reinterpret_cast<void**>(gen->GetArgAddress(0)); {
int typeId = gen->GetArgTypeId(0); void **ref = reinterpret_cast<void**>(gen->GetArgAddress(0));
CScriptHandle* self = reinterpret_cast<CScriptHandle*>(gen->GetObject()); int typeId = gen->GetArgTypeId(0);
self->Cast(ref, typeId); CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
self->Cast(ref, typeId);
} }
void CScriptHandle_Assign_Generic(asIScriptGeneric* gen) { void CScriptHandle_Assign_Generic(asIScriptGeneric *gen)
CScriptHandle* other = reinterpret_cast<CScriptHandle*>(gen->GetArgAddress(0)); {
CScriptHandle* self = reinterpret_cast<CScriptHandle*>(gen->GetObject()); CScriptHandle *other = reinterpret_cast<CScriptHandle*>(gen->GetArgAddress(0));
*self = *other; CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
gen->SetReturnAddress(self); *self = *other;
gen->SetReturnAddress(self);
} }
void CScriptHandle_AssignVar_Generic(asIScriptGeneric* gen) { void CScriptHandle_AssignVar_Generic(asIScriptGeneric *gen)
void* ref = gen->GetArgAddress(0); {
int typeId = gen->GetArgTypeId(0); void *ref = gen->GetArgAddress(0);
CScriptHandle* self = reinterpret_cast<CScriptHandle*>(gen->GetObject()); int typeId = gen->GetArgTypeId(0);
self->Assign(ref, typeId); CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
gen->SetReturnAddress(self); self->Assign(ref, typeId);
gen->SetReturnAddress(self);
} }
void CScriptHandle_Equals_Generic(asIScriptGeneric* gen) { void CScriptHandle_Equals_Generic(asIScriptGeneric *gen)
CScriptHandle* other = reinterpret_cast<CScriptHandle*>(gen->GetArgAddress(0)); {
CScriptHandle* self = reinterpret_cast<CScriptHandle*>(gen->GetObject()); CScriptHandle *other = reinterpret_cast<CScriptHandle*>(gen->GetArgAddress(0));
gen->SetReturnByte(*self == *other); CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
gen->SetReturnByte(*self == *other);
} }
void CScriptHandle_EqualsVar_Generic(asIScriptGeneric* gen) { void CScriptHandle_EqualsVar_Generic(asIScriptGeneric *gen)
void* ref = gen->GetArgAddress(0); {
int typeId = gen->GetArgTypeId(0); void *ref = gen->GetArgAddress(0);
CScriptHandle* self = reinterpret_cast<CScriptHandle*>(gen->GetObject()); int typeId = gen->GetArgTypeId(0);
gen->SetReturnByte(self->Equals(ref, typeId)); CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
gen->SetReturnByte(self->Equals(ref, typeId));
} }
void CScriptHandle_EnumReferences_Generic(asIScriptGeneric* gen) { void CScriptHandle_EnumReferences_Generic(asIScriptGeneric *gen)
CScriptHandle* self = reinterpret_cast<CScriptHandle*>(gen->GetObject()); {
self->EnumReferences(gen->GetEngine()); CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
self->EnumReferences(gen->GetEngine());
} }
void CScriptHandle_ReleaseReferences_Generic(asIScriptGeneric* gen) { void CScriptHandle_ReleaseReferences_Generic(asIScriptGeneric *gen)
CScriptHandle* self = reinterpret_cast<CScriptHandle*>(gen->GetObject()); {
self->ReleaseReferences(gen->GetEngine()); CScriptHandle *self = reinterpret_cast<CScriptHandle*>(gen->GetObject());
self->ReleaseReferences(gen->GetEngine());
} }
void RegisterScriptHandle_Generic(asIScriptEngine* engine) { void RegisterScriptHandle_Generic(asIScriptEngine *engine)
[[maybe_unused]] int r; {
int r;
r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), r = engine->RegisterObjectType("ref", sizeof(CScriptHandle), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK); assert( r >= 0 );
asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_GC | asOBJ_APP_CLASS_CDAK); r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(CScriptHandle_Construct_Generic), asCALL_GENERIC); assert( r >= 0 );
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()", r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", asFUNCTION(CScriptHandle_ConstructVar_Generic), asCALL_GENERIC); assert( r >= 0 );
asFUNCTION(CScriptHandle_Construct_Generic), asCALL_GENERIC); r = engine->RegisterObjectBehaviour("ref", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(CScriptHandle_Destruct_Generic), asCALL_GENERIC); assert( r >= 0 );
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_CONSTRUCT, "void f(const ref &in)", r = engine->RegisterObjectBehaviour("ref", asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(CScriptHandle_ReleaseReferences_Generic), asCALL_GENERIC); assert(r >= 0);
asFUNCTION(CScriptHandle_ConstructCopy_Generic), asCALL_GENERIC); r = engine->RegisterObjectMethod("ref", "void opCast(?&out)", asFUNCTION(CScriptHandle_Cast_Generic), asCALL_GENERIC); assert( r >= 0 );
assert(r >= 0); r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ref &in)", asFUNCTION(CScriptHandle_Assign_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("ref", asBEHAVE_CONSTRUCT, "void f(const ?&in)", r = engine->RegisterObjectMethod("ref", "ref &opHndlAssign(const ?&in)", asFUNCTION(CScriptHandle_AssignVar_Generic), asCALL_GENERIC); assert( r >= 0 );
asFUNCTION(CScriptHandle_ConstructVar_Generic), asCALL_GENERIC); r = engine->RegisterObjectMethod("ref", "bool opEquals(const ref &in) const", asFUNCTION(CScriptHandle_Equals_Generic), asCALL_GENERIC); assert( r >= 0 );
assert(r >= 0); r = engine->RegisterObjectMethod("ref", "bool opEquals(const ?&in) const", asFUNCTION(CScriptHandle_EqualsVar_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) { void RegisterScriptHandle(asIScriptEngine *engine)
if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY")) {
RegisterScriptHandle_Generic(engine); if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
else RegisterScriptHandle_Generic(engine);
RegisterScriptHandle_Native(engine); else
RegisterScriptHandle_Native(engine);
} }
END_AS_NAMESPACE END_AS_NAMESPACE

View File

@ -975,8 +975,7 @@ string ScriptGetExceptionInfo()
void RegisterExceptionRoutines(asIScriptEngine *engine) void RegisterExceptionRoutines(asIScriptEngine *engine)
{ {
[[maybe_unused]] int r;
int r;
// The string type must be available // The string type must be available
assert(engine->GetTypeInfoByDecl("string")); assert(engine->GetTypeInfoByDecl("string"));

View File

@ -28,25 +28,26 @@ typedef map<string, int> map_t;
END_AS_NAMESPACE END_AS_NAMESPACE
#endif #endif
BEGIN_AS_NAMESPACE
class CStdStringFactory : public asIStringFactory class CStdStringFactory : public asIStringFactory
{ {
public: public:
CStdStringFactory() = default; CStdStringFactory() {}
~CStdStringFactory() override ~CStdStringFactory()
{ {
// The script engine must release each string // The script engine must release each string
// constant that it has requested // 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 // The string factory might be modified from multiple
// threads, so it is necessary to use a mutex. // threads, so it is necessary to use a mutex.
asAcquireExclusiveLock(); asAcquireExclusiveLock();
string str(data, length); string str(data, length);
auto it = stringCache.find(str); map_t::iterator it = stringCache.find(str);
if (it != stringCache.end()) if (it != stringCache.end())
it->second++; it->second++;
else else
@ -57,9 +58,9 @@ public:
return reinterpret_cast<const void*>(&it->first); return reinterpret_cast<const void*>(&it->first);
} }
int ReleaseStringConstant(const void *str) override int ReleaseStringConstant(const void *str)
{ {
if (str == nullptr) if (str == 0)
return asERROR; return asERROR;
int ret = asSUCCESS; int ret = asSUCCESS;
@ -68,7 +69,7 @@ public:
// threads, so it is necessary to use a mutex. // threads, so it is necessary to use a mutex.
asAcquireExclusiveLock(); asAcquireExclusiveLock();
auto it = stringCache.find(*reinterpret_cast<const string*>(str)); map_t::iterator it = stringCache.find(*reinterpret_cast<const string*>(str));
if (it == stringCache.end()) if (it == stringCache.end())
ret = asERROR; ret = asERROR;
else else
@ -83,9 +84,9 @@ public:
return ret; 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; return asERROR;
if (length) if (length)
@ -98,17 +99,17 @@ public:
} }
// THe access to the string cache is protected with the common mutex provided by AngelScript // 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 // TODO: Make this public so the application can also use the string
// factory and share the string constants if so desired, or to // factory and share the string constants if so desired, or to
// monitor the size of the string factory cache. // monitor the size of the string factory cache.
CStdStringFactory *GetStdStringFactorySingleton() CStdStringFactory *GetStdStringFactorySingleton()
{ {
if( stringFactory == nullptr ) if( stringFactory == 0 )
{ {
// The following instance will be destroyed by the global // The following instance will be destroyed by the global
// CStdStringFactoryCleaner instance upon application shutdown // CStdStringFactoryCleaner instance upon application shutdown
@ -122,7 +123,7 @@ class CStdStringFactoryCleaner
public: public:
~CStdStringFactoryCleaner() ~CStdStringFactoryCleaner()
{ {
if (stringFactory != nullptr) if (stringFactory)
{ {
// Only delete the string factory if the stringCache is empty // Only delete the string factory if the stringCache is empty
// If it is not empty, it means that someone might still attempt // If it is not empty, it means that someone might still attempt
@ -133,13 +134,13 @@ public:
if (stringFactory->stringCache.empty()) if (stringFactory->stringCache.empty())
{ {
delete stringFactory; delete stringFactory;
stringFactory = nullptr; stringFactory = 0;
} }
} }
} }
}; };
static CStdStringFactoryCleaner cleaner = {}; static CStdStringFactoryCleaner cleaner;
static void ConstructString(string *thisPointer) 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) // string formatInt(int64 val, const string &in options, uint width)
static string formatInt(asINT64 value, const string &options, asUINT width) static string formatInt(asINT64 value, const string &options, asUINT width)
{ {
bool leftJustify = options.find('l') != string::npos; bool leftJustify = options.find("l") != string::npos;
bool padWithZero = options.find('0') != string::npos; bool padWithZero = options.find("0") != string::npos;
bool alwaysSign = options.find('+') != string::npos; bool alwaysSign = options.find("+") != string::npos;
bool spaceOnSign = options.find(' ') != string::npos; bool spaceOnSign = options.find(" ") != string::npos;
bool hexSmall = options.find('h') != string::npos; bool hexSmall = options.find("h") != string::npos;
bool hexLarge = options.find('H') != string::npos; bool hexLarge = options.find("H") != string::npos;
string fmt = "%"; string fmt = "%";
if( leftJustify ) 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) // string formatUInt(uint64 val, const string &in options, uint width)
static string formatUInt(asQWORD value, const string &options, asUINT width) static string formatUInt(asQWORD value, const string &options, asUINT width)
{ {
bool leftJustify = options.find('l') != string::npos; bool leftJustify = options.find("l") != string::npos;
bool padWithZero = options.find('0') != string::npos; bool padWithZero = options.find("0") != string::npos;
bool alwaysSign = options.find('+') != string::npos; bool alwaysSign = options.find("+") != string::npos;
bool spaceOnSign = options.find(' ') != string::npos; bool spaceOnSign = options.find(" ") != string::npos;
bool hexSmall = options.find('h') != string::npos; bool hexSmall = options.find("h") != string::npos;
bool hexLarge = options.find('H') != string::npos; bool hexLarge = options.find("H") != string::npos;
string fmt = "%"; string fmt = "%";
if( leftJustify ) 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) // string formatFloat(double val, const string &in options, uint width, uint precision)
static string formatFloat(double value, const string &options, asUINT width, asUINT precision) static string formatFloat(double value, const string &options, asUINT width, asUINT precision)
{ {
bool leftJustify = options.find('l') != string::npos; bool leftJustify = options.find("l") != string::npos;
bool padWithZero = options.find('0') != string::npos; bool padWithZero = options.find("0") != string::npos;
bool alwaysSign = options.find('+') != string::npos; bool alwaysSign = options.find("+") != string::npos;
bool spaceOnSign = options.find(' ') != string::npos; bool spaceOnSign = options.find(" ") != string::npos;
bool expSmall = options.find('e') != string::npos; bool expSmall = options.find("e") != string::npos;
bool expLarge = options.find('E') != string::npos; bool expLarge = options.find("E") != string::npos;
string fmt = "%"; string fmt = "%";
if( leftJustify ) 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. // makro, so this wrapper was introduced as work around.
static bool StringEquals(const std::string& lhs, const std::string& rhs) static bool StringEquals(const std::string& lhs, const std::string& rhs)
{ {
return lhs == rhs; return lhs == rhs;
} }
void RegisterStdString_Native(asIScriptEngine *engine) void RegisterStdString_Native(asIScriptEngine *engine)

View File

@ -112,8 +112,7 @@ static void StringJoin_Generic(asIScriptGeneric *gen)
// The string type must have been registered first. // The string type must have been registered first.
void RegisterStdStringUtils(asIScriptEngine *engine) void RegisterStdStringUtils(asIScriptEngine *engine)
{ {
[[maybe_unused]] int r;
int r;
if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
{ {

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any warranty. In no event will the authors be held liable for any
@ -58,8 +58,8 @@ BEGIN_AS_NAMESPACE
// AngelScript version // AngelScript version
#define ANGELSCRIPT_VERSION 23400 #define ANGELSCRIPT_VERSION 23500
#define ANGELSCRIPT_VERSION_STRING "2.34.0" #define ANGELSCRIPT_VERSION_STRING "2.35.0"
// Data types // Data types
@ -195,6 +195,7 @@ enum asEObjTypeFlags
asOBJ_APP_CLASS_A = (asOBJ_APP_CLASS + asOBJ_APP_CLASS_ASSIGNMENT), 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_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_K = (asOBJ_APP_CLASS + asOBJ_APP_CLASS_COPY_CONSTRUCTOR),
asOBJ_APP_CLASS_MORE_CONSTRUCTORS = (1<<31),
asOBJ_APP_PRIMITIVE = (1<<13), asOBJ_APP_PRIMITIVE = (1<<13),
asOBJ_APP_FLOAT = (1<<14), asOBJ_APP_FLOAT = (1<<14),
asOBJ_APP_ARRAY = (1<<15), asOBJ_APP_ARRAY = (1<<15),
@ -203,7 +204,7 @@ enum asEObjTypeFlags
asOBJ_NOCOUNT = (1<<18), asOBJ_NOCOUNT = (1<<18),
asOBJ_APP_CLASS_ALIGN8 = (1<<19), asOBJ_APP_CLASS_ALIGN8 = (1<<19),
asOBJ_IMPLICIT_HANDLE = (1<<20), asOBJ_IMPLICIT_HANDLE = (1<<20),
asOBJ_MASK_VALID_FLAGS = 0x1FFFFF, asOBJ_MASK_VALID_FLAGS = 0x801FFFFF,
// Internal flags // Internal flags
asOBJ_SCRIPT_OBJECT = (1<<21), asOBJ_SCRIPT_OBJECT = (1<<21),
asOBJ_SHARED = (1<<22), asOBJ_SHARED = (1<<22),
@ -385,7 +386,7 @@ typedef unsigned int asUINT;
#endif #endif
// Is the target a 64bit system? // 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 #ifndef AS_64BIT_PTR
#define AS_64BIT_PTR #define AS_64BIT_PTR
#endif #endif
@ -1015,7 +1016,7 @@ public:
// Miscellaneous // Miscellaneous
virtual asIScriptEngine *GetEngine() const = 0; virtual asIScriptEngine *GetEngine() const = 0;
virtual int CopyFrom(asIScriptObject *other) = 0; virtual int CopyFrom(const asIScriptObject *other) = 0;
// User data // User data
virtual void *SetUserData(void *data, asPWORD type = 0) = 0; virtual void *SetUserData(void *data, asPWORD type = 0) = 0;
@ -1238,7 +1239,7 @@ template <int N>
struct asSMethodPtr struct asSMethodPtr
{ {
template<class M> template<class M>
static asSFuncPtr Convert(M) static asSFuncPtr Convert(M Mthd)
{ {
// This version of the function should never be executed, nor compiled, // 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. // as it would mean that the size of the method pointer cannot be determined.

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any 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 = node->firstChild;
node->DisconnectParent(); node->DisconnectParent();
RegisterGlobalVar(node, script, module->defaultNamespace); RegisterGlobalVar(node, script, module->m_defaultNamespace);
CompileGlobalVariables(); CompileGlobalVariables();
@ -410,10 +410,10 @@ int asCBuilder::CompileGlobalVar(const char *sectionName, const char *code, int
for( asUINT n = 0; n < functions.GetLength(); n++ ) for( asUINT n = 0; n < functions.GetLength(); n++ )
{ {
asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId]; 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->m_globalFunctions.Erase(module->m_globalFunctions.GetIndex(func));
module->scriptFunctions.RemoveValue(func); module->m_scriptFunctions.RemoveValue(func);
func->ReleaseInternal(); func->ReleaseInternal();
} }
} }
@ -552,13 +552,13 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l
if( func == 0 ) if( func == 0 )
return asOUT_OF_MEMORY; 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->id = engine->GetNextScriptFunctionId();
func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : ""); func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
int row, col; int row, col;
scripts[0]->ConvertPosToRowCol(node->tokenPos, &row, &col); scripts[0]->ConvertPosToRowCol(node->tokenPos, &row, &col);
func->scriptData->declaredAt = (row & 0xFFFFF)|((col & 0xFFF)<<20); 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 // Make sure the default args are declared correctly
int r = ValidateDefaultArgs(script, node, func); 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 // Tell the engine that the function exists already so the compiler can access it
if( compileFlags & asCOMP_ADD_TO_MODULE ) 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 ) if( r < 0 )
{ {
func->ReleaseInternal(); func->ReleaseInternal();
return asERROR; return asERROR;
} }
module->globalFunctions.Put(func); module->m_globalFunctions.Put(func);
module->AddScriptFunction(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++ ) for( asUINT n = 0; n < functions.GetLength(); n++ )
{ {
asCScriptFunction *f = engine->scriptFunctions[functions[n]->funcId]; 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->m_globalFunctions.Erase(module->m_globalFunctions.GetIndex(f));
module->scriptFunctions.RemoveValue(f); module->m_scriptFunctions.RemoveValue(f);
f->ReleaseInternal(); f->ReleaseInternal();
} }
} }
@ -1096,7 +1096,7 @@ asCObjectProperty *asCBuilder::GetObjectProperty(asCDataType &obj, const char *p
{ {
if( props[n]->name == prop ) if( props[n]->name == prop )
{ {
if( module->accessMask & props[n]->accessMask ) if( module->m_accessMask & props[n]->accessMask )
return props[n]; return props[n];
else else
return 0; return 0;
@ -1137,7 +1137,7 @@ bool asCBuilder::DoesGlobalPropertyExist(const char *prop, asSNameSpace *ns, asC
// Check previously compiled global variables // Check previously compiled global variables
if( module ) if( module )
{ {
globProp = module->scriptGlobals.GetFirst(ns, prop); globProp = module->m_scriptGlobals.GetFirst(ns, prop);
if( globProp ) if( globProp )
{ {
if( outProp ) *outProp = globProp; if( outProp ) *outProp = globProp;
@ -1172,7 +1172,7 @@ asCGlobalProperty *asCBuilder::GetGlobalProperty(const char *prop, asSNameSpace
if( isAppProp ) if( isAppProp )
{ {
// Don't return the property if the module doesn't have access to it // 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; globProp = 0;
} }
return globProp; return globProp;
@ -1649,7 +1649,7 @@ int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScri
for( n = 0; n < funcDefs.GetLength(); n++ ) for( n = 0; n < funcDefs.GetLength(); n++ )
{ {
if( funcDefs[n]->name == name && if( funcDefs[n]->name == name &&
module->funcDefs[funcDefs[n]->idx]->nameSpace == ns ) module->m_funcDefs[funcDefs[n]->idx]->nameSpace == ns )
{ {
if( code ) if( code )
{ {
@ -1915,7 +1915,7 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
asCArray<asCString *> defaultArgs; asCArray<asCString *> defaultArgs;
asSFunctionTraits funcTraits; asSFunctionTraits funcTraits;
asCFuncdefType *fdt = module->funcDefs[funcDef->idx]; asCFuncdefType *fdt = module->m_funcDefs[funcDef->idx];
asASSERT( fdt ); asASSERT( fdt );
asCScriptFunction *func = fdt->funcdef; asCScriptFunction *func = fdt->funcdef;
@ -1972,7 +1972,7 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
{ {
// Replace our funcdef for the existing one // Replace our funcdef for the existing one
funcDef->idx = fdt2->funcdef->id; funcDef->idx = fdt2->funcdef->id;
module->funcDefs[module->funcDefs.IndexOf(fdt)] = fdt2; module->ReplaceFuncDef(fdt, fdt2);
fdt2->AddRefInternal(); fdt2->AddRefInternal();
engine->funcDefs.RemoveValue(fdt); 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 // Remember if the type was declared as external so the saved bytecode can be flagged accordingly
if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && found) 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) 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 // We'll use the existing type
decl->isExistingShared = true; decl->isExistingShared = true;
decl->typeInfo = st; decl->typeInfo = st;
module->classTypes.PushLast(st); module->AddClassType(st);
st->AddRefInternal(); st->AddRefInternal();
break; 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 // Remember if the class was declared as external so the saved bytecode can be flagged accordingly
if (isExternal) if (isExternal)
module->externalTypes.PushLast(st); module->m_externalTypes.PushLast(st);
if (!decl->isExistingShared) if (!decl->isExistingShared)
{ {
@ -2310,7 +2310,7 @@ int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameS
st->name = name; st->name = name;
st->nameSpace = ns; st->nameSpace = ns;
st->module = module; st->module = module;
module->classTypes.PushLast(st); module->AddClassType(st);
if (isShared) if (isShared)
{ {
engine->sharedScriptTypes.PushLast(st); engine->sharedScriptTypes.PushLast(st);
@ -2429,12 +2429,12 @@ int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSN
// We'll use the existing type // We'll use the existing type
decl->isExistingShared = true; decl->isExistingShared = true;
decl->typeInfo = st; decl->typeInfo = st;
module->classTypes.PushLast(st); module->AddClassType(st);
st->AddRefInternal(); st->AddRefInternal();
// Remember if the interface was declared as external so the saved bytecode can be flagged accordingly // Remember if the interface was declared as external so the saved bytecode can be flagged accordingly
if (isExternal) if (isExternal)
module->externalTypes.PushLast(st); module->m_externalTypes.PushLast(st);
return 0; return 0;
} }
@ -2463,7 +2463,7 @@ int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSN
st->name = name; st->name = name;
st->nameSpace = ns; st->nameSpace = ns;
st->module = module; st->module = module;
module->classTypes.PushLast(st); module->AddClassType(st);
if( isShared ) if( isShared )
{ {
engine->sharedScriptTypes.PushLast(st); 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 // 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 // of a single variable, in which case the initialization order of the previous
// variables must be preserved. // variables must be preserved.
if( module->scriptGlobals.GetSize() == initOrder.GetSize() ) if( module->m_scriptGlobals.GetSize() == initOrder.GetSize() )
module->scriptGlobals.SwapWith(initOrder); module->m_scriptGlobals.SwapWith(initOrder);
} }
CleanupEnumValues(); 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 // Remember if the type was declared as external so the saved bytecode can be flagged accordingly
if (isExternal && existingSharedType) if (isExternal && existingSharedType)
module->externalTypes.PushLast(existingSharedType); module->m_externalTypes.PushLast(existingSharedType);
// Check the name and add the enum // Check the name and add the enum
int r = CheckNameConflict(name.AddressOf(), tmp->firstChild, file, ns, true, false); 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->nameSpace = ns;
st->module = module; st->module = module;
} }
module->enumTypes.PushLast(st); module->AddEnumType(st);
if( !existingSharedType && isShared ) if( !existingSharedType && isShared )
{ {
@ -4513,7 +4513,7 @@ int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNam
st->aliasForType = dataType; st->aliasForType = dataType;
st->module = module; st->module = module;
module->typeDefs.PushLast(st); module->AddTypeDef(st);
// Store the location of this declaration for reference in name collisions // Store the location of this declaration for reference in name collisions
sClassDeclaration *decl = asNEW(sClassDeclaration); 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 // Remember if the function was declared as external so the saved bytecode can be flagged accordingly
if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && func->isExistingShared) 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) if (funcTraits.GetTrait(asTRAIT_EXTERNAL) && !func->isExistingShared)
{ {
@ -5099,7 +5099,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
module->AddScriptFunction(f); module->AddScriptFunction(f);
// TODO: clean up: This should be done by AddScriptFunction() itself // TODO: clean up: This should be done by AddScriptFunction() itself
module->globalFunctions.Put(f); module->m_globalFunctions.Put(f);
} }
else else
{ {
@ -5136,7 +5136,9 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
else else
{ {
// The copy constructor needs to be marked for easy finding // 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 // 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 @ // 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<int> &funcs,
asUINT n; asUINT n;
// Get the script declared global functions // Get the script declared global functions
const asCArray<unsigned int> &idxs = module->globalFunctions.GetIndexes(ns, name); const asCArray<unsigned int> &idxs = module->m_globalFunctions.GetIndexes(ns, name);
for( n = 0; n < idxs.GetLength(); n++ ) 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 ); asASSERT( f->objectType == 0 );
funcs.PushLast(f->id); funcs.PushLast(f->id);
} }
// Add the imported functions // Add the imported functions
// TODO: optimize: Linear search: This is probably not that critial. Also bindInformation will probably be removed in near future // 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 && if( module->m_bindInformations[n]->importedFunctionSignature->name == name &&
module->bindInformations[n]->importedFunctionSignature->nameSpace == ns ) module->m_bindInformations[n]->importedFunctionSignature->nameSpace == ns )
funcs.PushLast(module->bindInformations[n]->importedFunctionSignature->id); funcs.PushLast(module->m_bindInformations[n]->importedFunctionSignature->id);
} }
// Add the registered global functions // Add the registered global functions
@ -5447,7 +5449,7 @@ void asCBuilder::GetFunctionDescriptions(const char *name, asCArray<int> &funcs,
asCScriptFunction *f = engine->registeredGlobalFuncs.Get(idxs2[n]); asCScriptFunction *f = engine->registeredGlobalFuncs.Get(idxs2[n]);
// Verify if the module has access to the function // Verify if the module has access to the function
if( module->accessMask & f->accessMask ) if( module->m_accessMask & f->accessMask )
{ {
funcs.PushLast(f->id); funcs.PushLast(f->id);
} }
@ -5508,7 +5510,7 @@ void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *ob
asCScriptFunction *func = engine->scriptFunctions[objectType->methods[n]]; asCScriptFunction *func = engine->scriptFunctions[objectType->methods[n]];
if( func->name == name && if( func->name == name &&
(!objIsConst || func->IsReadOnly()) && (!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 // When the scope is defined the returned methods should be the true methods, not the virtual method stubs
if( scope == "" ) if( scope == "" )
@ -5845,7 +5847,7 @@ asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCod
isImplicitHandle = true; isImplicitHandle = true;
// Make sure the module has access to the object type // 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) ) if( asOBJ_TYPEDEF == (ti->flags & asOBJ_TYPEDEF) )
{ {
@ -6266,24 +6268,24 @@ bool asCBuilder::DoesTypeExist(const asCString &type)
if (module) if (module)
{ {
// Add script classes and interfaces // Add script classes and interfaces
for (n = 0; n < module->classTypes.GetLength(); n++) for (n = 0; n < module->m_classTypes.GetLength(); n++)
if (!knownTypes.MoveTo(0, module->classTypes[n]->name)) if (!knownTypes.MoveTo(0, module->m_classTypes[n]->name))
knownTypes.Insert(module->classTypes[n]->name, true); knownTypes.Insert(module->m_classTypes[n]->name, true);
// Add script enums // Add script enums
for (n = 0; n < module->enumTypes.GetLength(); n++) for (n = 0; n < module->m_enumTypes.GetLength(); n++)
if (!knownTypes.MoveTo(0, module->enumTypes[n]->name)) if (!knownTypes.MoveTo(0, module->m_enumTypes[n]->name))
knownTypes.Insert(module->enumTypes[n]->name, true); knownTypes.Insert(module->m_enumTypes[n]->name, true);
// Add script typedefs // Add script typedefs
for (n = 0; n < module->typeDefs.GetLength(); n++) for (n = 0; n < module->m_typeDefs.GetLength(); n++)
if (!knownTypes.MoveTo(0, module->typeDefs[n]->name)) if (!knownTypes.MoveTo(0, module->m_typeDefs[n]->name))
knownTypes.Insert(module->typeDefs[n]->name, true); knownTypes.Insert(module->m_typeDefs[n]->name, true);
// Add script funcdefs // Add script funcdefs
for (n = 0; n < module->funcDefs.GetLength(); n++) for (n = 0; n < module->m_funcDefs.GetLength(); n++)
if (!knownTypes.MoveTo(0, module->funcDefs[n]->name)) if (!knownTypes.MoveTo(0, module->m_funcDefs[n]->name))
knownTypes.Insert(module->funcDefs[n]->name, true); knownTypes.Insert(module->m_funcDefs[n]->name, true);
} }
} }
@ -6346,9 +6348,9 @@ asCFuncdefType *asCBuilder::GetFuncDef(const char *type, asSNameSpace *ns, asCOb
if (module) 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) if (funcDef && funcDef->nameSpace == ns && funcDef->name == type)
return funcDef; return funcDef;
} }
@ -6405,7 +6407,7 @@ int asCBuilder::GetEnumValue(const char *name, asCDataType &outDt, asDWORD &outV
if( ns != et->nameSpace ) continue; if( ns != et->nameSpace ) continue;
// Don't bother with types the module doesn't have access to // 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; continue;
if( GetEnumValueFromType(et, name, outDt, outValue) ) 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( ns != et->nameSpace ) continue;
if( GetEnumValueFromType(et, name, outDt, outValue) ) if( GetEnumValueFromType(et, name, outDt, outValue) )

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any 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); internal->callConv = (internalCallConv)(thisCallConv + 2);
#endif #endif
internal->baseOffset = ( int )MULTI_BASE_OFFSET(ptr); 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 // 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 // on ARM processors, the LSB in the __delta variable is used instead of
// the one in __pfn on ARM processors. // the one in __pfn on ARM processors.
@ -619,7 +619,7 @@ int CallSystemFunction(int id, asCContext *context)
} }
// Add the base offset for multiple inheritance // 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 // 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 // and the whole offset is thus shifted one bit left to keep the original
// offset resolution // offset resolution
@ -653,7 +653,7 @@ int CallSystemFunction(int id, asCContext *context)
if( obj ) if( obj )
{ {
// Add the base offset for multiple inheritance // 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 // 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 // and the whole offset is thus shifted one bit left to keep the original
// offset resolution // offset resolution
@ -680,7 +680,7 @@ int CallSystemFunction(int id, asCContext *context)
} }
// Add the base offset for multiple inheritance // 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 // 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 // and the whole offset is thus shifted one bit left to keep the original
// offset resolution // offset resolution

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any warranty. In no event will the authors be held liable for any
@ -100,7 +100,6 @@ struct asSSystemFunctionInterface
asFUNCTION_t func; asFUNCTION_t func;
int baseOffset; int baseOffset;
internalCallConv callConv; internalCallConv callConv;
int scriptReturnSize;
bool hostReturnInMemory; bool hostReturnInMemory;
bool hostReturnFloat; bool hostReturnFloat;
int hostReturnSize; int hostReturnSize;
@ -120,7 +119,7 @@ struct asSSystemFunctionInterface
}; };
asCArray<SClean> cleanArgs; asCArray<SClean> 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) asSSystemFunctionInterface(const asSSystemFunctionInterface &in)
{ {
@ -132,7 +131,6 @@ struct asSSystemFunctionInterface
func = in.func; func = in.func;
baseOffset = in.baseOffset; baseOffset = in.baseOffset;
callConv = in.callConv; callConv = in.callConv;
scriptReturnSize = in.scriptReturnSize;
hostReturnInMemory = in.hostReturnInMemory; hostReturnInMemory = in.hostReturnInMemory;
hostReturnFloat = in.hostReturnFloat; hostReturnFloat = in.hostReturnFloat;
hostReturnSize = in.hostReturnSize; hostReturnSize = in.hostReturnSize;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any 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(__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 */ /* iOS, Android, Marmalade, and Linux with soft-float ABI goes here */
@ -287,7 +287,7 @@ nomoreargsarmFuncR0R1:
ldmia sp!, {r4-r8, pc} 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 */ /* The Linux with hard-float ABI code goes here */

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any 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++) for (asUINT n = 0; n < usedStringConstants.GetLength(); n++)
engine->stringFactory->ReleaseStringConstant(usedStringConstants[n]); engine->stringFactory->ReleaseStringConstant(usedStringConstants[n]);
usedStringConstants.SetLength(0); 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) void asCCompiler::Reset(asCBuilder *in_builder, asCScriptCode *in_script, asCScriptFunction *in_outFunc)
@ -352,7 +356,9 @@ int asCCompiler::SetupParametersAndReturnVariable(asCArray<asCString> &parameter
// Is the return type allowed? // Is the return type allowed?
if( returnType != asCDataType::CreatePrimitive(ttVoid, false) && if( returnType != asCDataType::CreatePrimitive(ttVoid, false) &&
!returnType.CanBeInstantiated() ) !returnType.CanBeInstantiated() &&
!returnType.IsReference() &&
!returnType.IsObjectHandle() )
{ {
// TODO: Hasn't this been validated by the builder already? // TODO: Hasn't this been validated by the builder already?
asCString str; asCString str;
@ -431,6 +437,7 @@ void asCCompiler::CompileMemberInitialization(asCByteCode *bc, bool onlyDefaults
asCObjectProperty *prop = outFunc->objectType->properties[n]; asCObjectProperty *prop = outFunc->objectType->properties[n];
// Check if the property has an initialization expression // Check if the property has an initialization expression
asCParser parser(builder);
asCScriptNode *declNode = 0; asCScriptNode *declNode = 0;
asCScriptNode *initNode = 0; asCScriptNode *initNode = 0;
asCScriptCode *initScript = 0; asCScriptCode *initScript = 0;
@ -466,7 +473,6 @@ void asCCompiler::CompileMemberInitialization(asCByteCode *bc, bool onlyDefaults
initScript = script; initScript = script;
#else #else
// Re-parse the initialization expression as the parser now knows the types, which it didn't earlier // 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); int r = parser.ParseVarInit(initScript, initNode);
if( r < 0 ) if( r < 0 )
continue; continue;
@ -2322,6 +2328,12 @@ int asCCompiler::CompileDefaultAndNamedArgs(asCScriptNode *node, asCArray<asCExp
} }
MergeExprBytecodeAndType(args[n], &expr); MergeExprBytecodeAndType(args[n], &expr);
if (args[n]->exprNode)
{
// 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); reservedVariables.SetLength(prevReservedVars);
@ -2655,6 +2667,8 @@ bool asCCompiler::CompileAutoType(asCDataType &type, asCExprContext &compiledCtx
// Handle const qualifier on auto // Handle const qualifier on auto
if (type.IsReadOnly()) if (type.IsReadOnly())
newType.MakeReadOnly(true); newType.MakeReadOnly(true);
else if (type.IsHandleToConst())
newType.MakeHandleToConst(true);
else if (newType.IsPrimitive()) else if (newType.IsPrimitive())
newType.MakeReadOnly(false); newType.MakeReadOnly(false);
@ -9253,7 +9267,7 @@ asCCompiler::SYMBOLTYPE asCCompiler::SymbolLookupMember(const asCString &name, a
{ {
asCScriptFunction *f = engine->scriptFunctions[ot->methods[n]]; asCScriptFunction *f = engine->scriptFunctions[ot->methods[n]];
if (f->name == name && if (f->name == name &&
(builder->module->accessMask & f->accessMask)) (builder->module->m_accessMask & f->accessMask))
{ {
outResult->type.dataType.SetTypeInfo(objType); outResult->type.dataType.SetTypeInfo(objType);
return SL_CLASSMETHOD; return SL_CLASSMETHOD;
@ -9835,7 +9849,7 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s
{ {
asCScriptFunction *f = engine->scriptFunctions[ot->methods[n]]; asCScriptFunction *f = engine->scriptFunctions[ot->methods[n]];
if (f->name == name && if (f->name == name &&
(builder->module->accessMask & f->accessMask)) (builder->module->m_accessMask & f->accessMask))
{ {
func = f; func = f;
break; break;
@ -10901,7 +10915,7 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asCExprContext *ctx)
// It is possible that the name is really a constructor // It is possible that the name is really a constructor
asCDataType dt; asCDataType dt;
dt = builder->CreateDataTypeFromNode(node->firstChild, script, outFunc->nameSpace); dt = builder->CreateDataTypeFromNode(node->firstChild, script, outFunc->nameSpace, false, outFunc->objectType);
if( dt.IsPrimitive() ) if( dt.IsPrimitive() )
{ {
// This is a cast to a primitive type // This is a cast to a primitive type
@ -10965,6 +10979,10 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asCExprContext *ctx)
conv.Copy(args[0]); conv.Copy(args[0]);
asUINT cost = ImplicitConversion(&conv, dt, node->lastChild, asIC_EXPLICIT_VAL_CAST, false); 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 // 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 // is done and the script wants a new value to be constructed
if( conv.type.dataType.IsEqualExceptRef(dt) && cost > 0 ) 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) if (symbolType == SL_CLASSTYPE || symbolType == SL_GLOBALTYPE)
{ {
bool isValid = false; 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) if (isValid)
return CompileConstructCall(node, ctx); return CompileConstructCall(node, ctx);
} }
@ -13601,7 +13619,7 @@ int asCCompiler::CompileOverloadedDualOperator2(asCScriptNode *node, const char
(!isConst || func->IsReadOnly()) ) (!isConst || func->IsReadOnly()) )
{ {
// Make sure the method is accessible by the module // 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); funcs.PushLast(func->id);
} }

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any 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. // so they can be released upon completion, whether the compilation was successful or not.
asCArray<void*> usedStringConstants; asCArray<void*> usedStringConstants;
// This array holds the nodes that have been allocated temporarily
asCArray<asCScriptNode*> nodesToFreeUponComplete;
bool isCompilingDefaultArg; bool isCompilingDefaultArg;
bool isProcessingDeferredParams; bool isProcessingDeferredParams;
int noCodeOutput; int noCodeOutput;

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any 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) // Oracle Solaris Studio (previously known as Sun CC compiler)
// __SUNPRO_CC is defined // __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 // AS_ARM
// Use assembler code for the ARM CPU family // Use assembler code for the ARM CPU family
// AS_ARM64
// Use assembler code for the ARM64/AArch64 CPU family
// AS_SOFTFP // AS_SOFTFP
// Use to tell compiler that ARM soft-float ABI // Use to tell compiler that ARM soft-float ABI
// should be used instead of ARM hard-float ABI // should be used instead of ARM hard-float ABI
@ -227,6 +238,10 @@
// AS_SPARC // AS_SPARC
// Define this for SPARC CPU family // 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 #define AS_NO_THISCALL_FUNCTOR_METHOD
// Emscripten compiler toolchain
// ref: https://emscripten.org/
#if defined(__EMSCRIPTEN__)
#define AS_MAX_PORTABILITY
#endif
// Embarcadero C++Builder // Embarcadero C++Builder
#if defined(__BORLANDC__) #if defined(__BORLANDC__)
#ifndef _Windows #ifndef _Windows
@ -482,7 +505,7 @@
#define AS_CALLEE_DESTROY_OBJ_BY_VAL #define AS_CALLEE_DESTROY_OBJ_BY_VAL
#define AS_LARGE_OBJS_PASSED_BY_REF #define AS_LARGE_OBJS_PASSED_BY_REF
#define AS_LARGE_OBJ_MIN_SIZE 3 #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) #define COMPLEX_MASK (asOBJ_APP_CLASS_COPY_CONSTRUCTOR | asOBJ_APP_ARRAY)
#endif #endif
#endif #endif
@ -502,12 +525,18 @@
#endif #endif
#endif #endif
#if defined(_M_ARM64)
#define AS_ARM64
// TODO: MORE HERE
#endif
#ifndef COMPLEX_MASK #ifndef COMPLEX_MASK
#define COMPLEX_MASK (asOBJ_APP_ARRAY) #define COMPLEX_MASK (asOBJ_APP_ARRAY)
#endif #endif
#ifndef COMPLEX_RETURN_MASK #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 #endif
#define UNREACHABLE_RETURN #define UNREACHABLE_RETURN
@ -864,7 +893,7 @@
#elif defined(__ARMEL__) || defined(__arm__) || defined(__aarch64__) || defined(__AARCH64EL__) #elif defined(__ARMEL__) || defined(__arm__) || defined(__aarch64__) || defined(__AARCH64EL__)
// arm // 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__) #if !defined(__ARM_ARCH_4__) && !defined(__ARM_ARCH_4T__) && !defined(__LP64__)
#define AS_ARM #define AS_ARM
@ -894,13 +923,35 @@
#endif #endif
// Verify if soft-float or hard-float ABI is used // 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 // -ffloat-abi=softfp or -ffloat-abi=soft
#define AS_SOFTFP #define AS_SOFTFP
#endif #endif
// Tested with both hard float and soft float abi // Tested with both hard float and soft float abi
#undef AS_NO_THISCALL_FUNCTOR_METHOD #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 #endif
#elif defined(__mips__) #elif defined(__mips__)
@ -932,6 +983,17 @@
// although use 64bit PPC only uses 32bit pointers. // although use 64bit PPC only uses 32bit pointers.
// TODO: Add support for native calling conventions on Linux with PPC 64bit // TODO: Add support for native calling conventions on Linux with PPC 64bit
#define AS_MAX_PORTABILITY #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 #else
#define AS_MAX_PORTABILITY #define AS_MAX_PORTABILITY
#endif #endif
@ -1085,25 +1147,28 @@
// Haiku OS // Haiku OS
#elif __HAIKU__ #elif __HAIKU__
#define AS_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__) #if (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__)
#define AS_X86 #define AS_X86
#define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK #define THISCALL_PASS_OBJECT_POINTER_ON_THE_STACK
#define THISCALL_RETURN_SIMPLE_IN_MEMORY #define THISCALL_RETURN_SIMPLE_IN_MEMORY
#define CDECL_RETURN_SIMPLE_IN_MEMORY #define CDECL_RETURN_SIMPLE_IN_MEMORY
#define STDCALL_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 #else
#define AS_MAX_PORTABILITY #define AS_MAX_PORTABILITY
#endif #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 // Illumos
#elif defined(__sun) #elif defined(__sun)
#if (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__) #if (defined(i386) || defined(__i386) || defined(__i386__)) && !defined(__LP64__)
@ -1193,7 +1258,7 @@
// If there are no current support for native calling // If there are no current support for native calling
// conventions, then compile with AS_MAX_PORTABILITY // 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 #ifndef AS_MAX_PORTABILITY
#define AS_MAX_PORTABILITY #define AS_MAX_PORTABILITY
#endif #endif

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any 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(); globalProps[n]->Release();
// TODO: global: Should compact the registeredGlobalProps array
engine->registeredGlobalProps.Erase(index); engine->registeredGlobalProps.Erase(index);
} }
} }

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any warranty. In no event will the authors be held liable for any
@ -4404,7 +4404,23 @@ void asCContext::ExecuteNext()
// Call the method // Call the method
m_callingSystemFunction = m_engine->scriptFunctions[i]; 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; m_callingSystemFunction = 0;
*(asPWORD*)&m_regs.valueRegister = (asPWORD)ptr; *(asPWORD*)&m_regs.valueRegister = (asPWORD)ptr;
} }
@ -4816,8 +4832,9 @@ void asCContext::DetermineLiveObjects(asCArray<int> &liveObjects, asUINT stackLe
} }
} }
break; break;
case asOBJ_VARDECL: case asOBJ_VARDECL: // A variable was declared
break; // We don't really care about the variable declarations at this moment
break;
} }
} }

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any warranty. In no event will the authors be held liable for any
@ -38,7 +38,7 @@
#include <stdlib.h> #include <stdlib.h>
#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 <malloc.h> #include <malloc.h>
#endif #endif
@ -241,6 +241,11 @@ void asCMemoryMgr::FreeScriptNode(void *ptr)
scriptNodePool.Allocate(100, 0); scriptNodePool.Allocate(100, 0);
scriptNodePool.PushLast(ptr); scriptNodePool.PushLast(ptr);
#ifdef AS_DEBUG
// clear the memory to facilitate identification of use after free
memset(ptr, 0xCDCDCDCD, sizeof(asCScriptNode));
#endif
LEAVECRITICALSECTION(cs); LEAVECRITICALSECTION(cs);
} }
@ -249,6 +254,8 @@ void asCMemoryMgr::FreeScriptNode(void *ptr)
void *asCMemoryMgr::AllocByteInstruction() void *asCMemoryMgr::AllocByteInstruction()
{ {
// This doesn't need a critical section because, only one compilation is allowed at a time
if( byteInstructionPool.GetLength() ) if( byteInstructionPool.GetLength() )
return byteInstructionPool.PopLast(); return byteInstructionPool.PopLast();
@ -266,6 +273,11 @@ void asCMemoryMgr::FreeByteInstruction(void *ptr)
byteInstructionPool.Allocate(100, 0); byteInstructionPool.Allocate(100, 0);
byteInstructionPool.PushLast(ptr); 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 #endif // AS_NO_COMPILER

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any warranty. In no event will the authors be held liable for any
@ -182,6 +182,7 @@ public:
int CallInit(asIScriptContext *ctx); int CallInit(asIScriptContext *ctx);
void CallExit(); void CallExit();
int InitGlobalProp(asCGlobalProperty *prop, asIScriptContext *ctx);
void JITCompile(); void JITCompile();
@ -194,47 +195,61 @@ public:
int GetNextImportedFunctionId(); int GetNextImportedFunctionId();
asCScriptFunction *GetImportedFunction(int funcId) const; asCScriptFunction *GetImportedFunction(int funcId) const;
asCTypeInfo *GetType(const char *type, asSNameSpace *ns); asCTypeInfo *GetType(const asCString &type, asSNameSpace *ns) const;
asCObjectType *GetObjectType(const char *type, asSNameSpace *ns); asCObjectType *GetObjectType(const char *type, asSNameSpace *ns) const;
asCGlobalProperty *AllocateGlobalProperty(const char *name, const asCDataType &dt, asSNameSpace *ns); asCGlobalProperty *AllocateGlobalProperty(const char *name, const asCDataType &dt, asSNameSpace *ns);
void UninitializeGlobalProp(asCGlobalProperty *prop); 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; asCString m_name;
asCScriptEngine *m_engine;
asCScriptEngine *engine; asCBuilder *m_builder;
asCBuilder *builder; asCArray<asPWORD> m_userData;
asCArray<asPWORD> userData; asDWORD m_accessMask;
asDWORD accessMask; asSNameSpace *m_defaultNamespace;
asSNameSpace *defaultNamespace;
// This array holds all functions, class members, factories, etc that were compiled with the module. // 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. // These references hold an internal reference to the function object.
asCArray<asCScriptFunction *> scriptFunctions; // increases ref count asCArray<asCScriptFunction *> m_scriptFunctions; // increases ref count
// This array holds global functions declared in the module. These references are not counted, // 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. // as the same pointer is always present in the scriptFunctions array too.
asCSymbolTable<asCScriptFunction> globalFunctions; // doesn't increase ref count asCSymbolTable<asCScriptFunction> m_globalFunctions; // doesn't increase ref count
// This array holds imported functions in the module. // This array holds imported functions in the module.
asCArray<sBindInfo *> bindInformations; // increases ref count asCArray<sBindInfo *> m_bindInformations; // increases ref count
// This array holds template instance types created for the module's object types // This array holds template instance types created for the module's object types
asCArray<asCObjectType*> templateInstances; // increases ref count asCArray<asCObjectType*> m_templateInstances; // increases ref count
// This array holds the global variables declared in the script // This array holds the global variables declared in the script
asCSymbolTable<asCGlobalProperty> scriptGlobals; // increases ref count asCSymbolTable<asCGlobalProperty> m_scriptGlobals; // increases ref count
bool isGlobalVarInitialized; bool m_isGlobalVarInitialized;
// This array holds class and interface types // This array holds class and interface types
asCArray<asCObjectType*> classTypes; // increases ref count asCArray<asCObjectType*> m_classTypes; // increases ref count
// This array holds enum types // This array holds enum types
asCArray<asCEnumType*> enumTypes; // increases ref count asCArray<asCEnumType*> m_enumTypes; // increases ref count
// This array holds typedefs // This array holds typedefs
asCArray<asCTypedefType*> typeDefs; // increases ref count asCArray<asCTypedefType*> m_typeDefs; // increases ref count
// This array holds the funcdefs declared in the module // This array holds the funcdefs declared in the module
asCArray<asCFuncdefType*> funcDefs; // increases ref count asCArray<asCFuncdefType*> 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<asSNameSpaceNamePair, asCTypeInfo*> m_typeLookup; // doesn't increase ref count
// This array holds types that have been explicitly declared with 'external' // This array holds types that have been explicitly declared with 'external'
asCArray<asCTypeInfo*> externalTypes; // doesn't increase ref count asCArray<asCTypeInfo*> m_externalTypes; // doesn't increase ref count
// This array holds functions that have been explicitly declared with 'external' // This array holds functions that have been explicitly declared with 'external'
asCArray<asCScriptFunction*> externalFunctions; // doesn't increase ref count asCArray<asCScriptFunction*> m_externalFunctions; // doesn't increase ref count
}; };
END_AS_NAMESPACE END_AS_NAMESPACE

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any 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 // Make sure none of the loaded functions attempt to release
// references that have not yet been increased // references that have not yet been increased
asUINT i; asUINT i;
for( i = 0; i < module->scriptFunctions.GetLength(); i++ ) for( i = 0; i < module->m_scriptFunctions.GetLength(); i++ )
if( !dontTranslate.MoveTo(0, module->scriptFunctions[i]) ) if( !dontTranslate.MoveTo(0, module->m_scriptFunctions[i]) )
if( module->scriptFunctions[i]->scriptData ) if( module->m_scriptFunctions[i]->scriptData )
module->scriptFunctions[i]->scriptData->byteCode.SetLength(0); module->m_scriptFunctions[i]->scriptData->byteCode.SetLength(0);
asCSymbolTable<asCGlobalProperty>::iterator it = module->scriptGlobals.List(); asCSymbolTable<asCGlobalProperty>::iterator it = module->m_scriptGlobals.List();
for( ; it; it++ ) for( ; it; it++ )
if( (*it)->GetInitFunc() ) if( (*it)->GetInitFunc() )
if( (*it)->GetInitFunc()->scriptData ) if( (*it)->GetInitFunc()->scriptData )
@ -156,7 +156,7 @@ int asCReader::ReadInner()
// Read enums // Read enums
count = ReadEncodedUInt(); count = ReadEncodedUInt();
module->enumTypes.Allocate(count, false); module->m_enumTypes.Allocate(count, false);
for( i = 0; i < count && !error; i++ ) for( i = 0; i < count && !error; i++ )
{ {
asCEnumType *et = asNEW(asCEnumType)(engine); asCEnumType *et = asNEW(asCEnumType)(engine);
@ -216,10 +216,10 @@ int asCReader::ReadInner()
// Set this module as the owner // Set this module as the owner
et->module = module; et->module = module;
} }
module->enumTypes.PushLast(et); module->AddEnumType(et);
if (isExternal) if (isExternal)
module->externalTypes.PushLast(et); module->m_externalTypes.PushLast(et);
ReadTypeDeclaration(et, 2); ReadTypeDeclaration(et, 2);
} }
@ -229,7 +229,7 @@ int asCReader::ReadInner()
// classTypes[] // classTypes[]
// First restore the structure names, then the properties // First restore the structure names, then the properties
count = ReadEncodedUInt(); count = ReadEncodedUInt();
module->classTypes.Allocate(count, false); module->m_classTypes.Allocate(count, false);
for( i = 0; i < count && !error; ++i ) for( i = 0; i < count && !error; ++i )
{ {
asCObjectType *ot = asNEW(asCObjectType)(engine); asCObjectType *ot = asNEW(asCObjectType)(engine);
@ -290,17 +290,17 @@ int asCReader::ReadInner()
// Set this module as the owner // Set this module as the owner
ot->module = module; ot->module = module;
} }
module->classTypes.PushLast(ot); module->AddClassType(ot);
if (isExternal) if (isExternal)
module->externalTypes.PushLast(ot); module->m_externalTypes.PushLast(ot);
} }
if( error ) return asERROR; if( error ) return asERROR;
// Read func defs // Read func defs
count = ReadEncodedUInt(); count = ReadEncodedUInt();
module->funcDefs.Allocate(count, false); module->m_funcDefs.Allocate(count, false);
for( i = 0; i < count && !error; i++ ) for( i = 0; i < count && !error; i++ )
{ {
bool isNew, isExternal; bool isNew, isExternal;
@ -312,7 +312,7 @@ int asCReader::ReadInner()
asCFuncdefType *fdt = funcDef->funcdefType; asCFuncdefType *fdt = funcDef->funcdefType;
fdt->module = module; fdt->module = module;
module->funcDefs.PushLast(fdt); module->AddFuncDef(fdt);
engine->funcDefs.PushLast(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 // 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) ) f2->funcdef->IsSignatureExceptNameEqual(funcDef) )
{ {
// Replace our funcdef for the existing one // Replace our funcdef for the existing one
module->funcDefs[module->funcDefs.IndexOf(fdt)] = f2; module->ReplaceFuncDef(fdt, f2);
f2->AddRefInternal(); f2->AddRefInternal();
if (isExternal) if (isExternal)
module->externalTypes.PushLast(f2); module->m_externalTypes.PushLast(f2);
engine->funcDefs.RemoveValue(fdt); engine->funcDefs.RemoveValue(fdt);
@ -378,31 +378,31 @@ int asCReader::ReadInner()
} }
// Read interface methods // 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() ) if( module->m_classTypes[i]->IsInterface() )
ReadTypeDeclaration(module->classTypes[i], 2); ReadTypeDeclaration(module->m_classTypes[i], 2);
} }
// Read class methods and behaviours // 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() ) if( !module->m_classTypes[i]->IsInterface() )
ReadTypeDeclaration(module->classTypes[i], 2); ReadTypeDeclaration(module->m_classTypes[i], 2);
} }
// Read class properties // 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() ) if( !module->m_classTypes[i]->IsInterface() )
ReadTypeDeclaration(module->classTypes[i], 3); ReadTypeDeclaration(module->m_classTypes[i], 3);
} }
if( error ) return asERROR; if( error ) return asERROR;
// Read typedefs // Read typedefs
count = ReadEncodedUInt(); count = ReadEncodedUInt();
module->typeDefs.Allocate(count, false); module->m_typeDefs.Allocate(count, false);
for( i = 0; i < count && !error; i++ ) for( i = 0; i < count && !error; i++ )
{ {
asCTypedefType *td = asNEW(asCTypedefType)(engine); asCTypedefType *td = asNEW(asCTypedefType)(engine);
@ -415,7 +415,7 @@ int asCReader::ReadInner()
bool isExternal = false; bool isExternal = false;
ReadTypeDeclaration(td, 1, &isExternal); ReadTypeDeclaration(td, 1, &isExternal);
td->module = module; td->module = module;
module->typeDefs.PushLast(td); module->AddTypeDef(td);
ReadTypeDeclaration(td, 2); ReadTypeDeclaration(td, 2);
} }
@ -428,7 +428,7 @@ int asCReader::ReadInner()
engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_GLOBAL_VARS_NOT_ALLOWED); engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_GLOBAL_VARS_NOT_ALLOWED);
Error(TXT_INVALID_BYTECODE_d); Error(TXT_INVALID_BYTECODE_d);
} }
module->scriptGlobals.Allocate(count, false); module->m_scriptGlobals.Allocate(count, false);
for( i = 0; i < count && !error; ++i ) for( i = 0; i < count && !error; ++i )
{ {
ReadGlobalProperty(); ReadGlobalProperty();
@ -438,7 +438,7 @@ int asCReader::ReadInner()
count = ReadEncodedUInt(); count = ReadEncodedUInt();
for( i = 0; i < count && !error; ++i ) for( i = 0; i < count && !error; ++i )
{ {
size_t len = module->scriptFunctions.GetLength(); size_t len = module->m_scriptFunctions.GetLength();
bool isNew, isExternal; bool isNew, isExternal;
func = ReadFunction(isNew, true, true, true, &isExternal); func = ReadFunction(isNew, true, true, true, &isExternal);
if( func == 0 ) if( func == 0 )
@ -448,7 +448,7 @@ int asCReader::ReadInner()
} }
// Is the function shared and was it created now? // 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 // If the function already existed in another module, then
// we need to replace it with previously existing one // we need to replace it with previously existing one
@ -462,7 +462,7 @@ int asCReader::ReadInner()
realFunc->IsSignatureEqual(func) ) realFunc->IsSignatureEqual(func) )
{ {
// Replace the recently created function with the pre-existing function // 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(); realFunc->AddRefInternal();
savedFunctions[savedFunctions.GetLength()-1] = realFunc; savedFunctions[savedFunctions.GetLength()-1] = realFunc;
engine->RemoveScriptFunction(func); engine->RemoveScriptFunction(func);
@ -471,7 +471,7 @@ int asCReader::ReadInner()
dontTranslate.Insert(realFunc, true); dontTranslate.Insert(realFunc, true);
if (isExternal) if (isExternal)
module->externalFunctions.PushLast(realFunc); module->m_externalFunctions.PushLast(realFunc);
// Release the function, but make sure nothing else is released // Release the function, but make sure nothing else is released
func->id = 0; 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 // we're just re-reading the references to know which goes into the globalFunctions array
asASSERT( !isNew ); asASSERT( !isNew );
module->globalFunctions.Put(func); module->m_globalFunctions.Put(func);
} }
else else
Error(TXT_INVALID_BYTECODE_d); Error(TXT_INVALID_BYTECODE_d);
@ -517,7 +517,7 @@ int asCReader::ReadInner()
// bindInformations[] // bindInformations[]
count = ReadEncodedUInt(); count = ReadEncodedUInt();
module->bindInformations.Allocate(count, false); module->m_bindInformations.Allocate(count, false);
for( i = 0; i < count && !error; ++i ) for( i = 0; i < count && !error; ++i )
{ {
sBindInfo *info = asNEW(sBindInfo); sBindInfo *info = asNEW(sBindInfo);
@ -548,7 +548,7 @@ int asCReader::ReadInner()
} }
ReadString(&info->importFromModule); ReadString(&info->importFromModule);
info->boundFunctionId = -1; info->boundFunctionId = -1;
module->bindInformations.PushLast(info); module->m_bindInformations.PushLast(info);
} }
if( error ) return asERROR; if( error ) return asERROR;
@ -622,11 +622,11 @@ int asCReader::ReadInner()
// Update the loaded bytecode to point to the correct types, property offsets, // Update the loaded bytecode to point to the correct types, property offsets,
// function ids, etc. This is basically a linking stage. // function ids, etc. This is basically a linking stage.
for( i = 0; i < module->scriptFunctions.GetLength() && !error; i++ ) for( i = 0; i < module->m_scriptFunctions.GetLength() && !error; i++ )
if( module->scriptFunctions[i]->funcType == asFUNC_SCRIPT ) if( module->m_scriptFunctions[i]->funcType == asFUNC_SCRIPT )
TranslateFunction(module->scriptFunctions[i]); TranslateFunction(module->m_scriptFunctions[i]);
asCSymbolTable<asCGlobalProperty>::iterator globIt = module->scriptGlobals.List(); asCSymbolTable<asCGlobalProperty>::iterator globIt = module->m_scriptGlobals.List();
while( globIt && !error ) while( globIt && !error )
{ {
asCScriptFunction *initFunc = (*globIt)->GetInitFunc(); asCScriptFunction *initFunc = (*globIt)->GetInitFunc();
@ -638,11 +638,11 @@ int asCReader::ReadInner()
if( error ) return asERROR; if( error ) return asERROR;
// Add references for all functions (except for the pre-existing shared code) // Add references for all functions (except for the pre-existing shared code)
for( i = 0; i < module->scriptFunctions.GetLength(); i++ ) for( i = 0; i < module->m_scriptFunctions.GetLength(); i++ )
if( !dontTranslate.MoveTo(0, module->scriptFunctions[i]) ) if( !dontTranslate.MoveTo(0, module->m_scriptFunctions[i]) )
module->scriptFunctions[i]->AddReferences(); module->m_scriptFunctions[i]->AddReferences();
globIt = module->scriptGlobals.List(); globIt = module->m_scriptGlobals.List();
while( globIt ) while( globIt )
{ {
asCScriptFunction *initFunc = (*globIt)->GetInitFunc(); asCScriptFunction *initFunc = (*globIt)->GetInitFunc();
@ -721,9 +721,9 @@ void asCReader::ReadUsedFunctions()
{ {
if( func.funcType == asFUNC_IMPORTED ) 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 || if( func.objectType != f->objectType ||
func.funcType != f->funcType || func.funcType != f->funcType ||
func.nameSpace != f->nameSpace || func.nameSpace != f->nameSpace ||
@ -736,7 +736,7 @@ void asCReader::ReadUsedFunctions()
} }
else if( func.funcType == asFUNC_FUNCDEF ) else if( func.funcType == asFUNC_FUNCDEF )
{ {
const asCArray<asCFuncdefType *> &funcs = module->funcDefs; const asCArray<asCFuncdefType *> &funcs = module->m_funcDefs;
for( asUINT i = 0; i < funcs.GetLength(); i++ ) for( asUINT i = 0; i < funcs.GetLength(); i++ )
{ {
asCScriptFunction *f = funcs[i]->funcdef; 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: Global functions should be searched for in module->globalFunctions
// TODO: optimize: funcdefs should be searched for in module->funcDefs // TODO: optimize: funcdefs should be searched for in module->funcDefs
// TODO: optimize: object methods should be searched for directly in the object type // 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 || if( func.objectType != f->objectType ||
func.funcType != f->funcType || func.funcType != f->funcType ||
func.nameSpace != f->nameSpace || func.nameSpace != f->nameSpace ||
@ -922,17 +922,6 @@ void asCReader::ReadUsedFunctions()
usedFunctions[n] = f; 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" ) else if( func.name == "$dlgte" )
{ {
// This is the delegate factory // This is the delegate factory
@ -940,6 +929,11 @@ void asCReader::ReadUsedFunctions()
asASSERT( f && func.IsSignatureEqual(f) ); asASSERT( f && func.IsSignatureEqual(f) );
usedFunctions[n] = f; usedFunctions[n] = f;
} }
else
{
// Must match one of the above cases
asASSERT(false);
}
} }
else if( func.objectType == 0 ) else if( func.objectType == 0 )
{ {
@ -1205,7 +1199,7 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
if( func->funcType == asFUNC_SCRIPT ) if( func->funcType == asFUNC_SCRIPT )
{ {
// Skip this for external shared entities // 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 // Replace with the real function from the existing entity
isNew = false; isNew = false;
@ -1429,10 +1423,110 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
fdt->parentClass = parentClass; 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 ) if( addToModule )
{ {
// The refCount is already 1 // The refCount is already 1
module->scriptFunctions.PushLast(func); module->m_scriptFunctions.PushLast(func);
func->module = module; func->module = module;
} }
if( addToEngine ) if( addToEngine )
@ -1513,7 +1607,7 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
else if( phase == 2 ) else if( phase == 2 )
{ {
// external shared types doesn't store this // 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; return;
if( type->flags & asOBJ_ENUM ) if( type->flags & asOBJ_ENUM )
@ -1668,8 +1762,6 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
func->scriptData->byteCode.SetLength(0); func->scriptData->byteCode.SetLength(0);
func->ReleaseInternal(); func->ReleaseInternal();
} }
module->scriptFunctions.PushLast(realFunc);
realFunc->AddRefInternal();
dontTranslate.Insert(realFunc, true); dontTranslate.Insert(realFunc, true);
} }
} }
@ -1703,8 +1795,6 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
if( savedFunctions[savedFunctions.GetLength()-1] == func ) if( savedFunctions[savedFunctions.GetLength()-1] == func )
savedFunctions[savedFunctions.GetLength()-1] = realFunc; savedFunctions[savedFunctions.GetLength()-1] = realFunc;
found = true; found = true;
module->scriptFunctions.PushLast(realFunc);
realFunc->AddRefInternal();
dontTranslate.Insert(realFunc, true); dontTranslate.Insert(realFunc, true);
break; break;
} }
@ -1754,8 +1844,6 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
if( savedFunctions[savedFunctions.GetLength()-1] == func ) if( savedFunctions[savedFunctions.GetLength()-1] == func )
savedFunctions[savedFunctions.GetLength()-1] = realFunc; savedFunctions[savedFunctions.GetLength()-1] = realFunc;
found = true; found = true;
module->scriptFunctions.PushLast(realFunc);
realFunc->AddRefInternal();
dontTranslate.Insert(realFunc, true); dontTranslate.Insert(realFunc, true);
break; break;
} }
@ -1813,8 +1901,6 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
if( savedFunctions[savedFunctions.GetLength()-1] == func ) if( savedFunctions[savedFunctions.GetLength()-1] == func )
savedFunctions[savedFunctions.GetLength()-1] = realFunc; savedFunctions[savedFunctions.GetLength()-1] = realFunc;
found = true; found = true;
module->scriptFunctions.PushLast(realFunc);
realFunc->AddRefInternal();
dontTranslate.Insert(realFunc, true); dontTranslate.Insert(realFunc, true);
break; break;
} }
@ -1880,8 +1966,6 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
if( savedFunctions[savedFunctions.GetLength()-1] == func ) if( savedFunctions[savedFunctions.GetLength()-1] == func )
savedFunctions[savedFunctions.GetLength()-1] = realFunc; savedFunctions[savedFunctions.GetLength()-1] = realFunc;
found = true; found = true;
module->scriptFunctions.PushLast(realFunc);
realFunc->AddRefInternal();
dontTranslate.Insert(realFunc, true); dontTranslate.Insert(realFunc, true);
break; break;
} }
@ -1918,7 +2002,7 @@ void asCReader::ReadTypeDeclaration(asCTypeInfo *type, int phase, bool *isExtern
else if( phase == 3 ) else if( phase == 3 )
{ {
// external shared types doesn't store this // 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; return;
asCObjectType *ot = CastToObjectType(type); asCObjectType *ot = CastToObjectType(type);
@ -2614,7 +2698,7 @@ void asCReader::ReadUsedGlobalProps()
// Find the real property // Find the real property
asCGlobalProperty *globProp = 0; asCGlobalProperty *globProp = 0;
if( moduleProp ) if( moduleProp )
globProp = module->scriptGlobals.GetFirst(nameSpace, name); globProp = module->m_scriptGlobals.GetFirst(nameSpace, name);
else else
globProp = engine->registeredGlobalProps.GetFirst(nameSpace, name); globProp = engine->registeredGlobalProps.GetFirst(nameSpace, name);
@ -2873,9 +2957,9 @@ void asCReader::TranslateFunction(asCScriptFunction *func)
{ {
// Translate the function id // Translate the function id
asUINT *fid = (asUINT*)&bc[n+1]; 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 ) if( bi )
*fid = bi->importedFunctionSignature->id; *fid = bi->importedFunctionSignature->id;
else else
@ -3819,12 +3903,12 @@ int asCWriter::Write()
{ {
TimeIt("store enums"); TimeIt("store enums");
count = (asUINT)module->enumTypes.GetLength(); count = (asUINT)module->m_enumTypes.GetLength();
WriteEncodedInt64(count); WriteEncodedInt64(count);
for( i = 0; i < count; i++ ) for( i = 0; i < count; i++ )
{ {
WriteTypeDeclaration(module->enumTypes[i], 1); WriteTypeDeclaration(module->m_enumTypes[i], 1);
WriteTypeDeclaration(module->enumTypes[i], 2); WriteTypeDeclaration(module->m_enumTypes[i], 2);
} }
} }
@ -3832,12 +3916,12 @@ int asCWriter::Write()
{ {
TimeIt("type declarations"); TimeIt("type declarations");
count = (asUINT)module->classTypes.GetLength(); count = (asUINT)module->m_classTypes.GetLength();
WriteEncodedInt64(count); WriteEncodedInt64(count);
for( i = 0; i < count; i++ ) for( i = 0; i < count; i++ )
{ {
// Store only the name of the class/interface types // 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"); TimeIt("func defs");
count = (asUINT)module->funcDefs.GetLength(); count = (asUINT)module->m_funcDefs.GetLength();
WriteEncodedInt64(count); WriteEncodedInt64(count);
for( i = 0; i < count; i++ ) for( i = 0; i < count; i++ )
WriteFunction(module->funcDefs[i]->funcdef); WriteFunction(module->m_funcDefs[i]->funcdef);
} }
// Now store all interface methods // Now store all interface methods
{ {
TimeIt("interface methods"); TimeIt("interface methods");
count = (asUINT)module->classTypes.GetLength(); count = (asUINT)module->m_classTypes.GetLength();
for( i = 0; i < count; i++ ) for( i = 0; i < count; i++ )
{ {
if( module->classTypes[i]->IsInterface() ) if( module->m_classTypes[i]->IsInterface() )
WriteTypeDeclaration(module->classTypes[i], 2); WriteTypeDeclaration(module->m_classTypes[i], 2);
} }
} }
@ -3869,8 +3953,8 @@ int asCWriter::Write()
for( i = 0; i < count; ++i ) for( i = 0; i < count; ++i )
{ {
if( !module->classTypes[i]->IsInterface() ) if( !module->m_classTypes[i]->IsInterface() )
WriteTypeDeclaration(module->classTypes[i], 2); WriteTypeDeclaration(module->m_classTypes[i], 2);
} }
} }
@ -3880,8 +3964,8 @@ int asCWriter::Write()
for( i = 0; i < count; ++i ) for( i = 0; i < count; ++i )
{ {
if( !module->classTypes[i]->IsInterface() ) if( !module->m_classTypes[i]->IsInterface() )
WriteTypeDeclaration(module->classTypes[i], 3); WriteTypeDeclaration(module->m_classTypes[i], 3);
} }
} }
@ -3889,12 +3973,12 @@ int asCWriter::Write()
{ {
TimeIt("type defs"); TimeIt("type defs");
count = (asUINT)module->typeDefs.GetLength(); count = (asUINT)module->m_typeDefs.GetLength();
WriteEncodedInt64(count); WriteEncodedInt64(count);
for( i = 0; i < count; i++ ) for( i = 0; i < count; i++ )
{ {
WriteTypeDeclaration(module->typeDefs[i], 1); WriteTypeDeclaration(module->m_typeDefs[i], 1);
WriteTypeDeclaration(module->typeDefs[i], 2); WriteTypeDeclaration(module->m_typeDefs[i], 2);
} }
} }
@ -3902,9 +3986,9 @@ int asCWriter::Write()
{ {
TimeIt("script globals"); TimeIt("script globals");
count = (asUINT)module->scriptGlobals.GetSize(); count = (asUINT)module->m_scriptGlobals.GetSize();
WriteEncodedInt64(count); WriteEncodedInt64(count);
asCSymbolTable<asCGlobalProperty>::iterator it = module->scriptGlobals.List(); asCSymbolTable<asCGlobalProperty>::iterator it = module->m_scriptGlobals.List();
for( ; it; it++ ) for( ; it; it++ )
WriteGlobalProperty(*it); WriteGlobalProperty(*it);
} }
@ -3914,21 +3998,21 @@ int asCWriter::Write()
TimeIt("scriptFunctions"); TimeIt("scriptFunctions");
count = 0; count = 0;
for( i = 0; i < module->scriptFunctions.GetLength(); i++ ) for( i = 0; i < module->m_scriptFunctions.GetLength(); i++ )
if( module->scriptFunctions[i]->objectType == 0 ) if( module->m_scriptFunctions[i]->objectType == 0 )
count++; count++;
WriteEncodedInt64(count); WriteEncodedInt64(count);
for( i = 0; i < module->scriptFunctions.GetLength(); ++i ) for( i = 0; i < module->m_scriptFunctions.GetLength(); ++i )
if( module->scriptFunctions[i]->objectType == 0 ) if( module->m_scriptFunctions[i]->objectType == 0 )
WriteFunction(module->scriptFunctions[i]); WriteFunction(module->m_scriptFunctions[i]);
} }
// globalFunctions[] // globalFunctions[]
{ {
TimeIt("globalFunctions"); TimeIt("globalFunctions");
count = (int)module->globalFunctions.GetSize(); count = (int)module->m_globalFunctions.GetSize();
asCSymbolTable<asCScriptFunction>::iterator funcIt = module->globalFunctions.List(); asCSymbolTable<asCScriptFunction>::iterator funcIt = module->m_globalFunctions.List();
WriteEncodedInt64(count); WriteEncodedInt64(count);
while( funcIt ) while( funcIt )
{ {
@ -3941,12 +4025,12 @@ int asCWriter::Write()
{ {
TimeIt("bindInformations"); TimeIt("bindInformations");
count = (asUINT)module->bindInformations.GetLength(); count = (asUINT)module->m_bindInformations.GetLength();
WriteEncodedInt64(count); WriteEncodedInt64(count);
for( i = 0; i < count; ++i ) for( i = 0; i < count; ++i )
{ {
WriteFunction(module->bindInformations[i]->importedFunctionSignature); WriteFunction(module->m_bindInformations[i]->importedFunctionSignature);
WriteString(&module->bindInformations[i]->importFromModule); WriteString(&module->m_bindInformations[i]->importFromModule);
} }
} }
@ -4026,9 +4110,9 @@ void asCWriter::WriteUsedFunctions()
// Is the function from the module or the application? // Is the function from the module or the application?
c = func->module ? 'm' : 'a'; c = func->module ? 'm' : 'a';
// Functions and methods that are shared and not owned by the module can be // Functions and methods that are shared should be stored as 's' as the bytecode
// stored as 's' to tell the reader that these are received from other modules. // may be imported from other modules (even if the current module have received ownership)
if (c == 'm' && func->IsShared() && module->scriptFunctions.IndexOf(func) < 0 ) if (c == 'm' && func->IsShared() )
c = 's'; c = 's';
WriteData(&c, 1); WriteData(&c, 1);
@ -4164,13 +4248,13 @@ void asCWriter::WriteFunction(asCScriptFunction* func)
if( func->funcType == asFUNC_SCRIPT ) if( func->funcType == asFUNC_SCRIPT )
{ {
// Skip this for external shared entities // Skip this for external shared entities
if (module->externalTypes.IndexOf(func->objectType) >= 0) if (module->m_externalTypes.IndexOf(func->objectType) >= 0)
return; return;
char bits = 0; char bits = 0;
bits += func->IsShared() ? 1 : 0; bits += func->IsShared() ? 1 : 0;
bits += func->dontCleanUpOnException ? 2 : 0; bits += func->dontCleanUpOnException ? 2 : 0;
if (module->externalFunctions.IndexOf(func) >= 0) if (module->m_externalFunctions.IndexOf(func) >= 0)
bits += 4; bits += 4;
if (func->scriptData->objVariablePos.GetLength() || func->scriptData->objVariableInfo.GetLength()) if (func->scriptData->objVariablePos.GetLength() || func->scriptData->objVariableInfo.GetLength())
bits += 8; bits += 8;
@ -4305,7 +4389,7 @@ void asCWriter::WriteFunction(asCScriptFunction* func)
{ {
char bits = 0; char bits = 0;
bits += func->IsShared() ? 1 : 0; bits += func->IsShared() ? 1 : 0;
if (module->externalTypes.IndexOf(func->funcdefType) >= 0) if (module->m_externalTypes.IndexOf(func->funcdefType) >= 0)
bits += 2; bits += 2;
WriteData(&bits,1); WriteData(&bits,1);
} }
@ -4343,7 +4427,7 @@ void asCWriter::WriteTypeDeclaration(asCTypeInfo *type, int phase)
if ((type->flags & asOBJ_SHARED)) if ((type->flags & asOBJ_SHARED))
{ {
char c = ' '; char c = ' ';
if (module->externalTypes.IndexOf(type) >= 0) if (module->m_externalTypes.IndexOf(type) >= 0)
c = 'e'; c = 'e';
WriteData(&c, 1); WriteData(&c, 1);
} }
@ -4351,7 +4435,7 @@ void asCWriter::WriteTypeDeclaration(asCTypeInfo *type, int phase)
else if( phase == 2 ) else if( phase == 2 )
{ {
// external shared types doesn't need to save this // 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; return;
if(type->flags & asOBJ_ENUM ) if(type->flags & asOBJ_ENUM )
@ -4429,7 +4513,7 @@ void asCWriter::WriteTypeDeclaration(asCTypeInfo *type, int phase)
else if( phase == 3 ) else if( phase == 3 )
{ {
// external shared types doesn't need to save this // 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; return;
// properties[] // properties[]
@ -5046,8 +5130,8 @@ void asCWriter::WriteByteCode(asCScriptFunction *func)
{ {
// Translate the function id // Translate the function id
int funcId = tmpBC[1]; int funcId = tmpBC[1];
for( asUINT n = 0; n < module->bindInformations.GetLength(); n++ ) for( asUINT n = 0; n < module->m_bindInformations.GetLength(); n++ )
if( module->bindInformations[n]->importedFunctionSignature->id == funcId ) if( module->m_bindInformations[n]->importedFunctionSignature->id == funcId )
{ {
funcId = n; funcId = n;
break; break;

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any warranty. In no event will the authors be held liable for any
@ -218,6 +218,9 @@ AS_API const char * asGetLibraryOptions()
#endif #endif
#ifdef AS_SPARC #ifdef AS_SPARC
"AS_SPARC " "AS_SPARC "
#endif
#ifdef AS_ARM64
"AS_ARM64 "
#endif #endif
; ;
@ -919,15 +922,15 @@ asCModule *asCScriptEngine::FindNewOwnerForSharedType(asCTypeInfo *in_type, asCM
asCModule *mod = scriptModules[n]; asCModule *mod = scriptModules[n];
if( mod == in_type->module ) continue; if( mod == in_type->module ) continue;
if( in_type->flags & asOBJ_ENUM ) 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) 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) 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) else if (in_type->flags & asOBJ_TEMPLATE)
foundIdx = mod->templateInstances.IndexOf(CastToObjectType(in_type)); foundIdx = mod->m_templateInstances.IndexOf(CastToObjectType(in_type));
else else
foundIdx = mod->classTypes.IndexOf(CastToObjectType(in_type)); foundIdx = mod->m_classTypes.IndexOf(CastToObjectType(in_type));
if( foundIdx >= 0 ) if( foundIdx >= 0 )
{ {
@ -948,13 +951,30 @@ asCModule *asCScriptEngine::FindNewOwnerForSharedFunc(asCScriptFunction *in_func
if( in_func->module != in_mod) if( in_func->module != in_mod)
return in_func->module; 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++ ) for( asUINT n = 0; n < scriptModules.GetLength(); n++ )
{ {
// TODO: optimize: If the modules already stored the shared types separately, this would be quicker // TODO: optimize: If the modules already stored the shared types separately, this would be quicker
int foundIdx = -1; int foundIdx = -1;
asCModule *mod = scriptModules[n]; asCModule *mod = scriptModules[n];
if( mod == in_func->module ) continue; if( mod == in_func->module ) continue;
foundIdx = mod->scriptFunctions.IndexOf(in_func); foundIdx = mod->m_scriptFunctions.IndexOf(in_func);
if( foundIdx >= 0 ) if( foundIdx >= 0 )
{ {
@ -1495,7 +1515,9 @@ int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declara
prop->isCompositeIndirect = isCompositeIndirect; prop->isCompositeIndirect = isCompositeIndirect;
prop->accessMask = defaultAccessMask; 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 // Add references to types so they are not released too early
if( type.GetTypeInfo() ) if( type.GetTypeInfo() )
@ -1509,7 +1531,8 @@ int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declara
currentGroup->AddReferencesForType(this, type.GetTypeInfo()); currentGroup->AddReferencesForType(this, type.GetTypeInfo());
return asSUCCESS; // Return the index of the property to signal success
return idx;
} }
// interface // interface
@ -2111,6 +2134,8 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as
} }
else if( behaviour == asBEHAVE_LIST_CONSTRUCT ) else if( behaviour == asBEHAVE_LIST_CONSTRUCT )
{ {
func.name = "$list";
// Verify that the return type is void // Verify that the return type is void
if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) ) 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 ) 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 // Must be a ref type and must not have asOBJ_NOHANDLE
if( !(objectType->flags & asOBJ_REF) || (objectType->flags & 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); prop->SetRegisteredAddress(pointer);
varAddressMap.Insert(prop->GetAddressOfValue(), prop); varAddressMap.Insert(prop->GetAddressOfValue(), prop);
registeredGlobalProps.Put(prop); asUINT idx = registeredGlobalProps.Put(prop);
prop->AddRef(); prop->AddRef();
currentGroup->globalProps.PushLast(prop); currentGroup->globalProps.PushLast(prop);
currentGroup->AddReferencesForType(this, type.GetTypeInfo()); currentGroup->AddReferencesForType(this, type.GetTypeInfo());
return asSUCCESS; // Return the index of the property to signal success
return int(idx);
} }
// internal // internal
@ -2650,10 +2679,13 @@ int asCScriptEngine::GetGlobalPropertyByIndex(asUINT index, const char **name, c
} }
// interface // 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 // Find the global var id
while( ns ) while( ns )
{ {
@ -3254,13 +3286,13 @@ asCModule *asCScriptEngine::GetModule(const char *name, bool create)
asCModule *retModule = 0; asCModule *retModule = 0;
ACQUIRESHARED(engineRWLock); ACQUIRESHARED(engineRWLock);
if( lastModule && lastModule->name == name ) if( lastModule && lastModule->m_name == name )
retModule = lastModule; retModule = lastModule;
else else
{ {
// TODO: optimize: Improve linear search // TODO: optimize: Improve linear search
for( asUINT n = 0; n < scriptModules.GetLength(); ++n ) 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]; retModule = scriptModules[n];
break; 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 // It may be without ownership if it was previously created from application with for example GetTypeInfoByDecl
type->module = requestingModule; 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(); type->AddRefInternal();
} }
} }
@ -3418,7 +3450,7 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT
{ {
// Set the ownership of this template type // Set the ownership of this template type
ot->module = requestingModule; ot->module = requestingModule;
requestingModule->templateInstances.PushLast(ot); requestingModule->m_templateInstances.PushLast(ot);
ot->AddRefInternal(); ot->AddRefInternal();
} }
else else
@ -3434,7 +3466,7 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT
ot->module = subTypes[n].GetTypeInfo()->module; ot->module = subTypes[n].GetTypeInfo()->module;
if( ot->module ) if( ot->module )
{ {
ot->module->templateInstances.PushLast(ot); ot->module->m_templateInstances.PushLast(ot);
ot->AddRefInternal(); ot->AddRefInternal();
break; break;
} }
@ -3458,7 +3490,7 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT
ot->templateSubTypes.SetLength(0); ot->templateSubTypes.SetLength(0);
if( ot->module ) if( ot->module )
{ {
ot->module->templateInstances.RemoveValue(ot); ot->module->m_templateInstances.RemoveValue(ot);
ot->ReleaseInternal(); ot->ReleaseInternal();
} }
ot->ReleaseInternal(); ot->ReleaseInternal();
@ -5778,7 +5810,7 @@ asCFuncdefType *asCScriptEngine::FindMatchingFuncdef(asCScriptFunction *func, as
// Add the new funcdef to the module so it will // Add the new funcdef to the module so it will
// be available when saving the bytecode // be available when saving the bytecode
funcDef->module = module; 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 // 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 // Unless this is a registered funcDef the returned funcDef must
// be stored as part of the module for saving/loading bytecode // 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(); funcDef->AddRefInternal();
} }
else else
@ -6026,9 +6058,13 @@ asITypeInfo *asCScriptEngine::GetObjectTypeByIndex(asUINT index) const
} }
// interface // 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) while (ns)
{ {
// Check the object types // Check the object types
@ -6071,6 +6107,49 @@ asITypeInfo *asCScriptEngine::GetTypeInfoByName(const char *name) const
return 0; 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 // interface
asITypeInfo *asCScriptEngine::GetTypeInfoById(int typeId) const asITypeInfo *asCScriptEngine::GetTypeInfoById(int typeId) const
{ {

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any warranty. In no event will the authors be held liable for any
@ -305,6 +305,8 @@ public:
asCFuncdefType *FindMatchingFuncdef(asCScriptFunction *func, asCModule *mod); asCFuncdefType *FindMatchingFuncdef(asCScriptFunction *func, asCModule *mod);
int DetermineNameAndNamespace(const char *in_name, asSNameSpace *implicitNs, asCString &out_name, asSNameSpace *&out_ns) const;
// Global property management // Global property management
asCGlobalProperty *AllocateGlobalProperty(); asCGlobalProperty *AllocateGlobalProperty();
void RemoveGlobalProperty(asCGlobalProperty *prop); void RemoveGlobalProperty(asCGlobalProperty *prop);

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any 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 const char *asCScriptFunction::GetModuleName() const
{ {
if( module ) if( module )
{ return module->GetName();
return module->name.AddressOf();
}
return 0; return 0;
} }

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any 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) 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 // 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 // derives from this type as the member properties may not have the same layout
asIScriptContext *ctx = asGetActiveContext(); asIScriptContext *ctx = asGetActiveContext();
ctx->SetException(TXT_MISMATCH_IN_VALUE_ASSIGN); ctx->SetException(TXT_MISMATCH_IN_VALUE_ASSIGN);
return *this; return asERROR;
} }
// If the script class implements the opAssign method, it should be called // If the script class implements the opAssign method, it should be called
asCScriptEngine *engine = objType->engine; asCScriptEngine *engine = in_objType->engine;
asCScriptFunction *func = engine->scriptFunctions[objType->beh.copy]; asCScriptFunction *func = engine->scriptFunctions[in_objType->beh.copy];
if( func->funcType == asFUNC_SYSTEM ) if( func->funcType == asFUNC_SYSTEM )
{ {
// Copy all properties // If derived, use the base class' assignment operator to copy the inherited
for( asUINT n = 0; n < objType->properties.GetLength(); n++ ) // 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() ) if( prop->type.IsObject() )
{ {
void **dst = (void**)(((char*)this) + prop->byteOffset); 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.IsObjectHandle() )
{ {
if( prop->type.IsReference() || (prop->type.GetTypeInfo()->flags & asOBJ_REF) ) 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()) else if (prop->type.IsFuncdef())
{ {
asCScriptFunction **dst = (asCScriptFunction**)(((char*)this) + prop->byteOffset); asCScriptFunction **dst = (asCScriptFunction**)(((char*)this) + prop->byteOffset);
asCScriptFunction **src = (asCScriptFunction**)(((char*)&other) + prop->byteOffset); asCScriptFunction **src = (asCScriptFunction**)(((char*)other) + prop->byteOffset);
if (*dst) if (*dst)
(*dst)->Release(); (*dst)->Release();
*dst = *src; *dst = *src;
@ -935,7 +948,7 @@ asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other)
else else
{ {
void *dst = ((char*)this) + prop->byteOffset; void *dst = ((char*)this) + prop->byteOffset;
void *src = ((char*)&other) + prop->byteOffset; void *src = ((char*)other) + prop->byteOffset;
memcpy(dst, src, prop->type.GetSizeInMemoryBytes()); memcpy(dst, src, prop->type.GetSizeInMemoryBytes());
} }
} }
@ -961,24 +974,20 @@ asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other)
// Request a context from the engine // Request a context from the engine
ctx = engine->RequestContext(); ctx = engine->RequestContext();
if( ctx == 0 ) if( ctx == 0 )
{ return asERROR;
// TODO: How to best report this failure?
return *this;
}
} }
r = ctx->Prepare(engine->scriptFunctions[objType->beh.copy]); r = ctx->Prepare(engine->scriptFunctions[in_objType->beh.copy]);
if( r < 0 ) if( r < 0 )
{ {
if( isNested ) if( isNested )
ctx->PopState(); ctx->PopState();
else else
engine->ReturnContext(ctx); engine->ReturnContext(ctx);
// TODO: How to best report this failure? return r;
return *this;
} }
r = ctx->SetArgAddress(0, const_cast<asCScriptObject*>(&other)); r = ctx->SetArgAddress(0, const_cast<asCScriptObject*>(other));
asASSERT( r >= 0 ); asASSERT( r >= 0 );
r = ctx->SetObject(this); r = ctx->SetObject(this);
asASSERT( r >= 0 ); asASSERT( r >= 0 );
@ -1014,7 +1023,7 @@ asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other)
// Return the context to the engine // Return the context to the engine
engine->ReturnContext(ctx); engine->ReturnContext(ctx);
} }
return *this; return asERROR;
} }
if( isNested ) 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; if( other == 0 ) return asINVALID_ARG;
@ -1039,7 +1048,7 @@ int asCScriptObject::CopyFrom(asIScriptObject *other)
*this = *(asCScriptObject*)other; *this = *(asCScriptObject*)other;
return 0; return asSUCCESS;
} }
void *asCScriptObject::AllocateUninitializedObject(asCObjectType *in_objType, asCScriptEngine *engine) 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; int funcIndex = in_objType->beh.copy;
if( funcIndex ) if( funcIndex )
{ {
asCScriptFunction *func = engine->scriptFunctions[in_objType->beh.copy]; asCScriptFunction *func = engine->scriptFunctions[in_objType->beh.copy];
if( func->funcType == asFUNC_SYSTEM ) if( func->funcType == asFUNC_SYSTEM )
engine->CallObjectMethod(dst, src, funcIndex); engine->CallObjectMethod(dst, const_cast<void*>(src), funcIndex);
else else
{ {
// Call the script class' opAssign method // Call the script class' opAssign method
asASSERT(in_objType->flags & asOBJ_SCRIPT_OBJECT ); asASSERT(in_objType->flags & asOBJ_SCRIPT_OBJECT );
reinterpret_cast<asCScriptObject*>(dst)->CopyFrom(reinterpret_cast<asCScriptObject*>(src)); reinterpret_cast<asCScriptObject*>(dst)->CopyFrom(reinterpret_cast<const asCScriptObject*>(src));
} }
} }
else if( in_objType->size && (in_objType->flags & asOBJ_POD) ) else if( in_objType->size && (in_objType->flags & asOBJ_POD) )

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any warranty. In no event will the authors be held liable for any
@ -94,7 +94,7 @@ public:
// Miscellaneous // Miscellaneous
asIScriptEngine *GetEngine() const; asIScriptEngine *GetEngine() const;
int CopyFrom(asIScriptObject *other); int CopyFrom(const asIScriptObject *other);
// User data // User data
void *SetUserData(void *data, asPWORD type = 0); void *SetUserData(void *data, asPWORD type = 0);
@ -119,8 +119,9 @@ public:
// Used for properties // Used for properties
void *AllocateUninitializedObject(asCObjectType *objType, asCScriptEngine *engine); void *AllocateUninitializedObject(asCObjectType *objType, asCScriptEngine *engine);
void FreeObject(void *ptr, 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); void CopyHandle(asPWORD *src, asPWORD *dst, asCObjectType *objType, asCScriptEngine *engine);
int CopyFromAs(const asCScriptObject *other, asCObjectType *objType);
void CallDestructor(); void CallDestructor();

View File

@ -141,7 +141,7 @@ public:
private: private:
// Don't allow assignment // Don't allow assignment
asCSymbolTable<T>& operator=(const asCSymbolTable<T> &) { return *this; } asCSymbolTable<T>& operator=(const asCSymbolTable<T> &other) { return *this; }
friend class asCSymbolTableIterator<T, T>; friend class asCSymbolTableIterator<T, T>;
friend class asCSymbolTableIterator<T, const T>; friend class asCSymbolTableIterator<T, const T>;

View File

@ -1,6 +1,6 @@
/* /*
AngelCode Scripting Library 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any 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); asASSERT(func->funcdefType == 0);
// A function pointer is special kind of reference type // 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; name = func->name;
nameSpace = func->nameSpace; nameSpace = func->nameSpace;
module = func->module; module = func->module;

View File

@ -57,7 +57,6 @@ function registerFiles(directoryName: string) {
const filepath = directoryName + path.sep + file; const filepath = directoryName + path.sep + file;
var uri = "file://" + filepath; var uri = "file://" + filepath;
if (!allFiles.get(uri)) { if (!allFiles.get(uri)) {
connection.console.log("Loaded new file at uri " + uri);
let td = TextDocument.create(uri, "Angelscript", 0, fs.readFileSync(filepath, 'utf8')); let td = TextDocument.create(uri, "Angelscript", 0, fs.readFileSync(filepath, 'utf8'));
allFiles.set(uri, td); allFiles.set(uri, td);
} }
@ -168,9 +167,9 @@ function loadScript(textDocument: TextDocument): void {
async function validateBuild(): Promise<void> { async function validateBuild(): Promise<void> {
var r = database.build(); var r = database.build();
if (r < -1) { if (r < -1) {
connection.console.log(r.toString()); console.log(r.toString());
} }
connection.console.log("Building"); console.log("Building");
var messages = database.messages(); var messages = database.messages();
let diagnostics: Map<string, Diagnostic[]> = new Map<string, Diagnostic[]>(); let diagnostics: Map<string, Diagnostic[]> = new Map<string, Diagnostic[]>();