| 1 | // Licensed to the .NET Foundation under one or more agreements. |
| 2 | // The .NET Foundation licenses this file to you under the MIT license. |
| 3 | // See the LICENSE file in the project root for more information. |
| 4 | |
| 5 | #ifndef NIBBLEMAPMACROS_H_ |
| 6 | #define NIBBLEMAPMACROS_H_ |
| 7 | |
| 8 | /////////////////////////////////////////////////////////////////////// |
| 9 | //// some mmgr stuff for JIT, especially for jit code blocks |
| 10 | /////////////////////////////////////////////////////////////////////// |
| 11 | // |
| 12 | // In order to quickly find the start of a jit code block |
| 13 | // we keep track of all those positions via a map. |
| 14 | // Each entry in this map represents 32 byte (a bucket) of the code heap. |
| 15 | // We make the assumption that no two code-blocks can start in |
| 16 | // the same 32byte bucket; |
| 17 | // Additionally we assume that every code header is DWORD aligned. |
| 18 | // Because we cannot guarantee that jitblocks always start at |
| 19 | // multiples of 32 bytes we cannot use a simple bitmap; instead we |
| 20 | // use a nibble (4 bit) per bucket and encode the offset of the header |
| 21 | // inside the bucket (in DWORDS). In order to make initialization |
| 22 | // easier we add one to the real offset, a nibble-value of zero |
| 23 | // means that there is no header start in the resp. bucket. |
| 24 | // In order to speed up "backwards scanning" we start numbering |
| 25 | // nibbles inside a DWORD from the highest bits (28..31). Because |
| 26 | // of that we can scan backwards inside the DWORD with right shifts. |
| 27 | |
| 28 | #if defined(_WIN64) |
| 29 | // TODO: bump up the windows CODE_ALIGN to 16 and iron out any nibble map bugs that exist. |
| 30 | // TODO: there is something wrong with USE_INDIRECT_CODEHEADER with CODE_ALIGN=16 |
| 31 | # define CODE_ALIGN 4 |
| 32 | # define LOG2_CODE_ALIGN 2 |
| 33 | #else |
| 34 | # define CODE_ALIGN sizeof(DWORD) // 4 byte boundry |
| 35 | # define LOG2_CODE_ALIGN 2 |
| 36 | #endif |
| 37 | #define NIBBLE_MASK 0xf |
| 38 | #define NIBBLE_SIZE 4 // 4 bits |
| 39 | #define LOG2_NIBBLE_SIZE 2 |
| 40 | #define NIBBLES_PER_DWORD ((8*sizeof(DWORD)) >> LOG2_NIBBLE_SIZE) // 8 (4-bit) nibbles per dword |
| 41 | #define NIBBLES_PER_DWORD_MASK (NIBBLES_PER_DWORD - 1) // 7 |
| 42 | #define LOG2_NIBBLES_PER_DWORD 3 |
| 43 | #define BYTES_PER_BUCKET (NIBBLES_PER_DWORD * CODE_ALIGN) // 32 bytes per bucket |
| 44 | #define LOG2_BYTES_PER_BUCKET (LOG2_CODE_ALIGN + LOG2_NIBBLES_PER_DWORD) // 5 bits per bucket |
| 45 | #define MASK_BYTES_PER_BUCKET (BYTES_PER_BUCKET - 1) // 31 |
| 46 | #define HIGHEST_NIBBLE_BIT (32 - NIBBLE_SIZE) // 28 (i.e 32 - 4) |
| 47 | #define HIGHEST_NIBBLE_MASK (NIBBLE_MASK << HIGHEST_NIBBLE_BIT) // 0xf0000000 |
| 48 | |
| 49 | #define ADDR2POS(x) ((x) >> LOG2_BYTES_PER_BUCKET) |
| 50 | #define ADDR2OFFS(x) (DWORD) ((((x) & MASK_BYTES_PER_BUCKET) >> LOG2_CODE_ALIGN) + 1) |
| 51 | #define POSOFF2ADDR(pos, of) (size_t) (((pos) << LOG2_BYTES_PER_BUCKET) + (((of) - 1) << LOG2_CODE_ALIGN)) |
| 52 | #define HEAP2MAPSIZE(x) (((x) / (BYTES_PER_BUCKET * NIBBLES_PER_DWORD)) * CODE_ALIGN) |
| 53 | #define POS2SHIFTCOUNT(x) (DWORD) (HIGHEST_NIBBLE_BIT - (((x) & NIBBLES_PER_DWORD_MASK) << LOG2_NIBBLE_SIZE)) |
| 54 | #define POS2MASK(x) (DWORD) ~(HIGHEST_NIBBLE_MASK >> (((x) & NIBBLES_PER_DWORD_MASK) << LOG2_NIBBLE_SIZE)) |
| 55 | |
| 56 | #endif // NIBBLEMAPMACROS_H_ |
| 57 | |