add PLT_DUMP_JIT_RANGES

This variable is intended to support machine-code tracing
experiments. To enable a dump of ranges on exit, both
define PLT_DUMP_JIT_RANGES at compile time and as an environment
variable at run time.
This commit is contained in:
Matthew Flatt 2013-08-17 08:40:38 -06:00
parent 9888c7f496
commit f93f488a5a
2 changed files with 109 additions and 0 deletions

View File

@ -20,6 +20,45 @@ extern MZ_DLLIMPORT int GC_is_marked(void *);
#define NODE_STARTS_OFFSET 1 #define NODE_STARTS_OFFSET 1
#define NODE_GCABLE_OFFSET 2 #define NODE_GCABLE_OFFSET 2
/* Represent a node in the tree as an array of
NODE_HEADER_SIZE + KEY_COUNT pointers.
The first pointer is always NULL, so that the node can be
recognized as a node (as opposed to a Racket value) when referenced
by other nodes.
The second "pointer" is used as an array of bits, where each bit
indicates whether the corresponding pointer is the start of a
mapped range. The bits are shfted up by 1 an dthe low bit is always
set to 1, so that the GC doesn't think it's a pointer.
The third "pointer" is similar to the first, but it represents the
GC status of the reference, andthe bit is only used at a ramge
start.
Then there are KEY_COUNT "key" pointers for the content of the
node. Note that KEY_COUNT is smaller than the number of bits
available in the header's second and third "pointer"s.
In a leaf node, every "key" corresponds to an address. In a node
that references leaf nodes, every "key" corresponds to KEY_SIZE
addresses. So, at the root, the first key corresonds to address 0,
the second key corresponds to address (1 << (32-LOG_KEY_SIZE)) on a
32-bit platform, and so on.
To make the tree more compact, when all of the pointers in a node
would be the same non-node value, then the node itself can be
replaced with the non-node value. (That's why we need to be able to
distinguish node references from Scheme-object references.) Of
course, "leaf node" above means nodes that would be leaves without
this compaction.
When PLT_DUMP_JIT_RANGES is defined for compilation and as an
environment variable at run time, then an exit hook prints the
ranges of JIT-generated code. Furthermore, for 3m, defining
PLT_DUMP_JIT_RANGES at compilation time disables GC of
JIT-generated code. */
THREAD_LOCAL_DECL(static void **codetab_tree); THREAD_LOCAL_DECL(static void **codetab_tree);
THREAD_LOCAL_DECL(static int during_set); THREAD_LOCAL_DECL(static int during_set);
#ifdef MZ_USE_PLACES #ifdef MZ_USE_PLACES
@ -30,6 +69,11 @@ static void **shared_codetab_tree;
static mzrt_mutex *shared_codetab_lock; static mzrt_mutex *shared_codetab_lock;
#endif #endif
#ifdef PLT_DUMP_JIT_RANGES
static int dump_registered = 0;
static void dump_symbol_ranges();
#endif
static int do_clear_symbols(void **t, uintptr_t start, int offset, uintptr_t addr, int clearing); static int do_clear_symbols(void **t, uintptr_t start, int offset, uintptr_t addr, int clearing);
static void *do_find_symbol(void **the_tree, uintptr_t v) static void *do_find_symbol(void **the_tree, uintptr_t v)
@ -98,6 +142,14 @@ void scheme_jit_add_symbol(uintptr_t start, uintptr_t end, void *value, int gc_a
int offset = (JIT_WORD_SIZE * 8), split_offset = 0; int offset = (JIT_WORD_SIZE * 8), split_offset = 0;
void **the_tree, **t1, **t2, **split_t, *val1, *val2; void **the_tree, **t1, **t2, **split_t, *val1, *val2;
#ifdef PLT_DUMP_JIT_RANGES
if (!dump_registered) {
dump_registered = 1;
if (getenv("PLT_DUMP_JIT_RANGES"))
atexit(dump_symbol_ranges);
}
#endif
#ifdef MZ_USE_PLACES #ifdef MZ_USE_PLACES
if (!gc_able) { if (!gc_able) {
if (!shared_codetab_lock) { if (!shared_codetab_lock) {
@ -318,6 +370,60 @@ static void clear_symbols_for_collected()
#endif #endif
#ifdef PLT_DUMP_JIT_RANGES
static void *dump_symbol_range(void **t, int offset, uintptr_t base, void *val)
{
int i, m;
void *p;
offset -= LOG_KEY_SIZE;
for (i = 0; i < KEY_COUNT; i++) {
p = t[i + NODE_HEADER_SIZE];
if (p) {
if (*(Scheme_Type *)p) {
int is_start;
m = (1 << (i + 1));
is_start = (((uintptr_t *)t)[NODE_STARTS_OFFSET] & m);
if (val && ((p != val) || is_start)) {
printf("%" PRIxPTR "\n", base + (((uintptr_t)i - 1) << offset)); /* end range */
val = NULL;
}
if (is_start) {
/* start new range */
val = p;
printf("%" PRIxPTR "-", base + ((uintptr_t)i << offset));
if (find_symbol(base + ((uintptr_t)i << offset)) != val)
printf("[oops]");
}
} else {
val = dump_symbol_range((void **)p, offset, base + ((uintptr_t)i << offset), val);
}
} else if (val) {
printf("%" PRIxPTR "\n", base + (((uintptr_t)i - 1) << offset)); /* end range */
val = NULL;
}
}
return val;
}
static void dump_symbol_ranges()
{
(void)dump_symbol_range(codetab_tree, JIT_WORD_SIZE * 8, 0, NULL);
#ifdef MZ_USE_PLACES
if (shared_codetab_tree)
(void)dump_symbol_range(shared_codetab_tree, JIT_WORD_SIZE * 8, 0, NULL);
#endif
}
#endif
/*============================================================*/ /*============================================================*/
/* testing */ /* testing */
/*============================================================*/ /*============================================================*/

View File

@ -602,10 +602,13 @@ void scheme_jit_release_native_code(void *fnlized, void *p)
scheme_jit_malloced -= SCHEME_INT_VAL(len); scheme_jit_malloced -= SCHEME_INT_VAL(len);
# if !defined(PLT_DUMP_JIT_RANGES)
/* Remove name mapping: */ /* Remove name mapping: */
scheme_jit_add_symbol((uintptr_t)p, (uintptr_t)p + SCHEME_INT_VAL(len), NULL, 1); scheme_jit_add_symbol((uintptr_t)p, (uintptr_t)p + SCHEME_INT_VAL(len), NULL, 1);
/* Free memory: */ /* Free memory: */
scheme_free_code(p); scheme_free_code(p);
# endif
jit_notify_freed_code(); jit_notify_freed_code();
} }
#endif #endif