mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-01-31 01:47:16 +01:00
Initial implementation of constant-time type-info.
Since I gave up on the possibility of multiple VMs. It allows me to take a risky optimization and avoid unnecessary table lookups.
This commit is contained in:
parent
b31030e77b
commit
b0bbb05631
@ -99,15 +99,17 @@ public:
|
|||||||
|
|
||||||
ClassData<C>* cd = *ud;
|
ClassData<C>* cd = *ud;
|
||||||
|
|
||||||
if (ClassType<C>::getStaticClassData().Expired()) {
|
//if (ClassType<C>::getStaticClassData().Expired()) {
|
||||||
|
if (!ClassType<C>::getStaticClassData()) {
|
||||||
cd->staticData.Init(new StaticClassData<C, void>);
|
cd->staticData.Init(new StaticClassData<C, void>);
|
||||||
cd->staticData->copyFunc = &A::Copy;
|
cd->staticData->copyFunc = &A::Copy;
|
||||||
cd->staticData->className = string(className);
|
cd->staticData->className = string(className);
|
||||||
cd->staticData->baseClass = nullptr;
|
cd->staticData->baseClass = nullptr;
|
||||||
|
|
||||||
ClassType<C>::getStaticClassData() = cd->staticData;
|
//ClassType<C>::getStaticClassData() = cd->staticData;
|
||||||
} else {
|
} else {
|
||||||
cd->staticData = ClassType<C>::getStaticClassData().Lock();
|
//cd->staticData = ClassType<C>::getStaticClassData().Lock();
|
||||||
|
throw Exception("investigate me!");
|
||||||
}
|
}
|
||||||
|
|
||||||
HSQOBJECT& classObj = cd->classObj;
|
HSQOBJECT& classObj = cd->classObj;
|
||||||
|
@ -41,7 +41,7 @@ namespace Sqrat
|
|||||||
// The copy function for a class
|
// The copy function for a class
|
||||||
typedef SQInteger (*COPYFUNC)(HSQUIRRELVM, SQInteger, const void*);
|
typedef SQInteger (*COPYFUNC)(HSQUIRRELVM, SQInteger, const void*);
|
||||||
|
|
||||||
// Every Squirrel class instance made by Sqrat has its type tag set to a AbstractStaticClassData object that is unique per C++ class
|
//Obsolete: Every Squirrel class instance made by Sqrat has its type tag set to a AbstractStaticClassData object that is unique per C++ class
|
||||||
struct AbstractStaticClassData {
|
struct AbstractStaticClassData {
|
||||||
AbstractStaticClassData() = default;
|
AbstractStaticClassData() = default;
|
||||||
virtual ~AbstractStaticClassData() = default;
|
virtual ~AbstractStaticClassData() = default;
|
||||||
@ -51,10 +51,30 @@ struct AbstractStaticClassData {
|
|||||||
COPYFUNC copyFunc{};
|
COPYFUNC copyFunc{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Optimization technique with certain risks and requirements. Read the warnings.
|
||||||
|
// Provides an application-wide unique pointer for types and is used as an identification method.
|
||||||
|
template<class T>
|
||||||
|
struct StaticClassTypeTag {
|
||||||
|
StaticClassTypeTag() noexcept = default;
|
||||||
|
/* @WARNING : this makes the assumption that one (and only one) VM exists at once. which in this application is actually true. */
|
||||||
|
static AbstractStaticClassData* TAG;
|
||||||
|
// We don't need these:
|
||||||
|
StaticClassTypeTag(const StaticClassTypeTag&) = delete;
|
||||||
|
StaticClassTypeTag(StaticClassTypeTag&&) = delete;
|
||||||
|
StaticClassTypeTag& operator=(const StaticClassTypeTag&) = delete;
|
||||||
|
StaticClassTypeTag& operator=(StaticClassTypeTag&&) = delete;
|
||||||
|
// Just so we don't have to access it directly.
|
||||||
|
static inline AbstractStaticClassData* Get() noexcept { return TAG; }
|
||||||
|
};
|
||||||
|
// We provide initial unique tag to prevent any collision with null.
|
||||||
|
template<class T> AbstractStaticClassData* StaticClassTypeTag<T>::TAG=nullptr;
|
||||||
|
|
||||||
// StaticClassData keeps track of the nearest base class B and the class associated with itself C in order to cast C++ pointers to the right base class
|
// StaticClassData keeps track of the nearest base class B and the class associated with itself C in order to cast C++ pointers to the right base class
|
||||||
template<class C, class B>
|
template<class C, class B>
|
||||||
struct StaticClassData : public AbstractStaticClassData {
|
struct StaticClassData : public AbstractStaticClassData, public StaticClassTypeTag<C> {
|
||||||
virtual SQUserPointer Cast(SQUserPointer ptr, SQUserPointer classType) {
|
StaticClassData() : AbstractStaticClassData() { StaticClassTypeTag<C>::TAG = static_cast<AbstractStaticClassData*>(this); }
|
||||||
|
~StaticClassData() override { StaticClassTypeTag<C>::TAG = nullptr; }
|
||||||
|
SQUserPointer Cast(SQUserPointer ptr, SQUserPointer classType) override {
|
||||||
if (classType != this) {
|
if (classType != this) {
|
||||||
ptr = baseClass->Cast(static_cast<B*>(static_cast<C*>(ptr)), classType);
|
ptr = baseClass->Cast(static_cast<B*>(static_cast<C*>(ptr)), classType);
|
||||||
}
|
}
|
||||||
@ -65,14 +85,15 @@ struct StaticClassData : public AbstractStaticClassData {
|
|||||||
// Every Squirrel class object created by Sqrat in every VM has its own unique ClassData object stored in the registry table of the VM
|
// Every Squirrel class object created by Sqrat in every VM has its own unique ClassData object stored in the registry table of the VM
|
||||||
template<class C>
|
template<class C>
|
||||||
struct ClassData {
|
struct ClassData {
|
||||||
HSQOBJECT classObj;
|
HSQOBJECT classObj{};
|
||||||
HSQOBJECT getTable;
|
HSQOBJECT getTable{};
|
||||||
HSQOBJECT setTable;
|
HSQOBJECT setTable{};
|
||||||
SharedPtr<std::unordered_map<C*, HSQOBJECT>> instances;
|
SharedPtr<std::unordered_map<C*, HSQOBJECT>> instances;
|
||||||
SharedPtr<AbstractStaticClassData> staticData;
|
SharedPtr<AbstractStaticClassData> staticData;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Lookup static class data by type_info rather than a template because C++ cannot export generic templates
|
// Lookup static class data by type_info rather than a template because C++ cannot export generic templates
|
||||||
|
/*
|
||||||
class _ClassType_helper {
|
class _ClassType_helper {
|
||||||
public:
|
public:
|
||||||
#if defined(SCRAT_IMPORT)
|
#if defined(SCRAT_IMPORT)
|
||||||
@ -89,6 +110,7 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
// Internal helper class for managing classes
|
// Internal helper class for managing classes
|
||||||
template<class C>
|
template<class C>
|
||||||
@ -117,12 +139,16 @@ public:
|
|||||||
return *ud;
|
return *ud;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WeakPtr<AbstractStaticClassData>& getStaticClassData() {
|
//static WeakPtr<AbstractStaticClassData>& getStaticClassData() {
|
||||||
return _ClassType_helper::_getStaticClassData(&typeid(C));
|
// return _ClassType_helper::_getStaticClassData(&typeid(C));
|
||||||
|
//}
|
||||||
|
static AbstractStaticClassData* getStaticClassData() {
|
||||||
|
return StaticClassTypeTag<C>::Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool hasClassData(HSQUIRRELVM vm) {
|
static inline bool hasClassData(HSQUIRRELVM vm) {
|
||||||
if (!getStaticClassData().Expired()) {
|
//if (!getStaticClassData().Expired()) {
|
||||||
|
if (StaticClassTypeTag<C>::Get()!=nullptr) {
|
||||||
sq_pushregistrytable(vm);
|
sq_pushregistrytable(vm);
|
||||||
sq_pushstring(vm, "__classes", -1);
|
sq_pushstring(vm, "__classes", -1);
|
||||||
if (SQ_SUCCEEDED(sq_rawget(vm, -2))) {
|
if (SQ_SUCCEEDED(sq_rawget(vm, -2))) {
|
||||||
@ -138,24 +164,39 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static inline AbstractStaticClassData*& BaseClass() {
|
||||||
|
// assert(!getStaticClassData().Expired()); // fails because called before a Sqrat::Class for this type exists
|
||||||
|
// return getStaticClassData().Lock()->baseClass;
|
||||||
|
//}
|
||||||
|
|
||||||
static inline AbstractStaticClassData*& BaseClass() {
|
static inline AbstractStaticClassData*& BaseClass() {
|
||||||
assert(!getStaticClassData().Expired()); // fails because called before a Sqrat::Class for this type exists
|
assert(StaticClassTypeTag<C>::Get()); // fails because called before a Sqrat::Class for this type exists
|
||||||
return getStaticClassData().Lock()->baseClass;
|
return StaticClassTypeTag<C>::Get()->baseClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static inline string& ClassName() {
|
||||||
|
// assert(!getStaticClassData().Expired()); // fails because called before a Sqrat::Class for this type exists
|
||||||
|
// return getStaticClassData().Lock()->className;
|
||||||
|
//}
|
||||||
|
|
||||||
static inline string& ClassName() {
|
static inline string& ClassName() {
|
||||||
assert(!getStaticClassData().Expired()); // fails because called before a Sqrat::Class for this type exists
|
assert(StaticClassTypeTag<C>::Get()); // fails because called before a Sqrat::Class for this type exists
|
||||||
return getStaticClassData().Lock()->className;
|
return StaticClassTypeTag<C>::Get()->className;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static inline COPYFUNC& CopyFunc() {
|
||||||
|
// assert(!getStaticClassData().Expired()); // fails because called before a Sqrat::Class for this type exists
|
||||||
|
// return getStaticClassData().Lock()->copyFunc;
|
||||||
|
//}
|
||||||
|
|
||||||
static inline COPYFUNC& CopyFunc() {
|
static inline COPYFUNC& CopyFunc() {
|
||||||
assert(!getStaticClassData().Expired()); // fails because called before a Sqrat::Class for this type exists
|
assert(StaticClassTypeTag<C>::Get()); // fails because called before a Sqrat::Class for this type exists
|
||||||
return getStaticClassData().Lock()->copyFunc;
|
return StaticClassTypeTag<C>::Get()->copyFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SQInteger DeleteInstance(SQUserPointer ptr, SQInteger size) {
|
static SQInteger DeleteInstance(SQUserPointer ptr, SQInteger size) {
|
||||||
SQUNUSED(size);
|
SQUNUSED(size);
|
||||||
std::pair<C*, SharedPtr<std::unordered_map<C*, HSQOBJECT>> >* instance = reinterpret_cast<std::pair<C*, SharedPtr<std::unordered_map<C*, HSQOBJECT>> >*>(ptr);
|
auto* instance = reinterpret_cast<std::pair<C*, SharedPtr<std::unordered_map<C*, HSQOBJECT>> >*>(ptr);
|
||||||
instance->second->erase(instance->first);
|
instance->second->erase(instance->first);
|
||||||
delete instance;
|
delete instance;
|
||||||
return 0;
|
return 0;
|
||||||
@ -204,7 +245,8 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
classType = getStaticClassData().Lock().Get();
|
//classType = getStaticClassData().Lock().Get();
|
||||||
|
classType = StaticClassTypeTag<C>::Get();
|
||||||
|
|
||||||
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
#if !defined (SCRAT_NO_ERROR_CHECKING)
|
||||||
if (SQ_FAILED(sq_getinstanceup(vm, idx, (SQUserPointer*)&instance, classType))) {
|
if (SQ_FAILED(sq_getinstanceup(vm, idx, (SQUserPointer*)&instance, classType))) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user