diff --git a/IL2C.Runtime/src/Private/arduino_all.h b/IL2C.Runtime/src/Private/arduino_all.h index 7ac14ce9..71d6d569 100644 --- a/IL2C.Runtime/src/Private/arduino_all.h +++ b/IL2C.Runtime/src/Private/arduino_all.h @@ -53,6 +53,7 @@ extern void il2c_free(void* p); #define il2c_iand(pDest, newValue) __sync_fetch_and_and((interlock_t*)(pDest), (interlock_t)(newValue)) #define il2c_ior(pDest, newValue) __sync_fetch_and_or((interlock_t*)(pDest), (interlock_t)(newValue)) +#define il2c_ixor(pDest, newValue) __sync_fetch_and_xor((interlock_t*)(pDest), (interlock_t)(newValue)) #define il2c_iinc(pDest) __sync_add_and_fetch((interlock_t*)(pDest), 1) #define il2c_idec(pDest) __sync_sub_and_fetch((interlock_t*)(pDest), 1) #define il2c_ixchg(pDest, newValue) __sync_lock_test_and_set((interlock_t*)(pDest), (interlock_t)(newValue)) diff --git a/IL2C.Runtime/src/Private/gcc_linux.h b/IL2C.Runtime/src/Private/gcc_linux.h index 0bd40117..42ff0583 100644 --- a/IL2C.Runtime/src/Private/gcc_linux.h +++ b/IL2C.Runtime/src/Private/gcc_linux.h @@ -71,6 +71,7 @@ extern void il2c_free(void* p); #define il2c_iand(pDest, newValue) __sync_fetch_and_and((interlock_t*)(pDest), (interlock_t)(newValue)) #define il2c_ior(pDest, newValue) __sync_fetch_and_or((interlock_t*)(pDest), (interlock_t)(newValue)) +#define il2c_ixor(pDest, newValue) __sync_fetch_and_xor((interlock_t*)(pDest), (interlock_t)(newValue)) #define il2c_iinc(pDest) __sync_add_and_fetch((interlock_t*)(pDest), 1) #define il2c_idec(pDest) __sync_sub_and_fetch((interlock_t*)(pDest), 1) #define il2c_ixchg(pDest, newValue) __sync_lock_test_and_set((interlock_t*)(pDest), (interlock_t)(newValue)) diff --git a/IL2C.Runtime/src/Private/gcc_win32.h b/IL2C.Runtime/src/Private/gcc_win32.h index 63b72aa4..0b52d7bd 100644 --- a/IL2C.Runtime/src/Private/gcc_win32.h +++ b/IL2C.Runtime/src/Private/gcc_win32.h @@ -59,6 +59,7 @@ extern wchar_t* il2c_u64tow(uint64_t value, wchar_t* buffer, int radix); #define il2c_iand(pDest, newValue) __sync_fetch_and_and((interlock_t*)(pDest), (interlock_t)(newValue)) #define il2c_ior(pDest, newValue) __sync_fetch_and_or((interlock_t*)(pDest), (interlock_t)(newValue)) +#define il2c_ixor(pDest, newValue) __sync_fetch_and_xor((interlock_t*)(pDest), (interlock_t)(newValue)) #define il2c_iinc(pDest) __sync_add_and_fetch((interlock_t*)(pDest), 1) #define il2c_idec(pDest) __sync_sub_and_fetch((interlock_t*)(pDest), 1) #define il2c_ixchg(pDest, newValue) __sync_lock_test_and_set((interlock_t*)(pDest), (interlock_t)(newValue)) diff --git a/IL2C.Runtime/src/Private/msvc_uefi.h b/IL2C.Runtime/src/Private/msvc_uefi.h index bd93ae30..b982ce94 100644 --- a/IL2C.Runtime/src/Private/msvc_uefi.h +++ b/IL2C.Runtime/src/Private/msvc_uefi.h @@ -47,6 +47,7 @@ extern void il2c_free(void* p); #define il2c_iand(pDest, newValue) _InterlockedAnd((interlock_t*)(pDest), (interlock_t)(newValue)) #define il2c_ior(pDest, newValue) _InterlockedOr((interlock_t*)(pDest), (interlock_t)(newValue)) +#define il2c_ixor(pDest, newValue) _InterlockedXor((interlock_t*)(pDest), (interlock_t)(newValue)) #define il2c_iinc(pDest) _InterlockedIncrement((interlock_t*)(pDest)) #define il2c_idec(pDest) _InterlockedDecrement((interlock_t*)(pDest)) #define il2c_ixchg(pDest, newValue) _InterlockedExchange((interlock_t*)(pDest), (interlock_t)(newValue)) diff --git a/IL2C.Runtime/src/Private/msvc_wdm.h b/IL2C.Runtime/src/Private/msvc_wdm.h index ab81b086..4d819d27 100644 --- a/IL2C.Runtime/src/Private/msvc_wdm.h +++ b/IL2C.Runtime/src/Private/msvc_wdm.h @@ -47,6 +47,7 @@ extern "C" { #define il2c_iand(pDest, newValue) _InterlockedAnd((interlock_t*)(pDest), (interlock_t)(newValue)) #define il2c_ior(pDest, newValue) _InterlockedOr((interlock_t*)(pDest), (interlock_t)(newValue)) +#define il2c_ixor(pDest, newValue) _InterlockedXor((interlock_t*)(pDest), (interlock_t)(newValue)) #define il2c_iinc(pDest) _InterlockedIncrement((interlock_t*)(pDest)) #define il2c_idec(pDest) _InterlockedDecrement((interlock_t*)(pDest)) #define il2c_ixchg(pDest, newValue) _InterlockedExchange((interlock_t*)(pDest), (interlock_t)(newValue)) diff --git a/IL2C.Runtime/src/Private/msvc_win32.h b/IL2C.Runtime/src/Private/msvc_win32.h index e0fee030..70c0eb2f 100644 --- a/IL2C.Runtime/src/Private/msvc_win32.h +++ b/IL2C.Runtime/src/Private/msvc_win32.h @@ -64,6 +64,7 @@ extern wchar_t* il2c_u64tow(uint64_t value, wchar_t* buffer, int radix); #define il2c_iand(pDest, newValue) _InterlockedAnd((interlock_t*)(pDest), (interlock_t)(newValue)) #define il2c_ior(pDest, newValue) _InterlockedOr((interlock_t*)(pDest), (interlock_t)(newValue)) +#define il2c_ixor(pDest, newValue) _InterlockedXor((interlock_t*)(pDest), (interlock_t)(newValue)) #define il2c_iinc(pDest) _InterlockedIncrement((interlock_t*)(pDest)) #define il2c_idec(pDest) _InterlockedDecrement((interlock_t*)(pDest)) #define il2c_ixchg(pDest, newValue) _InterlockedExchange((interlock_t*)(pDest), (interlock_t)(newValue)) diff --git a/IL2C.Runtime/src/il2c.c b/IL2C.Runtime/src/il2c.c index 3a3b7c82..a73bb890 100644 --- a/IL2C.Runtime/src/il2c.c +++ b/IL2C.Runtime/src/il2c.c @@ -44,6 +44,7 @@ static IL2C_STATIC_FIELDS* g_pBeginStaticFields__ = NULL; static IL2C_MONITOR_LOCK_BLOCK_INFORMATION* g_MonitorLockBlockInformations[7] = { NULL }; +static interlock_t g_CollectionMarkIndex__ = 0; // IL2C_CHARACTERISTIC_MARK_INDEX; static interlock_t g_ExecutingCollection__ = 0; // The initializer count produces when works the type initializer. @@ -106,9 +107,10 @@ void* il2c_get_uninitialized_object_internal__( // Guarantee cleared body memset(pReference, 0, bodySize); - pHeader->pNext = NULL; pHeader->type = type; - pHeader->characteristic = 0; + + // HACK: Current GC mark status is same as g_CollectionMarkIndex__, it means "Marked." + pHeader->characteristic = g_CollectionMarkIndex__; // Safe link both headers. while (1) @@ -679,12 +681,12 @@ static void il2c_release_all_monitor_lock_for_final_shutdown__(void) ///////////////////////////////////////////////////////////// // Internal GC mark handlers -// Has to ignore if objref is const. +// Has to ignore if objref is const. (NOT const and NOT marked) // HACK: It's shame the icmpxchg may cause system fault if header is placed at read-only memory (CONST). // (at x86/x64 cause, another platform may cause) #define TRY_GET_HEADER(pHeader, pAdjustedReference) \ IL2C_REF_HEADER* pHeader = il2c_get_header__(pAdjustedReference); \ - if (il2c_unlikely__((pHeader->characteristic & (IL2C_CHARACTERISTIC_CONST | IL2C_CHARACTERISTIC_LIVE)) == 0)) + if (il2c_unlikely__(((pHeader->characteristic & (IL2C_CHARACTERISTIC_CONST | IL2C_CHARACTERISTIC_MARK_INDEX)) ^ IL2C_CHARACTERISTIC_MARK_INDEX) == g_CollectionMarkIndex__)) static void il2c_mark_handler_recursive__(void* pTarget, IL2C_RUNTIME_TYPE type, const uint8_t offset); @@ -698,14 +700,14 @@ static void il2c_mark_handler_for_objref__(System_Object* pAdjustedReference) il2c_assert(pHeader->type != NULL); // Marking with atomicity. - interlock_t characteristic = il2c_ior(&pHeader->characteristic, IL2C_CHARACTERISTIC_LIVE); - if (il2c_likely__((characteristic & IL2C_CHARACTERISTIC_LIVE) == IL2C_CHARACTERISTIC_LIVE)) + const interlock_t lastCharacteristic = il2c_ixor(&pHeader->characteristic, IL2C_CHARACTERISTIC_MARK_INDEX); + if (il2c_likely__((lastCharacteristic & IL2C_CHARACTERISTIC_MARK_INDEX) == g_CollectionMarkIndex__)) { il2c_runtime_debug_log_format( - L"il2c_mark_handler_for_objref__ [1]: pAdjustedReference=0x{0:p}, type={1:s}, characteristic=0x{2:x}", + L"il2c_mark_handler_for_objref__ [1]: pAdjustedReference=0x{0:p}, type={1:s}, lastCharacteristic=0x{2:x}", pAdjustedReference, pHeader->type->pTypeName, - characteristic); + lastCharacteristic); // Already marked/fixed/constant return; } @@ -842,21 +844,6 @@ static void il2c_mark_handler_recursive__(void* pTarget, IL2C_RUNTIME_TYPE type, ///////////////////////////////////////////////////////////// // GC processes -static void il2c_step1_clear_gcmark__(void) -{ - // It has to invoke from inside for GC process. - il2c_assert(g_ExecutingCollection__ >= 1); - - // Clear header marks. - IL2C_REF_HEADER* pCurrentHeader = g_pBeginHeader__; - while (il2c_likely__(pCurrentHeader != NULL)) - { - // Drop live marking. - il2c_iand(&pCurrentHeader->characteristic, ~IL2C_CHARACTERISTIC_LIVE); - pCurrentHeader = pCurrentHeader->pNext; - } -} - static void il2c_step2_mark_gcmark__(IL2C_GC_TRACKING_INFORMATION* pBeginFrame) { // It has to invoke from inside for GC process. @@ -981,7 +968,7 @@ static void il2c_step3_sweep_garbage__(void) while (il2c_likely__(pCurrentHeader != NULL)) { IL2C_REF_HEADER* pNext = pCurrentHeader->pNext; - if (il2c_unlikely__((pCurrentHeader->characteristic & IL2C_CHARACTERISTIC_LIVE) == 0)) + if (il2c_unlikely__((pCurrentHeader->characteristic & IL2C_CHARACTERISTIC_MARK_INDEX) != g_CollectionMarkIndex__)) { // Very important unlink step: because cause misread on purpose this__ instance is living. *ppUnlinkTarget = pNext; @@ -1091,8 +1078,11 @@ void il2c_collect__(void) ////////////////////////////////////////////////// // GC Step 1: - il2c_step1_clear_gcmark__(); - il2c_check_heap(); + // Note: Traditional mark-sweep GC's first step is clearing markings. + // The IL2C GC skips this step and mark/clear flag indicates with inverse arithmetic + // between g_CollectionMarkIndex__ and characteristic's MARK_INDEX. + // The instances characteristic MARK_INDEX will indicate last stats, so makes NOT MARKED if inversed this flag. + il2c_ixor(&g_CollectionMarkIndex__, IL2C_CHARACTERISTIC_MARK_INDEX); ////////////////////////////////////// // GC Step 2: @@ -1157,8 +1147,11 @@ static void il2c_collect_for_final_shutdown__(void) ////////////////////////////////////////////////// // GC Step 1: - il2c_step1_clear_gcmark__(); - il2c_check_heap(); + // Note: Traditional mark-sweep GC's first step is clearing markings. + // The IL2C GC skips this step and mark/clear flag indicates with inverse arithmetic + // between g_CollectionMarkIndex__ and characteristic's MARK_INDEX. + // The instances characteristic MARK_INDEX will indicate last stats, so makes NOT MARKED if inversed this flag. + il2c_ixor(&g_CollectionMarkIndex__, IL2C_CHARACTERISTIC_MARK_INDEX); ////////////////////////////////////// // GC Step 2: diff --git a/IL2C.Runtime/src/il2c_private.h b/IL2C.Runtime/src/il2c_private.h index 138e04b8..d4b09257 100644 --- a/IL2C.Runtime/src/il2c_private.h +++ b/IL2C.Runtime/src/il2c_private.h @@ -107,7 +107,7 @@ struct IL2C_RUNTIME_TYPE_DECL // IL2C_REF_HEADER_DECL.characteristic #define IL2C_CHARACTERISTIC_ACQUIRED_MONITOR_LOCK ((interlock_t)0x10000000UL) #define IL2C_CHARACTERISTIC_SUPPRESS_FINALIZE ((interlock_t)0x20000000UL) -#define IL2C_CHARACTERISTIC_LIVE ((interlock_t)0x40000000UL) +#define IL2C_CHARACTERISTIC_MARK_INDEX ((interlock_t)0x40000000UL) // Mark index is only 0 or 1. #define IL2C_CHARACTERISTIC_CONST ((interlock_t)0x80000000UL) #define il2c_get_header__(pReference) \