| 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 |  |