diff --git a/src/asmjit/core/constpool.cpp b/src/asmjit/core/constpool.cpp index 2c5a513..0d1cdb8 100644 --- a/src/asmjit/core/constpool.cpp +++ b/src/asmjit/core/constpool.cpp @@ -235,7 +235,7 @@ void ConstPool::fill(void* dst) const noexcept { // ============================================================================ #if defined(ASMJIT_TEST) -UNIT(asmjit_core_const_pool) { +UNIT(const_pool) { Zone zone(32384 - Zone::kBlockOverhead); ConstPool pool(&zone); diff --git a/src/asmjit/core/jitallocator.cpp b/src/asmjit/core/jitallocator.cpp index 76166d2..d8139d1 100644 --- a/src/asmjit/core/jitallocator.cpp +++ b/src/asmjit/core/jitallocator.cpp @@ -1022,7 +1022,7 @@ static void JitAllocatorTest_usage(JitAllocator& allocator) noexcept { INFO(" Overhead (HeapMem): %9llu [Bytes] (%.1f%%)", (unsigned long long)(stats.overheadSize()), stats.overheadSizeAsPercent()); } -UNIT(asmjit_jit_allocator) { +UNIT(jit_allocator) { size_t kCount = BrokenAPI::hasArg("--quick") ? 1000 : 100000; struct TestParams { diff --git a/src/asmjit/core/operand.cpp b/src/asmjit/core/operand.cpp index 6156d6f..82040c0 100644 --- a/src/asmjit/core/operand.cpp +++ b/src/asmjit/core/operand.cpp @@ -15,7 +15,7 @@ ASMJIT_BEGIN_NAMESPACE // ============================================================================ #if defined(ASMJIT_TEST) -UNIT(asmjit_core_operand) { +UNIT(operand) { INFO("Checking operand sizes"); EXPECT(sizeof(Operand) == 16); EXPECT(sizeof(BaseReg) == 16); diff --git a/src/asmjit/core/string.cpp b/src/asmjit/core/string.cpp index b1952f4..da2fa05 100644 --- a/src/asmjit/core/string.cpp +++ b/src/asmjit/core/string.cpp @@ -461,7 +461,7 @@ bool String::eq(const char* other, size_t size) const noexcept { // ============================================================================ #if defined(ASMJIT_TEST) -UNIT(asmjit_core_string) { +UNIT(core_string) { String s; EXPECT(s.isLarge() == false); diff --git a/src/asmjit/core/support.cpp b/src/asmjit/core/support.cpp index 0a83f12..77d11f9 100644 --- a/src/asmjit/core/support.cpp +++ b/src/asmjit/core/support.cpp @@ -470,7 +470,7 @@ static void testSorting() noexcept { } } -UNIT(asmjit_support) { +UNIT(support) { testAlignment(); testBitUtils(); testIntUtils(); diff --git a/src/asmjit/core/zonehash.cpp b/src/asmjit/core/zonehash.cpp index abed5c1..54fb328 100644 --- a/src/asmjit/core/zonehash.cpp +++ b/src/asmjit/core/zonehash.cpp @@ -16,27 +16,165 @@ ASMJIT_BEGIN_NAMESPACE // [asmjit::ZoneHashBase - Helpers] // ============================================================================ -static uint32_t ZoneHash_getClosestPrime(uint32_t x) noexcept { - static const uint32_t primeTable[] = { - 23, 53, 193, 389, 769, 1543, 3079, 6151, 12289, 24593 - }; +#define ASMJIT_POPULATE_PRIMES(ENTRY) \ + ENTRY(2 , 0x80000000, 32), /* [N * 0x80000000 >> 32] (rcp=2147483648) */ \ + ENTRY(11 , 0xBA2E8BA3, 35), /* [N * 0xBA2E8BA3 >> 35] (rcp=3123612579) */ \ + ENTRY(29 , 0x8D3DCB09, 36), /* [N * 0x8D3DCB09 >> 36] (rcp=2369637129) */ \ + ENTRY(41 , 0xC7CE0C7D, 37), /* [N * 0xC7CE0C7D >> 37] (rcp=3352169597) */ \ + ENTRY(59 , 0x8AD8F2FC, 37), /* [N * 0x8AD8F2FC >> 37] (rcp=2329473788) */ \ + ENTRY(83 , 0xC565C87C, 38), /* [N * 0xC565C87C >> 38] (rcp=3311782012) */ \ + ENTRY(131 , 0xFA232CF3, 39), /* [N * 0xFA232CF3 >> 39] (rcp=4196609267) */ \ + ENTRY(191 , 0xAB8F69E3, 39), /* [N * 0xAB8F69E3 >> 39] (rcp=2878302691) */ \ + ENTRY(269 , 0xF3A0D52D, 40), /* [N * 0xF3A0D52D >> 40] (rcp=4087403821) */ \ + ENTRY(383 , 0xAB1CBDD4, 40), /* [N * 0xAB1CBDD4 >> 40] (rcp=2870787540) */ \ + ENTRY(541 , 0xF246FACC, 41), /* [N * 0xF246FACC >> 41] (rcp=4064737996) */ \ + ENTRY(757 , 0xAD2589A4, 41), /* [N * 0xAD2589A4 >> 41] (rcp=2904918436) */ \ + ENTRY(1061 , 0xF7129426, 42), /* [N * 0xF7129426 >> 42] (rcp=4145189926) */ \ + ENTRY(1499 , 0xAEE116B7, 42), /* [N * 0xAEE116B7 >> 42] (rcp=2933986999) */ \ + ENTRY(2099 , 0xF9C7A737, 43), /* [N * 0xF9C7A737 >> 43] (rcp=4190611255) */ \ + ENTRY(2939 , 0xB263D25C, 43), /* [N * 0xB263D25C >> 43] (rcp=2992886364) */ \ + ENTRY(4111 , 0xFF10E02E, 44), /* [N * 0xFF10E02E >> 44] (rcp=4279296046) */ \ + ENTRY(5779 , 0xB5722823, 44), /* [N * 0xB5722823 >> 44] (rcp=3044157475) */ \ + ENTRY(8087 , 0x81A97405, 44), /* [N * 0x81A97405 >> 44] (rcp=2175366149) */ \ + ENTRY(11321 , 0xB93E91DB, 45), /* [N * 0xB93E91DB >> 45] (rcp=3107885531) */ \ + ENTRY(15859 , 0x843CC26B, 45), /* [N * 0x843CC26B >> 45] (rcp=2218574443) */ \ + ENTRY(22189 , 0xBD06B9EA, 46), /* [N * 0xBD06B9EA >> 46] (rcp=3171334634) */ \ + ENTRY(31051 , 0x8713F186, 46), /* [N * 0x8713F186 >> 46] (rcp=2266231174) */ \ + ENTRY(43451 , 0xC10F1CB9, 47), /* [N * 0xC10F1CB9 >> 47] (rcp=3238993081) */ \ + ENTRY(60869 , 0x89D06A86, 47), /* [N * 0x89D06A86 >> 47] (rcp=2312137350) */ \ + ENTRY(85159 , 0xC502AF3B, 48), /* [N * 0xC502AF3B >> 48] (rcp=3305287483) */ \ + ENTRY(102107 , 0xA44F65AE, 48), /* [N * 0xA44F65AE >> 48] (rcp=2756666798) */ \ + ENTRY(122449 , 0x89038F77, 48), /* [N * 0x89038F77 >> 48] (rcp=2298711927) */ \ + ENTRY(146819 , 0xE48AF7E9, 49), /* [N * 0xE48AF7E9 >> 49] (rcp=3834312681) */ \ + ENTRY(176041 , 0xBE9B145B, 49), /* [N * 0xBE9B145B >> 49] (rcp=3197834331) */ \ + ENTRY(211073 , 0x9EF882BA, 49), /* [N * 0x9EF882BA >> 49] (rcp=2667086522) */ \ + ENTRY(253081 , 0x849571AB, 49), /* [N * 0x849571AB >> 49] (rcp=2224386475) */ \ + ENTRY(303469 , 0xDD239C97, 50), /* [N * 0xDD239C97 >> 50] (rcp=3710098583) */ \ + ENTRY(363887 , 0xB86C196D, 50), /* [N * 0xB86C196D >> 50] (rcp=3094092141) */ \ + ENTRY(436307 , 0x99CFA4E9, 50), /* [N * 0x99CFA4E9 >> 50] (rcp=2580522217) */ \ + ENTRY(523177 , 0x804595C0, 50), /* [N * 0x804595C0 >> 50] (rcp=2152043968) */ \ + ENTRY(627293 , 0xD5F69FCF, 51), /* [N * 0xD5F69FCF >> 51] (rcp=3589709775) */ \ + ENTRY(752177 , 0xB27063BA, 51), /* [N * 0xB27063BA >> 51] (rcp=2993710010) */ \ + ENTRY(901891 , 0x94D170AC, 51), /* [N * 0x94D170AC >> 51] (rcp=2496753836) */ \ + ENTRY(1081369 , 0xF83C9767, 52), /* [N * 0xF83C9767 >> 52] (rcp=4164720487) */ \ + ENTRY(1296563 , 0xCF09435D, 52), /* [N * 0xCF09435D >> 52] (rcp=3473490781) */ \ + ENTRY(1554583 , 0xACAC7198, 52), /* [N * 0xACAC7198 >> 52] (rcp=2896982424) */ \ + ENTRY(1863971 , 0x90033EE3, 52), /* [N * 0x90033EE3 >> 52] (rcp=2416131811) */ \ + ENTRY(2234923 , 0xF0380EBD, 53), /* [N * 0xF0380EBD >> 53] (rcp=4030205629) */ \ + ENTRY(2679673 , 0xC859731E, 53), /* [N * 0xC859731E >> 53] (rcp=3361305374) */ \ + ENTRY(3212927 , 0xA718DE27, 53), /* [N * 0xA718DE27 >> 53] (rcp=2803424807) */ \ + ENTRY(3852301 , 0x8B5D1B4B, 53), /* [N * 0x8B5D1B4B >> 53] (rcp=2338134859) */ \ + ENTRY(4618921 , 0xE8774804, 54), /* [N * 0xE8774804 >> 54] (rcp=3900131332) */ \ + ENTRY(5076199 , 0xD386574E, 54), /* [N * 0xD386574E >> 54] (rcp=3548796750) */ \ + ENTRY(5578757 , 0xC0783FE1, 54), /* [N * 0xC0783FE1 >> 54] (rcp=3229106145) */ \ + ENTRY(6131057 , 0xAF21B08F, 54), /* [N * 0xAF21B08F >> 54] (rcp=2938220687) */ \ + ENTRY(6738031 , 0x9F5AFD6E, 54), /* [N * 0x9F5AFD6E >> 54] (rcp=2673540462) */ \ + ENTRY(7405163 , 0x90FFC3B9, 54), /* [N * 0x90FFC3B9 >> 54] (rcp=2432680889) */ \ + ENTRY(8138279 , 0x83EFECFC, 54), /* [N * 0x83EFECFC >> 54] (rcp=2213539068) */ \ + ENTRY(8943971 , 0xF01AA2EF, 55), /* [N * 0xF01AA2EF >> 55] (rcp=4028277487) */ \ + ENTRY(9829447 , 0xDA7979B2, 55), /* [N * 0xDA7979B2 >> 55] (rcp=3665394098) */ \ + ENTRY(10802581 , 0xC6CB2771, 55), /* [N * 0xC6CB2771 >> 55] (rcp=3335202673) */ \ + ENTRY(11872037 , 0xB4E2C7DD, 55), /* [N * 0xB4E2C7DD >> 55] (rcp=3034761181) */ \ + ENTRY(13047407 , 0xA4974124, 55), /* [N * 0xA4974124 >> 55] (rcp=2761376036) */ \ + ENTRY(14339107 , 0x95C39CF1, 55), /* [N * 0x95C39CF1 >> 55] (rcp=2512624881) */ \ + ENTRY(15758737 , 0x8845C763, 55), /* [N * 0x8845C763 >> 55] (rcp=2286274403) */ \ + ENTRY(17318867 , 0xF7FE593F, 56), /* [N * 0xF7FE593F >> 56] (rcp=4160641343) */ \ + ENTRY(19033439 , 0xE1A75D93, 56), /* [N * 0xE1A75D93 >> 56] (rcp=3785842067) */ \ + ENTRY(20917763 , 0xCD5389B3, 56), /* [N * 0xCD5389B3 >> 56] (rcp=3444804019) */ \ + ENTRY(22988621 , 0xBAD4841A, 56), /* [N * 0xBAD4841A >> 56] (rcp=3134489626) */ \ + ENTRY(25264543 , 0xA9FFF2FF, 56), /* [N * 0xA9FFF2FF >> 56] (rcp=2852123391) */ \ + ENTRY(27765763 , 0x9AAF8BF3, 56), /* [N * 0x9AAF8BF3 >> 56] (rcp=2595195891) */ \ + ENTRY(30514607 , 0x8CC04E18, 56), /* [N * 0x8CC04E18 >> 56] (rcp=2361413144) */ \ + ENTRY(33535561 , 0x80127068, 56), /* [N * 0x80127068 >> 56] (rcp=2148692072) */ \ + ENTRY(36855587 , 0xE911F0BB, 57), /* [N * 0xE911F0BB >> 57] (rcp=3910267067) */ \ + ENTRY(38661533 , 0xDE2ED7BE, 57), /* [N * 0xDE2ED7BE >> 57] (rcp=3727611838) */ \ + ENTRY(40555961 , 0xD3CDF2FD, 57), /* [N * 0xD3CDF2FD >> 57] (rcp=3553489661) */ \ + ENTRY(42543269 , 0xC9E9196C, 57), /* [N * 0xC9E9196C >> 57] (rcp=3387496812) */ \ + ENTRY(44627909 , 0xC07A9EB6, 57), /* [N * 0xC07A9EB6 >> 57] (rcp=3229261494) */ \ + ENTRY(46814687 , 0xB77CEF65, 57), /* [N * 0xB77CEF65 >> 57] (rcp=3078418277) */ \ + ENTRY(49108607 , 0xAEEAC65C, 57), /* [N * 0xAEEAC65C >> 57] (rcp=2934621788) */ \ + ENTRY(51514987 , 0xA6BF0EF0, 57), /* [N * 0xA6BF0EF0 >> 57] (rcp=2797539056) */ \ + ENTRY(54039263 , 0x9EF510B5, 57), /* [N * 0x9EF510B5 >> 57] (rcp=2666860725) */ \ + ENTRY(56687207 , 0x97883B42, 57), /* [N * 0x97883B42 >> 57] (rcp=2542287682) */ \ + ENTRY(59464897 , 0x907430ED, 57), /* [N * 0x907430ED >> 57] (rcp=2423533805) */ \ + ENTRY(62378699 , 0x89B4CA91, 57), /* [N * 0x89B4CA91 >> 57] (rcp=2310326929) */ \ + ENTRY(65435273 , 0x83461568, 57), /* [N * 0x83461568 >> 57] (rcp=2202408296) */ \ + ENTRY(68641607 , 0xFA489AA8, 58), /* [N * 0xFA489AA8 >> 58] (rcp=4199062184) */ \ + ENTRY(72005051 , 0xEE97B1C5, 58), /* [N * 0xEE97B1C5 >> 58] (rcp=4002918853) */ \ + ENTRY(75533323 , 0xE3729293, 58), /* [N * 0xE3729293 >> 58] (rcp=3815936659) */ \ + ENTRY(79234469 , 0xD8D2BBA3, 58), /* [N * 0xD8D2BBA3 >> 58] (rcp=3637689251) */ \ + ENTRY(83116967 , 0xCEB1F196, 58), /* [N * 0xCEB1F196 >> 58] (rcp=3467768214) */ \ + ENTRY(87189709 , 0xC50A4426, 58), /* [N * 0xC50A4426 >> 58] (rcp=3305784358) */ \ + ENTRY(91462061 , 0xBBD6052B, 58), /* [N * 0xBBD6052B >> 58] (rcp=3151365419) */ \ + ENTRY(95943737 , 0xB30FD999, 58), /* [N * 0xB30FD999 >> 58] (rcp=3004160409) */ \ + ENTRY(100644991 , 0xAAB29CED, 58), /* [N * 0xAAB29CED >> 58] (rcp=2863832301) */ \ + ENTRY(105576619 , 0xA2B96421, 58), /* [N * 0xA2B96421 >> 58] (rcp=2730058785) */ \ + ENTRY(110749901 , 0x9B1F8434, 58), /* [N * 0x9B1F8434 >> 58] (rcp=2602533940) */ \ + ENTRY(116176651 , 0x93E08B4A, 58), /* [N * 0x93E08B4A >> 58] (rcp=2480966474) */ \ + ENTRY(121869317 , 0x8CF837E0, 58), /* [N * 0x8CF837E0 >> 58] (rcp=2365077472) */ \ + ENTRY(127840913 , 0x86627F01, 58), /* [N * 0x86627F01 >> 58] (rcp=2254601985) */ \ + ENTRY(134105159 , 0x801B8178, 58), /* [N * 0x801B8178 >> 58] (rcp=2149286264) */ \ + ENTRY(140676353 , 0xF43F294F, 59), /* [N * 0xF43F294F >> 59] (rcp=4097780047) */ \ + ENTRY(147569509 , 0xE8D67089, 59), /* [N * 0xE8D67089 >> 59] (rcp=3906367625) */ \ + ENTRY(154800449 , 0xDDF6243C, 59), /* [N * 0xDDF6243C >> 59] (rcp=3723895868) */ \ + ENTRY(162385709 , 0xD397E6AE, 59), /* [N * 0xD397E6AE >> 59] (rcp=3549947566) */ \ + ENTRY(170342629 , 0xC9B5A65A, 59), /* [N * 0xC9B5A65A >> 59] (rcp=3384125018) */ \ + ENTRY(178689419 , 0xC0499865, 59), /* [N * 0xC0499865 >> 59] (rcp=3226048613) */ \ + ENTRY(187445201 , 0xB74E35FA, 59), /* [N * 0xB74E35FA >> 59] (rcp=3075356154) */ \ + ENTRY(196630033 , 0xAEBE3AC1, 59), /* [N * 0xAEBE3AC1 >> 59] (rcp=2931702465) */ \ + ENTRY(206264921 , 0xA694A37F, 59), /* [N * 0xA694A37F >> 59] (rcp=2794759039) */ \ + ENTRY(216371963 , 0x9ECCA59F, 59), /* [N * 0x9ECCA59F >> 59] (rcp=2664211871) */ \ + ENTRY(226974197 , 0x9761B6AE, 59), /* [N * 0x9761B6AE >> 59] (rcp=2539763374) */ \ + ENTRY(238095983 , 0x904F79A1, 59), /* [N * 0x904F79A1 >> 59] (rcp=2421127585) */ \ + ENTRY(249762697 , 0x8991CD1F, 59), /* [N * 0x8991CD1F >> 59] (rcp=2308033823) */ \ + ENTRY(262001071 , 0x8324BCA5, 59), /* [N * 0x8324BCA5 >> 59] (rcp=2200222885) */ \ + ENTRY(274839137 , 0xFA090732, 60), /* [N * 0xFA090732 >> 60] (rcp=4194895666) */ \ + ENTRY(288306269 , 0xEE5B16ED, 60), /* [N * 0xEE5B16ED >> 60] (rcp=3998947053) */ \ + ENTRY(302433337 , 0xE338CE49, 60), /* [N * 0xE338CE49 >> 60] (rcp=3812150857) */ \ + ENTRY(317252587 , 0xD89BABC0, 60), /* [N * 0xD89BABC0 >> 60] (rcp=3634080704) */ \ + ENTRY(374358107 , 0xB790EF43, 60), /* [N * 0xB790EF43 >> 60] (rcp=3079728963) */ \ + ENTRY(441742621 , 0x9B908414, 60), /* [N * 0x9B908414 >> 60] (rcp=2609939476) */ \ + ENTRY(521256293 , 0x83D596FA, 60), /* [N * 0x83D596FA >> 60] (rcp=2211813114) */ \ + ENTRY(615082441 , 0xDF72B16E, 61), /* [N * 0xDF72B16E >> 61] (rcp=3748835694) */ \ + ENTRY(725797313 , 0xBD5CDB3B, 61), /* [N * 0xBD5CDB3B >> 61] (rcp=3176979259) */ \ + ENTRY(856440829 , 0xA07A14E9, 61), /* [N * 0xA07A14E9 >> 61] (rcp=2692355305) */ \ + ENTRY(1010600209, 0x87FF5289, 61), /* [N * 0x87FF5289 >> 61] (rcp=2281656969) */ \ + ENTRY(1192508257, 0xE6810540, 62), /* [N * 0xE6810540 >> 62] (rcp=3867215168) */ \ + ENTRY(1407159797, 0xC357A480, 62), /* [N * 0xC357A480 >> 62] (rcp=3277300864) */ \ + ENTRY(1660448617, 0xA58B5B4F, 62), /* [N * 0xA58B5B4F >> 62] (rcp=2777373519) */ \ + ENTRY(1959329399, 0x8C4AB55F, 62), /* [N * 0x8C4AB55F >> 62] (rcp=2353706335) */ \ + ENTRY(2312008693, 0xEDC86320, 63), /* [N * 0xEDC86320 >> 63] (rcp=3989332768) */ \ + ENTRY(2728170257, 0xC982C4D2, 63), /* [N * 0xC982C4D2 >> 63] (rcp=3380790482) */ \ + ENTRY(3219240923, 0xAAC599B6, 63) /* [N * 0xAAC599B6 >> 63] (rcp=2865076662) */ - size_t i = 0; - uint32_t p; - do { - if ((p = primeTable[i]) > x) - break; - } while (++i < ASMJIT_ARRAY_SIZE(primeTable)); +struct HashPrime { + //! Prime number + uint32_t prime; + //! Reciprocal to turn division into multiplication. + uint32_t rcp; +}; - return p; -} +static const HashPrime ZoneHash_primeArray[] = { + #define E(PRIME, RCP, SHIFT) { PRIME, RCP } + ASMJIT_POPULATE_PRIMES(E) + #undef E +}; + +static const uint8_t ZoneHash_primeShift[] = { + #define E(PRIME, RCP, SHIFT) uint8_t(SHIFT) + ASMJIT_POPULATE_PRIMES(E) + #undef E +}; // ============================================================================ // [asmjit::ZoneHashBase - Rehash] // ============================================================================ -void ZoneHashBase::_rehash(ZoneAllocator* allocator, uint32_t newCount) noexcept { +void ZoneHashBase::_rehash(ZoneAllocator* allocator, uint32_t primeIndex) noexcept { + ASMJIT_ASSERT(primeIndex < ASMJIT_ARRAY_SIZE(ZoneHash_primeArray)); + uint32_t newCount = ZoneHash_primeArray[primeIndex].prime; + ZoneHashNode** oldData = _data; ZoneHashNode** newData = reinterpret_cast( allocator->allocZeroed(size_t(newCount) * sizeof(ZoneHashNode*))); @@ -48,26 +186,27 @@ void ZoneHashBase::_rehash(ZoneAllocator* allocator, uint32_t newCount) noexcept uint32_t i; uint32_t oldCount = _bucketsCount; + _data = newData; + _bucketsCount = newCount; + _bucketsGrow = uint32_t(newCount * 0.9); + _rcpValue = ZoneHash_primeArray[primeIndex].rcp; + _rcpShift = ZoneHash_primeShift[primeIndex]; + _primeIndex = uint8_t(primeIndex); + for (i = 0; i < oldCount; i++) { ZoneHashNode* node = oldData[i]; while (node) { ZoneHashNode* next = node->_hashNext; - uint32_t hMod = node->_hashCode % newCount; + uint32_t hashMod = _calcMod(node->_hashCode); - node->_hashNext = newData[hMod]; - newData[hMod] = node; + node->_hashNext = newData[hashMod]; + newData[hashMod] = node; node = next; } } - // 90% is the maximum occupancy, can't overflow since the maximum capacity - // is limited to the last prime number stored in the prime table. if (oldData != _embedded) - allocator->release(oldData, _bucketsCount * sizeof(ZoneHashNode*)); - - _bucketsCount = newCount; - _bucketsGrow = newCount * 9 / 10; - _data = newData; + allocator->release(oldData, oldCount * sizeof(ZoneHashNode*)); } // ============================================================================ @@ -75,16 +214,16 @@ void ZoneHashBase::_rehash(ZoneAllocator* allocator, uint32_t newCount) noexcept // ============================================================================ ZoneHashNode* ZoneHashBase::_insert(ZoneAllocator* allocator, ZoneHashNode* node) noexcept { - uint32_t hMod = node->_hashCode % _bucketsCount; - ZoneHashNode* next = _data[hMod]; + uint32_t hashMod = _calcMod(node->_hashCode); + ZoneHashNode* next = _data[hashMod]; node->_hashNext = next; - _data[hMod] = node; + _data[hashMod] = node; - if (++_size >= _bucketsGrow && next) { - uint32_t newCapacity = ZoneHash_getClosestPrime(_bucketsCount); - if (newCapacity != _bucketsCount) - _rehash(allocator, newCapacity); + if (++_size > _bucketsGrow) { + uint32_t primeIndex = Support::min(_primeIndex + 2, ASMJIT_ARRAY_SIZE(ZoneHash_primeArray) - 1); + if (primeIndex > _primeIndex) + _rehash(allocator, primeIndex); } return node; @@ -92,9 +231,9 @@ ZoneHashNode* ZoneHashBase::_insert(ZoneAllocator* allocator, ZoneHashNode* node ZoneHashNode* ZoneHashBase::_remove(ZoneAllocator* allocator, ZoneHashNode* node) noexcept { ASMJIT_UNUSED(allocator); - uint32_t hMod = node->_hashCode % _bucketsCount; + uint32_t hashMod = _calcMod(node->_hashCode); - ZoneHashNode** pPrev = &_data[hMod]; + ZoneHashNode** pPrev = &_data[hashMod]; ZoneHashNode* p = *pPrev; while (p) { @@ -134,7 +273,7 @@ struct MyKeyMatcher { uint32_t _key; }; -UNIT(asmjit_zone_hash) { +UNIT(zone_hash) { uint32_t kCount = BrokenAPI::hasArg("--quick") ? 1000 : 10000; Zone zone(4096); diff --git a/src/asmjit/core/zonehash.h b/src/asmjit/core/zonehash.h index 88b6590..79d2a47 100644 --- a/src/asmjit/core/zonehash.h +++ b/src/asmjit/core/zonehash.h @@ -47,15 +47,21 @@ class ZoneHashBase { public: ASMJIT_NONCOPYABLE(ZoneHashBase) + //! Buckets data. + ZoneHashNode** _data; //! Count of records inserted into the hash table. size_t _size; //! Count of hash buckets. uint32_t _bucketsCount; - //! When buckets array should grow. + //! When buckets array should grow (only checked after insertion). uint32_t _bucketsGrow; + //! Reciprocal value of `_bucketsCount`. + uint32_t _rcpValue; + //! How many bits to shift right when hash is multiplied with `_rcpValue`. + uint8_t _rcpShift; + //! Prime value index in internal prime array. + uint8_t _primeIndex; - //! Buckets data. - ZoneHashNode** _data; //! Embedded data, used by empty hash tables. ZoneHashNode* _embedded[1]; @@ -63,28 +69,30 @@ public: //! \{ inline ZoneHashBase() noexcept { - _size = 0; - _bucketsCount = 1; - _bucketsGrow = 1; - _data = _embedded; - _embedded[0] = nullptr; + reset(); } inline ZoneHashBase(ZoneHashBase&& other) noexcept { + _data = other._data; _size = other._size; _bucketsCount = other._bucketsCount; _bucketsGrow = other._bucketsGrow; - _data = other._data; + _rcpValue = other._rcpValue; + _rcpShift = other._rcpShift; + _primeIndex = other._primeIndex; _embedded[0] = other._embedded[0]; if (_data == other._embedded) _data = _embedded; } inline void reset() noexcept { + _data = _embedded; _size = 0; _bucketsCount = 1; _bucketsGrow = 1; - _data = _embedded; + _rcpValue = 1; + _rcpShift = 0; + _primeIndex = 0; _embedded[0] = nullptr; } @@ -109,10 +117,13 @@ public: //! \{ inline void _swap(ZoneHashBase& other) noexcept { + std::swap(_data, other._data); std::swap(_size, other._size); std::swap(_bucketsCount, other._bucketsCount); std::swap(_bucketsGrow, other._bucketsGrow); - std::swap(_data, other._data); + std::swap(_rcpValue, other._rcpValue); + std::swap(_rcpShift, other._rcpShift); + std::swap(_primeIndex, other._primeIndex); std::swap(_embedded[0], other._embedded[0]); if (_data == other._embedded) _data = _embedded; @@ -120,6 +131,11 @@ public: } //! \cond INTERNAL + inline uint32_t _calcMod(uint32_t hash) const noexcept { + uint32_t x = uint32_t((uint64_t(hash) * _rcpValue) >> _rcpShift); + return hash - x * _bucketsCount; + } + ASMJIT_API void _rehash(ZoneAllocator* allocator, uint32_t newCount) noexcept; ASMJIT_API ZoneHashNode* _insert(ZoneAllocator* allocator, ZoneHashNode* node) noexcept; ASMJIT_API ZoneHashNode* _remove(ZoneAllocator* allocator, ZoneHashNode* node) noexcept; @@ -163,8 +179,8 @@ public: template inline NodeT* get(const KeyT& key) const noexcept { - uint32_t hMod = key.hashCode() % _bucketsCount; - NodeT* node = static_cast(_data[hMod]); + uint32_t hashMod = _calcMod(key.hashCode()); + NodeT* node = static_cast(_data[hashMod]); while (node && !key.matches(node)) node = static_cast(node->_hashNext); diff --git a/src/asmjit/core/zonelist.cpp b/src/asmjit/core/zonelist.cpp index 41b69bb..557feb8 100644 --- a/src/asmjit/core/zonelist.cpp +++ b/src/asmjit/core/zonelist.cpp @@ -18,7 +18,7 @@ ASMJIT_BEGIN_NAMESPACE #if defined(ASMJIT_TEST) class MyListNode : public ZoneListNode {}; -UNIT(asmjit_zone_list) { +UNIT(zone_list) { Zone zone(4096); ZoneList list; diff --git a/src/asmjit/core/zonestack.cpp b/src/asmjit/core/zonestack.cpp index 9c375b6..d11e92a 100644 --- a/src/asmjit/core/zonestack.cpp +++ b/src/asmjit/core/zonestack.cpp @@ -169,7 +169,7 @@ static void test_zone_stack(ZoneAllocator* allocator, const char* typeName) { EXPECT(stack.empty()); } -UNIT(asmjit_zone_stack) { +UNIT(zone_stack) { Zone zone(8096 - Zone::kBlockOverhead); ZoneAllocator allocator(&zone); diff --git a/src/asmjit/core/zonetree.cpp b/src/asmjit/core/zonetree.cpp index a89c6e2..95237fb 100644 --- a/src/asmjit/core/zonetree.cpp +++ b/src/asmjit/core/zonetree.cpp @@ -66,7 +66,7 @@ public: uint32_t _key; }; -UNIT(asmjit_zone_rbtree) { +UNIT(zone_rbtree) { uint32_t kCount = BrokenAPI::hasArg("--quick") ? 1000 : 10000; Zone zone(4096); diff --git a/src/asmjit/core/zonevector.cpp b/src/asmjit/core/zonevector.cpp index daa2ff4..29c4c2d 100644 --- a/src/asmjit/core/zonevector.cpp +++ b/src/asmjit/core/zonevector.cpp @@ -346,7 +346,7 @@ static void test_zone_bitvector(ZoneAllocator* allocator) { } } -UNIT(asmjit_zone_vector) { +UNIT(zone_vector) { Zone zone(8096 - Zone::kBlockOverhead); ZoneAllocator allocator(&zone); diff --git a/src/asmjit/x86/x86instapi.cpp b/src/asmjit/x86/x86instapi.cpp index 21c23bb..6b170dc 100644 --- a/src/asmjit/x86/x86instapi.cpp +++ b/src/asmjit/x86/x86instapi.cpp @@ -1505,7 +1505,7 @@ Error InstInternal::queryFeatures(uint32_t archId, const BaseInst& inst, const O // ============================================================================ #if defined(ASMJIT_TEST) -UNIT(asmjit_x86_inst_api_text) { +UNIT(x86_inst_api_text) { // All known instructions should be matched. INFO("Matching all X86 instructions"); for (uint32_t a = 1; a < Inst::_kIdCount; a++) { diff --git a/src/asmjit/x86/x86instdb.cpp b/src/asmjit/x86/x86instdb.cpp index 4957ec4..542864d 100644 --- a/src/asmjit/x86/x86instdb.cpp +++ b/src/asmjit/x86/x86instdb.cpp @@ -3944,7 +3944,7 @@ const InstDB::RWInfoRm InstDB::rwInfoRm[] = { // ============================================================================ #if defined(ASMJIT_TEST) -UNIT(asmjit_x86_inst_db) { +UNIT(x86_inst_db) { INFO("Checking validity of Inst enums"); // Cross-validate prefixes. diff --git a/src/asmjit/x86/x86operand.cpp b/src/asmjit/x86/x86operand.cpp index be367e0..ec24880 100644 --- a/src/asmjit/x86/x86operand.cpp +++ b/src/asmjit/x86/x86operand.cpp @@ -42,7 +42,7 @@ const OpData opData = { // ============================================================================ #if defined(ASMJIT_TEST) -UNIT(asmjit_x86_operand) { +UNIT(x86_operand) { Label L(1000); // Label with some ID. INFO("Checking basic properties of built-in X86 registers"); diff --git a/test/asmjit_test_x86_cc.cpp b/test/asmjit_test_x86_cc.cpp index 9175201..6fb144e 100644 --- a/test/asmjit_test_x86_cc.cpp +++ b/test/asmjit_test_x86_cc.cpp @@ -504,13 +504,13 @@ public: cc.setArg(1, val); cc.cmp(val, 0); - cc.je(L0); + cc.je(L2); cc.cmp(val, 1); cc.je(L1); cc.cmp(val, 2); - cc.je(L2); + cc.je(L0); cc.mov(x86::dword_ptr(dst), val); cc.jmp(LEnd); diff --git a/test/broken.cpp b/test/broken.cpp index eae6e5c..1d3ddfa 100644 --- a/test/broken.cpp +++ b/test/broken.cpp @@ -271,16 +271,20 @@ void BrokenAPI::info(const char* fmt, ...) noexcept { va_end(ap); } -void BrokenAPI::fail(const char* file, int line, const char* fmt, ...) noexcept { +void BrokenAPI::fail(const char* file, int line, const char* expression, const char* fmt, ...) noexcept { BrokenGlobal& global = _brokenGlobal; FILE* dst = global.file(); - va_list ap; - va_start(ap, fmt); - BrokenAPI_printMessage(" FAILED!", fmt, ap); - va_end(ap); + fprintf(dst, " FAILED: %s\n", expression); - fprintf(dst, " File: %s (Line: %d)\n", file, line); + if (fmt) { + va_list ap; + va_start(ap, fmt); + BrokenAPI_printMessage(" REASON: ", fmt, ap); + va_end(ap); + } + + fprintf(dst, " SOURCE: %s (Line: %d)\n", file, line); fflush(dst); exit(1); diff --git a/test/broken.h b/test/broken.h index 9923ce1..1cc04e2 100644 --- a/test/broken.h +++ b/test/broken.h @@ -70,20 +70,20 @@ struct BrokenAPI { static void info(const char* fmt, ...) noexcept; //! Called on `EXPECT()` failure. - static void fail(const char* file, int line, const char* fmt, ...) noexcept; + static void fail(const char* file, int line, const char* expression, const char* fmt, ...) noexcept; //! Used internally by `EXPECT` macro. template - static inline void expect(const char* file, int line, const T& exp) noexcept { - if (!exp) - fail(file, line, nullptr); + static inline void expect(const char* file, int line, const char* expression, const T& result) noexcept { + if (!result) + fail(file, line, expression, nullptr); } //! Used internally by `EXPECT` macro. template - static inline void expect(const char* file, int line, const T& exp, const char* fmt, Args&&... args) noexcept { - if (!exp) - fail(file, line, fmt, std::forward(args)...); + static inline void expect(const char* file, int line, const char* expression, const T& result, const char* fmt, Args&&... args) noexcept { + if (!result) + fail(file, line, expression, fmt, std::forward(args)...); } }; @@ -92,11 +92,14 @@ struct BrokenAPI { // ============================================================================ //! Internal macro used by `UNIT()`. -#define UNIT_INTERNAL(NAME, ...) \ +#define BROKEN_UNIT_INTERNAL(NAME, PRIORITY) \ static void unit_##NAME##_entry(void); \ - static ::BrokenAPI::AutoUnit unit_##NAME##_autoinit(unit_##NAME##_entry, #NAME, __VA_ARGS__); \ + static ::BrokenAPI::AutoUnit unit_##NAME##_autoinit(unit_##NAME##_entry, #NAME, PRIORITY); \ static void unit_##NAME##_entry(void) +//! Stringifies the expression used by EXPECT(). +#define BROKEN_STRINFIGY_EXPRESSION_INTERNAL(EXP, ...) #EXP + //! \def UNIT(NAME [, PRIORITY]) //! //! Define a unit test with an optional priority. @@ -107,7 +110,7 @@ struct BrokenAPI { //! `PRIORITY` specifies the order in which unit tests are run. Lesses value //! increases the priority. At the moment all units are first sorted by //! priority and then by name - this makes the run always deterministic. -#define UNIT(...) UNIT_INTERNAL(__VA_ARGS__, 0) +#define UNIT(NAME, ...) BROKEN_UNIT_INTERNAL(NAME, __VA_ARGS__ + 0) //! #define INFO(FORMAT [, ...]) //! @@ -117,7 +120,7 @@ struct BrokenAPI { //! #define INFO(EXP [, FORMAT [, ...]]) //! //! Expect `EXP` to be true or evaluates to true, fail otherwise. -#define EXPECT(...) ::BrokenAPI::expect(__FILE__, __LINE__, __VA_ARGS__) +#define EXPECT(...) ::BrokenAPI::expect(__FILE__, __LINE__, BROKEN_STRINFIGY_EXPRESSION_INTERNAL(__VA_ARGS__), __VA_ARGS__) //! \endcond