[add] first

This commit is contained in:
2023-10-08 10:24:48 +08:00
commit b1ae0510a9
1048 changed files with 3254361 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
#pragma once
#include "GarbageCollector.h"
namespace il2cpp
{
namespace gc
{
template<typename T>
class Allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
typedef Allocator<T> allocator_type;
Allocator() {}
Allocator(const Allocator&) {}
pointer allocate(size_type n, const void * = 0)
{
T* t = (T*)GarbageCollector::AllocateFixed(n * sizeof(T), 0);
return t;
}
void deallocate(void* p, size_type)
{
if (p)
{
GarbageCollector::FreeFixed(p);
}
}
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
Allocator<T>& operator=(const Allocator&) { return *this; }
void construct(pointer p, const T& val) { new((T*)p) T(val); }
void destroy(pointer p) { p->~T(); }
size_type max_size() const { return size_t(-1); }
template<class U>
struct rebind { typedef Allocator<U> other; };
template<class U>
Allocator(const Allocator<U>&) {}
template<class U>
Allocator& operator=(const Allocator<U>&) { return *this; }
};
}
}

View File

@@ -0,0 +1,127 @@
#pragma once
#include "utils/Il2CppHashMap.h"
#include "utils/NonCopyable.h"
#include "GarbageCollector.h"
#include "os/FastReaderReaderWriterLock.h"
namespace il2cpp
{
namespace gc
{
template<class Key, class T,
class HashFcn,
class EqualKey = std::equal_to<Key> >
class AppendOnlyGCHashMap : public il2cpp::utils::NonCopyable
{
typedef Il2CppHashMap<Key, size_t, HashFcn, EqualKey> hash_map_type;
typedef typename Il2CppHashMap<Key, size_t, HashFcn, EqualKey>::const_iterator ConstIterator;
public:
typedef typename hash_map_type::key_type key_type;
typedef T data_type;
typedef typename hash_map_type::size_type size_type;
typedef typename hash_map_type::hasher hasher;
typedef typename hash_map_type::key_equal key_equal;
AppendOnlyGCHashMap() :
m_Data(NULL),
m_Size(0)
{
}
~AppendOnlyGCHashMap()
{
if (m_Data)
il2cpp::gc::GarbageCollector::FreeFixed(m_Data);
}
bool Contains(const Key& k)
{
os::FastReaderReaderWriterAutoSharedLock readLock(&lock);
return m_Map.find(k) != m_Map.end();
}
// Returns the existing value if the it was already added or inserts and returns value
T GetOrAdd(const Key& k, T value)
{
os::FastReaderReaderWriterAutoExclusiveLock writeLock(&lock);
ConstIterator iter = m_Map.find(k);
if (iter != m_Map.end())
{
size_t index = iter->second;
IL2CPP_ASSERT(index <= m_Map.size());
return m_Data[index];
}
if (m_Size == 0)
{
m_Size = 8;
m_Data = (T*)il2cpp::gc::GarbageCollector::AllocateFixed(m_Size * sizeof(T), NULL);
IL2CPP_ASSERT(m_Data);
}
else if (m_Map.size() == m_Size)
{
size_t newSize = 2 * m_Size;
T* newData = (T*)il2cpp::gc::GarbageCollector::AllocateFixed(newSize * sizeof(T), NULL);
MemCpyData memCpyData = { newData, m_Data, m_Size * sizeof(T) };
// perform memcpy with GC lock held so GC doesn't see torn pointer values.I think this is less of an issue with Boehm than other GCs, but being safe.
il2cpp::gc::GarbageCollector::CallWithAllocLockHeld(&CopyValues, &memCpyData);
il2cpp::gc::GarbageCollector::FreeFixed(m_Data);
GarbageCollector::SetWriteBarrier((void**)newData, m_Size * sizeof(T));
m_Size = newSize;
m_Data = newData;
IL2CPP_ASSERT(m_Data);
}
size_t index = m_Map.size();
m_Map.insert(std::make_pair(k, index));
m_Data[index] = value;
GarbageCollector::SetWriteBarrier((void**)(m_Data + index));
IL2CPP_ASSERT(m_Map.size() <= m_Size);
return value;
}
bool TryGetValue(const Key& k, T* value)
{
os::FastReaderReaderWriterAutoSharedLock readLock(&lock);
ConstIterator iter = m_Map.find(k);
if (iter == m_Map.end())
return false;
size_t index = iter->second;
IL2CPP_ASSERT(index <= m_Map.size());
*value = m_Data[index];
return true;
}
private:
struct MemCpyData
{
void* dst;
const void* src;
size_t size;
};
static void* CopyValues(void* arg)
{
MemCpyData* thisPtr = (MemCpyData*)arg;
memcpy(thisPtr->dst, thisPtr->src, thisPtr->size);
return NULL;
}
Il2CppHashMap<Key, size_t, HashFcn, EqualKey> m_Map;
T* m_Data;
size_t m_Size;
os::FastReaderReaderWriterLock lock;
};
}
}

