Optimize CSharp scripting runtime to use arena allocator per-assembly
This commit is contained in:
@@ -78,7 +78,7 @@ namespace ScriptsBuilderImpl
|
||||
void onScriptsReloadEnd();
|
||||
void onScriptsLoaded();
|
||||
|
||||
void GetClassName(const StringAnsi& fullname, StringAnsi& className);
|
||||
void GetClassName(const StringAnsiView fullname, StringAnsi& className);
|
||||
|
||||
void onCodeEditorAsyncOpenBegin()
|
||||
{
|
||||
@@ -273,7 +273,7 @@ bool ScriptsBuilder::GenerateProject(const StringView& customArgs)
|
||||
return RunBuildTool(args);
|
||||
}
|
||||
|
||||
void ScriptsBuilderImpl::GetClassName(const StringAnsi& fullname, StringAnsi& className)
|
||||
void ScriptsBuilderImpl::GetClassName(const StringAnsiView fullname, StringAnsi& className)
|
||||
{
|
||||
const auto lastDotIndex = fullname.FindLast('.');
|
||||
if (lastDotIndex != -1)
|
||||
|
||||
@@ -44,9 +44,19 @@ public:
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Invokes destructor on values in an array and clears it.
|
||||
template<typename Value, typename Allocator>
|
||||
static void ClearDelete(Array<Value, Allocator>& collection)
|
||||
{
|
||||
Value* ptr = collection.Get();
|
||||
for (int32 i = 0; i < collection.Count(); i++)
|
||||
Memory::DestructItem(ptr[i]);
|
||||
collection.Clear();
|
||||
}
|
||||
|
||||
// Invokes destructor on values in a dictionary and clears it.
|
||||
template<typename Key, typename Value, typename Allocator>
|
||||
void ClearDelete(Dictionary<Key, Value, Allocator>& collection)
|
||||
static void ClearDelete(Dictionary<Key, Value, Allocator>& collection)
|
||||
{
|
||||
for (auto it = collection.Begin(); it.IsNotEnd(); ++it)
|
||||
Memory::DestructItem(it->Value);
|
||||
|
||||
@@ -118,7 +118,7 @@ VariantType::VariantType(Types type, const MClass* klass)
|
||||
#if USE_CSHARP
|
||||
if (klass)
|
||||
{
|
||||
const StringAnsi& typeName = klass->GetFullName();
|
||||
const StringAnsiView typeName = klass->GetFullName();
|
||||
const int32 length = typeName.Length();
|
||||
TypeName = static_cast<char*>(Allocator::Allocate(length + 1));
|
||||
Platform::MemoryCopy(TypeName, typeName.Get(), length);
|
||||
|
||||
@@ -215,7 +215,7 @@ namespace
|
||||
{
|
||||
if (!method->IsStatic())
|
||||
continue;
|
||||
const StringAnsi& name = method->GetName();
|
||||
const StringAnsiView name = method->GetName();
|
||||
if (name.Contains("Internal_") ||
|
||||
mclass->GetFullName().Contains(".Interop."))
|
||||
continue;
|
||||
|
||||
@@ -1029,7 +1029,7 @@ void ManagedBinaryModule::InitType(MClass* mclass)
|
||||
{
|
||||
#if !COMPILE_WITHOUT_CSHARP
|
||||
// Skip if already initialized
|
||||
const StringAnsi& typeName = mclass->GetFullName();
|
||||
const StringAnsiView typeName = mclass->GetFullName();
|
||||
if (TypeNameToTypeIndex.ContainsKey(typeName))
|
||||
return;
|
||||
PROFILE_MEM(Scripting);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "Engine/Core/Types/String.h"
|
||||
#include "Engine/Core/Collections/Array.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "Engine/Core/Memory/ArenaAllocation.h"
|
||||
#include "Engine/Platform/CriticalSection.h"
|
||||
|
||||
/// <summary>
|
||||
@@ -19,7 +20,7 @@ class FLAXENGINE_API MAssembly
|
||||
friend Scripting;
|
||||
|
||||
public:
|
||||
typedef Dictionary<StringAnsi, MClass*> ClassesDictionary;
|
||||
typedef Dictionary<StringAnsiView, MClass*> ClassesDictionary;
|
||||
|
||||
private:
|
||||
#if USE_MONO
|
||||
@@ -67,6 +68,15 @@ public:
|
||||
/// </summary>
|
||||
~MAssembly();
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Memory storage with all assembly-related data that shares its lifetime (eg. metadata).
|
||||
/// </summary>
|
||||
ArenaAllocator Memory;
|
||||
|
||||
// Allocates the given string within a memory that has lifetime of assembly.
|
||||
StringAnsiView AllocString(const char* str);
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Managed assembly actions delegate type.
|
||||
|
||||
@@ -17,14 +17,13 @@ private:
|
||||
mutable void* _attrInfo = nullptr;
|
||||
#elif USE_NETCORE
|
||||
void* _handle;
|
||||
StringAnsi _name;
|
||||
StringAnsi _namespace;
|
||||
StringAnsiView _name;
|
||||
StringAnsiView _namespace;
|
||||
StringAnsiView _fullname;
|
||||
uint32 _types = 0;
|
||||
mutable uint32 _size = 0;
|
||||
#endif
|
||||
const MAssembly* _assembly;
|
||||
|
||||
StringAnsi _fullname;
|
||||
MAssembly* _assembly;
|
||||
|
||||
mutable Array<MMethod*> _methods;
|
||||
mutable Array<MField*> _fields;
|
||||
@@ -47,12 +46,13 @@ private:
|
||||
int32 _isInterface : 1;
|
||||
int32 _isValueType : 1;
|
||||
int32 _isEnum : 1;
|
||||
int32 _isGeneric : 1;
|
||||
|
||||
public:
|
||||
#if USE_MONO
|
||||
MClass(const MAssembly* parentAssembly, MonoClass* monoClass, const StringAnsi& fullname);
|
||||
#elif USE_NETCORE
|
||||
MClass(const MAssembly* parentAssembly, void* handle, const char* name, const char* fullname, const char* namespace_, MTypeAttributes typeAttributes);
|
||||
MClass(MAssembly* parentAssembly, void* handle, const char* name, const char* fullname, const char* namespace_, MTypeAttributes typeAttributes);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the parent assembly.
|
||||
/// </summary>
|
||||
const MAssembly* GetAssembly() const
|
||||
FORCE_INLINE MAssembly* GetAssembly() const
|
||||
{
|
||||
return _assembly;
|
||||
}
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the full name of the class (namespace and typename).
|
||||
/// </summary>
|
||||
FORCE_INLINE const StringAnsi& GetFullName() const
|
||||
FORCE_INLINE StringAnsiView GetFullName() const
|
||||
{
|
||||
return _fullname;
|
||||
}
|
||||
@@ -80,12 +80,18 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the name of the class.
|
||||
/// </summary>
|
||||
StringAnsiView GetName() const;
|
||||
FORCE_INLINE StringAnsiView GetName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the namespace of the class.
|
||||
/// </summary>
|
||||
StringAnsiView GetNamespace() const;
|
||||
FORCE_INLINE StringAnsiView GetNamespace() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
#if USE_MONO
|
||||
/// <summary>
|
||||
@@ -161,9 +167,9 @@ public:
|
||||
/// <summary>
|
||||
/// Gets if class is generic
|
||||
/// </summary>
|
||||
bool IsGeneric() const
|
||||
FORCE_INLINE bool IsGeneric() const
|
||||
{
|
||||
return _fullname.FindLast('`') != -1;
|
||||
return _isGeneric != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -71,6 +71,17 @@ MAssembly::~MAssembly()
|
||||
Unload();
|
||||
}
|
||||
|
||||
StringAnsiView MAssembly::AllocString(const char* str)
|
||||
{
|
||||
if (!str)
|
||||
return StringAnsiView::Empty;
|
||||
int32 len = StringUtils::Length(str);
|
||||
char* mem = (char*)Memory.Allocate(len + 1);
|
||||
Platform::MemoryCopy(mem, str, len);
|
||||
mem[len] = 0;
|
||||
return StringAnsiView(mem, len);
|
||||
}
|
||||
|
||||
String MAssembly::ToString() const
|
||||
{
|
||||
return _name.ToString();
|
||||
@@ -127,7 +138,11 @@ void MAssembly::Unload(bool isReloading)
|
||||
_isLoading = false;
|
||||
_isLoaded = false;
|
||||
_hasCachedClasses = false;
|
||||
#if USE_NETCORE
|
||||
ArenaAllocator::ClearDelete(_classes);
|
||||
#else
|
||||
_classes.ClearDelete();
|
||||
#endif
|
||||
|
||||
Unloaded(this);
|
||||
}
|
||||
|
||||
@@ -15,16 +15,16 @@ class FLAXENGINE_API MEvent
|
||||
protected:
|
||||
#if USE_MONO
|
||||
MonoEvent* _monoEvent;
|
||||
StringAnsi _name;
|
||||
#elif USE_NETCORE
|
||||
void* _handle;
|
||||
StringAnsiView _name;
|
||||
#endif
|
||||
|
||||
mutable MMethod* _addMethod;
|
||||
mutable MMethod* _removeMethod;
|
||||
MClass* _parentClass;
|
||||
|
||||
StringAnsi _name;
|
||||
|
||||
mutable int32 _hasCachedAttributes : 1;
|
||||
mutable int32 _hasAddMonoMethod : 1;
|
||||
mutable int32 _hasRemoveMonoMethod : 1;
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the event name.
|
||||
/// </summary>
|
||||
FORCE_INLINE const StringAnsi& GetName() const
|
||||
FORCE_INLINE StringAnsiView GetName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
@@ -17,14 +17,15 @@ protected:
|
||||
#if USE_MONO
|
||||
MonoClassField* _monoField;
|
||||
MonoType* _monoType;
|
||||
StringAnsi _name;
|
||||
#elif USE_NETCORE
|
||||
void* _handle;
|
||||
void* _type;
|
||||
int32 _fieldOffset;
|
||||
StringAnsiView _name;
|
||||
#endif
|
||||
|
||||
MClass* _parentClass;
|
||||
StringAnsi _name;
|
||||
|
||||
MVisibility _visibility;
|
||||
|
||||
@@ -44,7 +45,7 @@ public:
|
||||
/// <summary>
|
||||
/// Gets field name.
|
||||
/// </summary>
|
||||
FORCE_INLINE const StringAnsi& GetName() const
|
||||
FORCE_INLINE StringAnsiView GetName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
@@ -21,15 +21,16 @@ class FLAXENGINE_API MMethod
|
||||
protected:
|
||||
#if USE_MONO
|
||||
MonoMethod* _monoMethod;
|
||||
StringAnsi _name;
|
||||
#elif USE_NETCORE
|
||||
void* _handle;
|
||||
StringAnsiView _name;
|
||||
int32 _paramsCount;
|
||||
mutable void* _returnType;
|
||||
mutable Array<void*, InlinedAllocation<8>> _parameterTypes;
|
||||
void CacheSignature() const;
|
||||
#endif
|
||||
MClass* _parentClass;
|
||||
StringAnsi _name;
|
||||
MVisibility _visibility;
|
||||
#if !USE_MONO_AOT
|
||||
void* _cachedThunk = nullptr;
|
||||
@@ -48,12 +49,11 @@ public:
|
||||
explicit MMethod(MonoMethod* monoMethod, MClass* parentClass);
|
||||
explicit MMethod(MonoMethod* monoMethod, const char* name, MClass* parentClass);
|
||||
#elif USE_NETCORE
|
||||
MMethod(MClass* parentClass, StringAnsi&& name, void* handle, int32 paramsCount, MMethodAttributes attributes);
|
||||
MMethod(MClass* parentClass, StringAnsiView name, void* handle, int32 paramsCount, MMethodAttributes attributes);
|
||||
#endif
|
||||
|
||||
public:
|
||||
#if COMPILE_WITH_PROFILER
|
||||
StringAnsi ProfilerName;
|
||||
SourceLocationData ProfilerData;
|
||||
#endif
|
||||
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the method name.
|
||||
/// </summary>
|
||||
FORCE_INLINE const StringAnsi& GetName() const
|
||||
FORCE_INLINE StringAnsiView GetName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
@@ -17,16 +17,16 @@ class FLAXENGINE_API MProperty
|
||||
protected:
|
||||
#if USE_MONO
|
||||
MonoProperty* _monoProperty;
|
||||
StringAnsi _name;
|
||||
#elif USE_NETCORE
|
||||
void* _handle;
|
||||
StringAnsiView _name;
|
||||
#endif
|
||||
|
||||
mutable MMethod* _getMethod;
|
||||
mutable MMethod* _setMethod;
|
||||
MClass* _parentClass;
|
||||
|
||||
StringAnsi _name;
|
||||
|
||||
mutable int32 _hasCachedAttributes : 1;
|
||||
mutable int32 _hasSetMethod : 1;
|
||||
mutable int32 _hasGetMethod : 1;
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the property name.
|
||||
/// </summary>
|
||||
FORCE_INLINE const StringAnsi& GetName() const
|
||||
FORCE_INLINE StringAnsiView GetName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ ScriptingTypeHandle MUtils::UnboxScriptingTypeHandle(MTypeObject* value)
|
||||
MClass* klass = GetClass(value);
|
||||
if (!klass)
|
||||
return ScriptingTypeHandle();
|
||||
const StringAnsi& typeName = klass->GetFullName();
|
||||
const StringAnsiView typeName = klass->GetFullName();
|
||||
const ScriptingTypeHandle typeHandle = Scripting::FindScriptingType(typeName);
|
||||
if (!typeHandle)
|
||||
LOG(Warning, "Unknown scripting type {}", String(typeName));
|
||||
@@ -821,14 +821,14 @@ MObject* MUtils::BoxVariant(const Variant& value)
|
||||
}
|
||||
}
|
||||
|
||||
const StringAnsi& MUtils::GetClassFullname(MObject* obj)
|
||||
StringAnsiView MUtils::GetClassFullname(MObject* obj)
|
||||
{
|
||||
if (obj)
|
||||
{
|
||||
MClass* mClass = MCore::Object::GetClass(obj);
|
||||
return mClass->GetFullName();
|
||||
}
|
||||
return StringAnsi::Empty;
|
||||
return StringAnsiView::Empty;
|
||||
}
|
||||
|
||||
MClass* MUtils::GetClass(MTypeObject* type)
|
||||
|
||||
@@ -400,7 +400,7 @@ struct MConverter<Array<T>>
|
||||
namespace MUtils
|
||||
{
|
||||
// Outputs the full typename for the type of the specified object.
|
||||
extern FLAXENGINE_API const StringAnsi& GetClassFullname(MObject* obj);
|
||||
extern FLAXENGINE_API StringAnsiView GetClassFullname(MObject* obj);
|
||||
|
||||
// Returns the class of the provided object.
|
||||
extern FLAXENGINE_API MClass* GetClass(MObject* object);
|
||||
|
||||
@@ -183,7 +183,7 @@ Dictionary<void*, MAssembly*> CachedAssemblyHandles;
|
||||
/// <summary>
|
||||
/// Returns the function pointer to the managed static method in NativeInterop class.
|
||||
/// </summary>
|
||||
void* GetStaticMethodPointer(const String& methodName);
|
||||
void* GetStaticMethodPointer(StringView methodName);
|
||||
|
||||
/// <summary>
|
||||
/// Calls the managed static method with given parameters.
|
||||
@@ -753,12 +753,13 @@ const MAssembly::ClassesDictionary& MAssembly::GetClasses() const
|
||||
static void* GetManagedClassesPtr = GetStaticMethodPointer(TEXT("GetManagedClasses"));
|
||||
CallStaticMethod<void, void*, NativeClassDefinitions**, int*>(GetManagedClassesPtr, _handle, &managedClasses, &classCount);
|
||||
_classes.EnsureCapacity(classCount);
|
||||
MAssembly* assembly = const_cast<MAssembly*>(this);
|
||||
for (int32 i = 0; i < classCount; i++)
|
||||
{
|
||||
NativeClassDefinitions& managedClass = managedClasses[i];
|
||||
|
||||
// Create class object
|
||||
MClass* klass = New<MClass>(this, managedClass.typeHandle, managedClass.name, managedClass.fullname, managedClass.namespace_, managedClass.typeAttributes);
|
||||
MClass* klass = assembly->Memory.New<MClass>(assembly, managedClass.typeHandle, managedClass.name, managedClass.fullname, managedClass.namespace_, managedClass.typeAttributes);
|
||||
_classes.Add(klass->GetFullName(), klass);
|
||||
|
||||
managedClass.nativePointer = klass;
|
||||
@@ -811,7 +812,7 @@ DEFINE_INTERNAL_CALL(void) NativeInterop_CreateClass(NativeClassDefinitions* man
|
||||
CachedAssemblyHandles.Add(assemblyHandle, assembly);
|
||||
}
|
||||
|
||||
MClass* klass = New<MClass>(assembly, managedClass->typeHandle, managedClass->name, managedClass->fullname, managedClass->namespace_, managedClass->typeAttributes);
|
||||
MClass* klass = assembly->Memory.New<MClass>(assembly, managedClass->typeHandle, managedClass->name, managedClass->fullname, managedClass->namespace_, managedClass->typeAttributes);
|
||||
if (assembly != nullptr)
|
||||
{
|
||||
auto& classes = const_cast<MAssembly::ClassesDictionary&>(assembly->GetClasses());
|
||||
@@ -819,7 +820,7 @@ DEFINE_INTERNAL_CALL(void) NativeInterop_CreateClass(NativeClassDefinitions* man
|
||||
if (classes.TryGet(klass->GetFullName(), oldKlass))
|
||||
{
|
||||
LOG(Warning, "Class '{0}' was already added to assembly '{1}'", String(klass->GetFullName()), String(assembly->GetName()));
|
||||
Delete(klass);
|
||||
Memory::DestructItem(klass);
|
||||
klass = oldKlass;
|
||||
}
|
||||
else
|
||||
@@ -915,12 +916,12 @@ bool MAssembly::UnloadImage(bool isReloading)
|
||||
return false;
|
||||
}
|
||||
|
||||
MClass::MClass(const MAssembly* parentAssembly, void* handle, const char* name, const char* fullname, const char* namespace_, MTypeAttributes attributes)
|
||||
MClass::MClass(MAssembly* parentAssembly, void* handle, const char* name, const char* fullname, const char* namespace_, MTypeAttributes attributes)
|
||||
: _handle(handle)
|
||||
, _name(name)
|
||||
, _namespace(namespace_)
|
||||
, _name(parentAssembly->AllocString(name))
|
||||
, _namespace(parentAssembly->AllocString(namespace_))
|
||||
, _fullname(parentAssembly->AllocString(fullname))
|
||||
, _assembly(parentAssembly)
|
||||
, _fullname(fullname)
|
||||
, _hasCachedProperties(false)
|
||||
, _hasCachedFields(false)
|
||||
, _hasCachedMethods(false)
|
||||
@@ -967,6 +968,8 @@ MClass::MClass(const MAssembly* parentAssembly, void* handle, const char* name,
|
||||
static void* TypeIsEnumPtr = GetStaticMethodPointer(TEXT("TypeIsEnum"));
|
||||
_isEnum = CallStaticMethod<bool, void*>(TypeIsEnumPtr, handle);
|
||||
|
||||
_isGeneric = _fullname.FindLast('`') != -1;
|
||||
|
||||
CachedClassHandles[handle] = this;
|
||||
}
|
||||
|
||||
@@ -982,24 +985,14 @@ bool MAssembly::ResolveMissingFile(String& assemblyPath) const
|
||||
|
||||
MClass::~MClass()
|
||||
{
|
||||
_methods.ClearDelete();
|
||||
_fields.ClearDelete();
|
||||
_properties.ClearDelete();
|
||||
_events.ClearDelete();
|
||||
ArenaAllocator::ClearDelete(_methods);
|
||||
ArenaAllocator::ClearDelete(_fields);
|
||||
ArenaAllocator::ClearDelete(_properties);
|
||||
ArenaAllocator::ClearDelete(_events);
|
||||
|
||||
CachedClassHandles.Remove(_handle);
|
||||
}
|
||||
|
||||
StringAnsiView MClass::GetName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
StringAnsiView MClass::GetNamespace() const
|
||||
{
|
||||
return _namespace;
|
||||
}
|
||||
|
||||
MType* MClass::GetType() const
|
||||
{
|
||||
return (MType*)_handle;
|
||||
@@ -1071,10 +1064,11 @@ const Array<MMethod*>& MClass::GetMethods() const
|
||||
static void* GetClassMethodsPtr = GetStaticMethodPointer(TEXT("GetClassMethods"));
|
||||
CallStaticMethod<void, void*, NativeMethodDefinitions**, int*>(GetClassMethodsPtr, _handle, &methods, &methodsCount);
|
||||
_methods.Resize(methodsCount);
|
||||
MAssembly* assembly = const_cast<MAssembly*>(_assembly);
|
||||
for (int32 i = 0; i < methodsCount; i++)
|
||||
{
|
||||
NativeMethodDefinitions& definition = methods[i];
|
||||
MMethod* method = New<MMethod>(const_cast<MClass*>(this), StringAnsi(definition.name), definition.handle, definition.numParameters, definition.methodAttributes);
|
||||
MMethod* method = assembly->Memory.New<MMethod>(const_cast<MClass*>(this), assembly->AllocString(definition.name), definition.handle, definition.numParameters, definition.methodAttributes);
|
||||
_methods[i] = method;
|
||||
MCore::GC::FreeMemory((void*)definition.name);
|
||||
}
|
||||
@@ -1112,7 +1106,7 @@ const Array<MField*>& MClass::GetFields() const
|
||||
for (int32 i = 0; i < numFields; i++)
|
||||
{
|
||||
NativeFieldDefinitions& definition = fields[i];
|
||||
MField* field = New<MField>(const_cast<MClass*>(this), definition.fieldHandle, definition.name, definition.fieldType, definition.fieldOffset, definition.fieldAttributes);
|
||||
MField* field = _assembly->Memory.New<MField>(const_cast<MClass*>(this), definition.fieldHandle, definition.name, definition.fieldType, definition.fieldOffset, definition.fieldAttributes);
|
||||
_fields[i] = field;
|
||||
MCore::GC::FreeMemory((void*)definition.name);
|
||||
}
|
||||
@@ -1162,7 +1156,7 @@ const Array<MProperty*>& MClass::GetProperties() const
|
||||
for (int i = 0; i < numProperties; i++)
|
||||
{
|
||||
const NativePropertyDefinitions& definition = foundProperties[i];
|
||||
MProperty* property = New<MProperty>(const_cast<MClass*>(this), definition.name, definition.propertyHandle, definition.getterHandle, definition.setterHandle, definition.getterAttributes, definition.setterAttributes);
|
||||
MProperty* property = _assembly->Memory.New<MProperty>(const_cast<MClass*>(this), definition.name, definition.propertyHandle, definition.getterHandle, definition.setterHandle, definition.getterAttributes, definition.setterAttributes);
|
||||
_properties[i] = property;
|
||||
MCore::GC::FreeMemory((void*)definition.name);
|
||||
}
|
||||
@@ -1241,7 +1235,7 @@ MEvent::MEvent(MClass* parentClass, void* handle, const char* name)
|
||||
, _addMethod(nullptr)
|
||||
, _removeMethod(nullptr)
|
||||
, _parentClass(parentClass)
|
||||
, _name(name)
|
||||
, _name(parentClass->GetAssembly()->AllocString(name))
|
||||
, _hasCachedAttributes(false)
|
||||
, _hasAddMonoMethod(true)
|
||||
, _hasRemoveMonoMethod(true)
|
||||
@@ -1317,7 +1311,7 @@ MField::MField(MClass* parentClass, void* handle, const char* name, void* type,
|
||||
, _type(type)
|
||||
, _fieldOffset(fieldOffset)
|
||||
, _parentClass(parentClass)
|
||||
, _name(name)
|
||||
, _name(parentClass->GetAssembly()->AllocString(name))
|
||||
, _hasCachedAttributes(false)
|
||||
{
|
||||
switch (attributes & MFieldAttributes::FieldAccessMask)
|
||||
@@ -1409,11 +1403,11 @@ const Array<MObject*>& MField::GetAttributes() const
|
||||
return _attributes;
|
||||
}
|
||||
|
||||
MMethod::MMethod(MClass* parentClass, StringAnsi&& name, void* handle, int32 paramsCount, MMethodAttributes attributes)
|
||||
MMethod::MMethod(MClass* parentClass, StringAnsiView name, void* handle, int32 paramsCount, MMethodAttributes attributes)
|
||||
: _handle(handle)
|
||||
, _paramsCount(paramsCount)
|
||||
, _parentClass(parentClass)
|
||||
, _name(MoveTemp(name))
|
||||
, _name(name)
|
||||
, _hasCachedAttributes(false)
|
||||
, _hasCachedSignature(false)
|
||||
{
|
||||
@@ -1443,13 +1437,15 @@ MMethod::MMethod(MClass* parentClass, StringAnsi&& name, void* handle, int32 par
|
||||
_isStatic = (attributes & MMethodAttributes::Static) == MMethodAttributes::Static;
|
||||
|
||||
#if COMPILE_WITH_PROFILER
|
||||
const StringAnsi& className = parentClass->GetFullName();
|
||||
ProfilerName.Resize(className.Length() + 2 + _name.Length());
|
||||
Platform::MemoryCopy(ProfilerName.Get(), className.Get(), className.Length());
|
||||
ProfilerName.Get()[className.Length()] = ':';
|
||||
ProfilerName.Get()[className.Length() + 1] = ':';
|
||||
Platform::MemoryCopy(ProfilerName.Get() + className.Length() + 2, _name.Get(), _name.Length());
|
||||
ProfilerData.name = ProfilerName.Get();
|
||||
// Setup Tracy profiler entry (use assembly memory)
|
||||
const StringAnsiView className = parentClass->GetFullName();
|
||||
char* profilerName = (char*)parentClass->GetAssembly()->Memory.Allocate(className.Length() + _name.Length() + 3);
|
||||
Platform::MemoryCopy(profilerName, className.Get(), className.Length());
|
||||
profilerName[className.Length()] = ':';
|
||||
profilerName[className.Length() + 1] = ':';
|
||||
Platform::MemoryCopy(profilerName + className.Length() + 2, _name.Get(), _name.Length());
|
||||
profilerName[className.Length() + 2 + _name.Length()] = 0;
|
||||
ProfilerData.name = profilerName;
|
||||
ProfilerData.function = _name.Get();
|
||||
ProfilerData.file = nullptr;
|
||||
ProfilerData.line = 0;
|
||||
@@ -1573,20 +1569,30 @@ const Array<MObject*>& MMethod::GetAttributes() const
|
||||
return _attributes;
|
||||
}
|
||||
|
||||
FORCE_INLINE StringAnsiView GetPropertyMethodName(MProperty* property, StringAnsiView prefix)
|
||||
{
|
||||
StringAnsiView name = property->GetName();
|
||||
char* mem = (char*)property->GetParentClass()->GetAssembly()->Memory.Allocate(name.Length() + prefix.Length() + 1);
|
||||
Platform::MemoryCopy(mem, prefix.Get(), prefix.Length());
|
||||
Platform::MemoryCopy(mem + prefix.Length(), name.Get(), name.Length());
|
||||
mem[name.Length() + prefix.Length()] = 0;
|
||||
return StringAnsiView(mem, name.Length() + prefix.Length() + 1);
|
||||
}
|
||||
|
||||
MProperty::MProperty(MClass* parentClass, const char* name, void* handle, void* getterHandle, void* setterHandle, MMethodAttributes getterAttributes, MMethodAttributes setterAttributes)
|
||||
: _parentClass(parentClass)
|
||||
, _name(name)
|
||||
, _name(parentClass->GetAssembly()->AllocString(name))
|
||||
, _handle(handle)
|
||||
, _hasCachedAttributes(false)
|
||||
{
|
||||
_hasGetMethod = getterHandle != nullptr;
|
||||
if (_hasGetMethod)
|
||||
_getMethod = New<MMethod>(parentClass, StringAnsi("get_" + _name), getterHandle, 0, getterAttributes);
|
||||
_getMethod = parentClass->GetAssembly()->Memory.New<MMethod>(parentClass, GetPropertyMethodName(this, StringAnsiView("get_", 4)), getterHandle, 0, getterAttributes);
|
||||
else
|
||||
_getMethod = nullptr;
|
||||
_hasSetMethod = setterHandle != nullptr;
|
||||
if (_hasSetMethod)
|
||||
_setMethod = New<MMethod>(parentClass, StringAnsi("set_" + _name), setterHandle, 1, setterAttributes);
|
||||
_setMethod = parentClass->GetAssembly()->Memory.New<MMethod>(parentClass, GetPropertyMethodName(this, StringAnsiView("set_", 4)), setterHandle, 1, setterAttributes);
|
||||
else
|
||||
_setMethod = nullptr;
|
||||
}
|
||||
@@ -1594,9 +1600,9 @@ MProperty::MProperty(MClass* parentClass, const char* name, void* handle, void*
|
||||
MProperty::~MProperty()
|
||||
{
|
||||
if (_getMethod)
|
||||
Delete(_getMethod);
|
||||
Memory::DestructItem(_getMethod);
|
||||
if (_setMethod)
|
||||
Delete(_setMethod);
|
||||
Memory::DestructItem(_setMethod);
|
||||
}
|
||||
|
||||
MMethod* MProperty::GetGetMethod() const
|
||||
@@ -1683,7 +1689,7 @@ MClass* GetOrCreateClass(MType* typeHandle)
|
||||
static void* GetManagedClassFromTypePtr = GetStaticMethodPointer(TEXT("GetManagedClassFromType"));
|
||||
CallStaticMethod<void, void*, void*>(GetManagedClassFromTypePtr, typeHandle, &classInfo, &assemblyHandle);
|
||||
MAssembly* assembly = GetAssembly(assemblyHandle);
|
||||
klass = New<MClass>(assembly, classInfo.typeHandle, classInfo.name, classInfo.fullname, classInfo.namespace_, classInfo.typeAttributes);
|
||||
klass = assembly->Memory.New<MClass>(assembly, classInfo.typeHandle, classInfo.name, classInfo.fullname, classInfo.namespace_, classInfo.typeAttributes);
|
||||
if (assembly != nullptr)
|
||||
{
|
||||
auto& classes = const_cast<MAssembly::ClassesDictionary&>(assembly->GetClasses());
|
||||
@@ -1889,7 +1895,7 @@ void ShutdownHostfxr()
|
||||
{
|
||||
}
|
||||
|
||||
void* GetStaticMethodPointer(const String& methodName)
|
||||
void* GetStaticMethodPointer(StringView methodName)
|
||||
{
|
||||
void* fun;
|
||||
if (CachedFunctions.TryGet(methodName, fun))
|
||||
|
||||
Reference in New Issue
Block a user