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