View File

@@ -0,0 +1,38 @@
#pragma once
#include "utils/Expected.h"
#include "utils/Il2CppError.h"
#include <stdint.h>
struct Il2CppObject;
namespace il2cpp
{
namespace gc
{
enum GCHandleType
{
HANDLE_WEAK,
HANDLE_WEAK_TRACK,
HANDLE_NORMAL,
HANDLE_PINNED
};
class LIBIL2CPP_CODEGEN_API GCHandle
{
public:
// external
static uint32_t New(Il2CppObject *obj, bool pinned);
static utils::Expected<uint32_t> NewWeakref(Il2CppObject *obj, bool track_resurrection);
static Il2CppObject* GetTarget(uint32_t gchandle);
static GCHandleType GetHandleType(uint32_t gcHandle);
static void Free(uint32_t gchandle);
public:
//internal
static utils::Expected<uint32_t> GetTargetHandle(Il2CppObject * obj, int32_t handle, int32_t type);
typedef void(*WalkGCHandleTargetsCallback)(Il2CppObject* obj, void* context);
static void WalkStrongGCHandleTargets(WalkGCHandleTargetsCallback callback, void* context);
};
} /* gc */
} /* il2cpp */

View File

@@ -0,0 +1,114 @@
#pragma once
struct Il2CppGuid;
struct Il2CppIUnknown;
struct Il2CppObject;
struct Il2CppThread;
namespace il2cpp
{
namespace gc
{
class LIBIL2CPP_CODEGEN_API GarbageCollector
{
public:
static void Collect(int maxGeneration);
static int32_t CollectALittle();
static int32_t GetCollectionCount(int32_t generation);
static int64_t GetUsedHeapSize();
#if IL2CPP_ENABLE_WRITE_BARRIERS
static void SetWriteBarrier(void **ptr);
static void SetWriteBarrier(void **ptr, size_t numBytes);
#else
static inline void SetWriteBarrier(void **ptr) {}
static inline void SetWriteBarrier(void **ptr, size_t numBytes) {}
#endif
public:
// internal
typedef void (*FinalizerCallback)(void* object, void* client_data);
// functions implemented in a GC agnostic manner
static void UninitializeGC();
static void AddMemoryPressure(int64_t value);
static int32_t GetMaxGeneration();
static int32_t GetGeneration(void* addr);
#if !RUNTIME_TINY
static void InitializeFinalizer();
static bool IsFinalizerThread(Il2CppThread* thread);
static void UninitializeFinalizers();
static void NotifyFinalizers();
static void RunFinalizer(void *obj, void *data);
static void RegisterFinalizerForNewObject(Il2CppObject* obj);
static void RegisterFinalizer(Il2CppObject* obj);
static void SuppressFinalizer(Il2CppObject* obj);
static void WaitForPendingFinalizers();
static Il2CppIUnknown* GetOrCreateCCW(Il2CppObject* obj, const Il2CppGuid& iid);
#endif
// functions implemented in a GC specific manner
static void Initialize();
// Deprecated. Remove when Unity has switched to mono_unity_gc_set_mode
static void Enable();
// Deprecated. Remove when Unity has switched to mono_unity_gc_set_mode
static void Disable();
// Deprecated. Remove when Unity has switched to mono_unity_gc_set_mode
static bool IsDisabled();
static void SetMode(Il2CppGCMode mode);
static bool IsIncremental();
static void StartIncrementalCollection();
static int64_t GetMaxTimeSliceNs();
static void SetMaxTimeSliceNs(int64_t maxTimeSlice);
static FinalizerCallback RegisterFinalizerWithCallback(Il2CppObject* obj, FinalizerCallback callback);
static int64_t GetAllocatedHeapSize();
static void* MakeDescriptorForObject(size_t *bitmap, int numbits);
static void* MakeDescriptorForString();
static void* MakeDescriptorForArray();
#if RUNTIME_TINY
static void* Allocate(size_t size);
static void* AllocateObject(size_t size, void* type);
#endif
static void* AllocateFixed(size_t size, void *descr);
static void FreeFixed(void* addr);
static bool RegisterThread(void *baseptr);
static bool UnregisterThread();
#if !RUNTIME_TINY
static bool HasPendingFinalizers();
static int32_t InvokeFinalizers();
#endif
static void AddWeakLink(void **link_addr, Il2CppObject *obj, bool track);
static void RemoveWeakLink(void **link_addr);
static Il2CppObject *GetWeakLink(void **link_addr);
/* Used by liveness code */
static void StopWorld();
static void StartWorld();
typedef void (*HeapSectionCallback) (void* user_data, void* start, void* end);
static void ForEachHeapSection(void* user_data, HeapSectionCallback callback);
static size_t GetSectionCount();
typedef void* (*GCCallWithAllocLockCallback)(void* user_data);
static void* CallWithAllocLockHeld(GCCallWithAllocLockCallback callback, void* user_data);
static void RegisterRoot(char *start, size_t size);
static void UnregisterRoot(char* start);
static void SetSkipThread(bool skip);
static bool EphemeronArrayAdd(Il2CppObject* obj);
};
} /* namespace vm */
} /* namespace il2cpp */

