summaryrefslogtreecommitdiff
path: root/src/inc/nibblemapmacros.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/inc/nibblemapmacros.h')
-rw-r--r--src/inc/nibblemapmacros.h56
1 files changed, 56 insertions, 0 deletions
diff --git a/src/inc/nibblemapmacros.h b/src/inc/nibblemapmacros.h
new file mode 100644
index 0000000000..42ea90a2b6
--- /dev/null
+++ b/src/inc/nibblemapmacros.h
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#ifndef NIBBLEMAPMACROS_H_
+#define NIBBLEMAPMACROS_H_
+
+///////////////////////////////////////////////////////////////////////
+//// some mmgr stuff for JIT, especially for jit code blocks
+///////////////////////////////////////////////////////////////////////
+//
+// In order to quickly find the start of a jit code block
+// we keep track of all those positions via a map.
+// Each entry in this map represents 32 byte (a bucket) of the code heap.
+// We make the assumption that no two code-blocks can start in
+// the same 32byte bucket;
+// Additionally we assume that every code header is DWORD aligned.
+// Because we cannot guarantee that jitblocks always start at
+// multiples of 32 bytes we cannot use a simple bitmap; instead we
+// use a nibble (4 bit) per bucket and encode the offset of the header
+// inside the bucket (in DWORDS). In order to make initialization
+// easier we add one to the real offset, a nibble-value of zero
+// means that there is no header start in the resp. bucket.
+// In order to speed up "backwards scanning" we start numbering
+// nibbles inside a DWORD from the highest bits (28..31). Because
+// of that we can scan backwards inside the DWORD with right shifts.
+
+#if defined(_WIN64)
+// TODO: bump up the windows CODE_ALIGN to 16 and iron out any nibble map bugs that exist.
+// TODO: there is something wrong with USE_INDIRECT_CODEHEADER with CODE_ALIGN=16
+# define CODE_ALIGN 4
+# define LOG2_CODE_ALIGN 2
+#else
+# define CODE_ALIGN sizeof(DWORD) // 4 byte boundry
+# define LOG2_CODE_ALIGN 2
+#endif
+#define NIBBLE_MASK 0xf
+#define NIBBLE_SIZE 4 // 4 bits
+#define LOG2_NIBBLE_SIZE 2
+#define NIBBLES_PER_DWORD ((8*sizeof(DWORD)) >> LOG2_NIBBLE_SIZE) // 8 (4-bit) nibbles per dword
+#define NIBBLES_PER_DWORD_MASK (NIBBLES_PER_DWORD - 1) // 7
+#define LOG2_NIBBLES_PER_DWORD 3
+#define BYTES_PER_BUCKET (NIBBLES_PER_DWORD * CODE_ALIGN) // 32 bytes per bucket
+#define LOG2_BYTES_PER_BUCKET (LOG2_CODE_ALIGN + LOG2_NIBBLES_PER_DWORD) // 5 bits per bucket
+#define MASK_BYTES_PER_BUCKET (BYTES_PER_BUCKET - 1) // 31
+#define HIGHEST_NIBBLE_BIT (32 - NIBBLE_SIZE) // 28 (i.e 32 - 4)
+#define HIGHEST_NIBBLE_MASK (NIBBLE_MASK << HIGHEST_NIBBLE_BIT) // 0xf0000000
+
+#define ADDR2POS(x) ((x) >> LOG2_BYTES_PER_BUCKET)
+#define ADDR2OFFS(x) (DWORD) ((((x) & MASK_BYTES_PER_BUCKET) >> LOG2_CODE_ALIGN) + 1)
+#define POSOFF2ADDR(pos, of) (size_t) (((pos) << LOG2_BYTES_PER_BUCKET) + (((of) - 1) << LOG2_CODE_ALIGN))
+#define HEAP2MAPSIZE(x) (((x) / (BYTES_PER_BUCKET * NIBBLES_PER_DWORD)) * CODE_ALIGN)
+#define POS2SHIFTCOUNT(x) (DWORD) (HIGHEST_NIBBLE_BIT - (((x) & NIBBLES_PER_DWORD_MASK) << LOG2_NIBBLE_SIZE))
+#define POS2MASK(x) (DWORD) ~(HIGHEST_NIBBLE_MASK >> (((x) & NIBBLES_PER_DWORD_MASK) << LOG2_NIBBLE_SIZE))
+
+#endif // NIBBLEMAPMACROS_H_