View File

@@ -0,0 +1,43 @@
#pragma once
#include <type_traits>
struct Il2CppObject;
namespace il2cpp
{
namespace gc
{
class WriteBarrier
{
public:
static void GenericStore(void** ptr, void* value);
template<typename TPtr, typename TValue>
static void GenericStore(TPtr** ptr, TValue* value)
{
static_assert((std::is_assignable<TPtr*&, TValue*>::value), "Pointers types are not assignment compatible");
GenericStore((void**)ptr, (void*)value);
}
template<typename TPtr>
static void GenericStoreNull(TPtr** ptr)
{
*ptr = NULL;
}
};
} /* gc */
} /* il2cpp */
#define IL2CPP_OBJECT_SETREF(obj, fieldname, value) do {\
il2cpp::gc::WriteBarrier::GenericStore(&(obj)->fieldname, (value));\
} while (0)
/* This should be used if 's' can reside on the heap */
#define IL2CPP_STRUCT_SETREF(s, fieldname, value) do {\
il2cpp::gc::WriteBarrier::GenericStore(&(s)->fieldname, (value));\
} while (0)
#define IL2CPP_OBJECT_SETREF_NULL(obj, fieldname) do {\
il2cpp::gc::WriteBarrier::GenericStoreNull(&(obj)->fieldname);\
} while (0)

View File

@@ -0,0 +1,22 @@
#pragma once
#if IL2CPP_ENABLE_WRITE_BARRIER_VALIDATION
namespace il2cpp
{
namespace gc
{
class WriteBarrierValidation
{
public:
typedef void(*ExternalAllocationTrackerFunction)(void*, size_t, int);
static void SetExternalAllocationTracker(ExternalAllocationTrackerFunction func);
typedef void(*ExternalWriteBarrierTrackerFunction)(void**);
static void SetExternalWriteBarrierTracker(ExternalWriteBarrierTrackerFunction func);
static void Setup();
static void Run();
};
} /* gc */
} /* il2cpp */
#endif

View File

@@ -0,0 +1,28 @@
#pragma once
#include "il2cpp-config.h"
#if IL2CPP_GC_BOEHM
/* here is the defines we build Boehm with */
#define IGNORE_DYNAMIC_LOADING 1
#define GC_DONT_REGISTER_MAIN_STATIC_DATA 1
#if IL2CPP_HAS_GC_DESCRIPTORS
#define GC_GCJ_SUPPORT 1
#endif
#if IL2CPP_SUPPORT_THREADS
#define GC_THREADS 1
#endif
#include "gc.h"
#include "gc_typed.h"
#include "gc_mark.h"
#include "gc_gcj.h"
#include "gc_vector.h"
#define GC_NO_DESCRIPTOR ((void*)(0 | GC_DS_LENGTH))
#else
#define GC_NO_DESCRIPTOR ((void*)0)
#endif