/home/travis/build/MoarVM/MoarVM/src/jit/log.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "moar.h" |
2 | | |
3 | | /* inline this? maybe */ |
4 | 3.21M | void MVM_jit_log(MVMThreadContext *tc, const char * fmt, ...) { |
5 | 3.21M | va_list args; |
6 | 3.21M | va_start(args, fmt); |
7 | 3.21M | if (tc->instance->jit_log_fh) { |
8 | 0 | vfprintf(tc->instance->jit_log_fh, fmt, args); |
9 | 0 | } |
10 | 3.21M | va_end(args); |
11 | 3.21M | } |
12 | | |
13 | 0 | void MVM_jit_log_bytecode(MVMThreadContext *tc, MVMJitCode *code) { |
14 | 0 | /* Filename format: moar-jit-%d.bin. number can consume at most 10 |
15 | 0 | * bytes, moar-jit-.bin is 13 bytes, one byte for the zero at the |
16 | 0 | * end, one byte for the directory separator is 25 bytes, plus the |
17 | 0 | * length of the bytecode directory itself */ |
18 | 0 | size_t filename_size = strlen(tc->instance->jit_bytecode_dir) + 25; |
19 | 0 | char * filename = MVM_malloc(filename_size); |
20 | 0 | FILE * out; |
21 | 0 | snprintf(filename, filename_size, "%s/moar-jit-%04d.bin", tc->instance->jit_bytecode_dir, code->seq_nr); |
22 | 0 | out = fopen(filename, "w"); |
23 | 0 | if (out) { |
24 | 0 | fwrite(code->func_ptr, sizeof(char), code->size, out); |
25 | 0 | fclose(out); |
26 | 0 | if (tc->instance->jit_bytecode_map) { |
27 | 0 | char *frame_name = code->sf |
28 | 0 | ? MVM_string_utf8_encode_C_string(tc, code->sf->body.name) |
29 | 0 | : NULL; |
30 | 0 | char *frame_cuuid = code->sf |
31 | 0 | ? MVM_string_utf8_encode_C_string(tc, code->sf->body.cuuid) |
32 | 0 | : NULL; |
33 | 0 | /* I'd like to add linenumber and filename information, but it's really a lot of work at this point */ |
34 | 0 | fprintf( |
35 | 0 | tc->instance->jit_bytecode_map, |
36 | 0 | "%s\t%s\t%s\n", |
37 | 0 | filename, |
38 | 0 | frame_name ? frame_name : "(unknown)", |
39 | 0 | frame_cuuid ? frame_cuuid : "(unknown)" |
40 | 0 | ); |
41 | 0 | fflush(tc->instance->jit_bytecode_map); |
42 | 0 | MVM_free(frame_name); |
43 | 0 | MVM_free(frame_cuuid); |
44 | 0 | } |
45 | 0 | } else { |
46 | 0 | MVM_jit_log(tc, "ERROR: could dump bytecode in %s\n", filename); |
47 | 0 | } |
48 | 0 | MVM_free(filename); |
49 | 0 | } |
50 | | |
51 | | |
52 | | static void dump_tree(MVMThreadContext *tc, MVMJitTreeTraverser *traverser, |
53 | 0 | MVMJitExprTree *tree, MVMint32 node) { |
54 | 0 | MVMJitExprNodeInfo *info = &tree->info[node]; |
55 | 0 | const MVMJitExprOpInfo *op = info->op_info; |
56 | 0 | MVMint32 *depth = traverser->data; |
57 | 0 | MVMint32 i, j; |
58 | 0 | char indent[64]; |
59 | 0 | char nargs[80]; |
60 | 0 |
|
61 | 0 | (*depth)++; |
62 | 0 | #define MIN(a,b) ((a) < (b) ? (a) : (b)) |
63 | 0 | i = MIN(*depth*2, sizeof(indent)-1); |
64 | 0 | memset(indent, ' ', i); |
65 | 0 | indent[i] = 0; |
66 | 0 | j = 0; |
67 | 0 | for (i = 0; i < op->nargs; i++) { |
68 | 0 | MVMint64 arg = tree->nodes[node+op->nchild+i+1]; |
69 | 0 | j += snprintf(nargs + j, sizeof(nargs)-j-3, "%"PRId64, arg); |
70 | 0 | if (i+1 < op->nargs && j < sizeof(nargs)-3) { |
71 | 0 | j += sprintf(nargs + j, ", "); |
72 | 0 | } |
73 | 0 | } |
74 | 0 | nargs[j] = 0; |
75 | 0 | MVM_jit_log(tc, "%04d%s%s (%s; sz=%d)\n", node, indent, op->name, |
76 | 0 | nargs, info->size); |
77 | 0 | } |
78 | | |
79 | | static void ascend_tree(MVMThreadContext *tc, MVMJitTreeTraverser *traverser, |
80 | 0 | MVMJitExprTree *tree, MVMint32 node) { |
81 | 0 | MVMint32 *depth = traverser->data; |
82 | 0 | (*depth)--; |
83 | 0 | } |
84 | | |
85 | | |
86 | | static void write_graphviz_node(MVMThreadContext *tc, MVMJitTreeTraverser *traverser, |
87 | 0 | MVMJitExprTree *tree, MVMint32 node) { |
88 | 0 | FILE *graph_file = traverser->data; |
89 | 0 | const MVMJitExprOpInfo *op_info = tree->info[node].op_info; |
90 | 0 | MVMint32 first_child = node + 1; |
91 | 0 | MVMint32 nchild = op_info->nchild < 0 ? tree->nodes[first_child++] : op_info->nchild; |
92 | 0 | MVMint32 first_arg = first_child + nchild; |
93 | 0 | MVMint32 i; |
94 | 0 | /* maximum length of op name is 'invokish' at 8 characters, let's allocate |
95 | 0 | * 16; maximum number of parameters is 4, and 64 bits; printing them in |
96 | 0 | * hexadecimal would require at most 8 characters, plus 4 for the '0x' and |
97 | 0 | * the ', '; minus 2 for the last one, plus 2 for the ampersands, plus 0 for |
98 | 0 | * the terminus, gives us 16 + 4*12 + 3 = 67; 80 should be plenty */ |
99 | 0 | char node_label[80]; |
100 | 0 | char *ptr = node_label + sprintf(node_label, "%s%s", op_info->name, |
101 | 0 | op_info->nargs ? "(" : ""); |
102 | 0 | for (i = 0; i < op_info->nargs; i++) { |
103 | 0 | ptr += sprintf(ptr, "%#" PRIx64 "%s", tree->nodes[first_arg+i], |
104 | 0 | (i + 1 < op_info->nargs) ? ", " : ")"); |
105 | 0 | } |
106 | 0 |
|
107 | 0 | fprintf(graph_file, " n_%04d [label=\"%s\"];\n", node, node_label); |
108 | 0 | for (i = 0; i < nchild; i++) { |
109 | 0 | fprintf(graph_file, " n_%04d -> n_%04d;\n", node, (MVMint32)tree->nodes[first_child+i]); |
110 | 0 | } |
111 | 0 | } |
112 | | |
113 | | |
114 | 262k | void MVM_jit_log_expr_tree(MVMThreadContext *tc, MVMJitExprTree *tree) { |
115 | 262k | MVMJitTreeTraverser traverser; |
116 | 262k | if (!tc->instance->jit_log_fh) |
117 | 262k | return; |
118 | 0 | traverser.policy = MVM_JIT_TRAVERSER_ONCE; |
119 | 0 | traverser.preorder = NULL; |
120 | 0 | traverser.inorder = NULL; |
121 | 0 | traverser.postorder = &write_graphviz_node; |
122 | 0 | traverser.data = tc->instance->jit_log_fh; |
123 | 0 |
|
124 | 0 | MVM_jit_log(tc, "Starting dump of JIT expression tree\n" |
125 | 0 | "====================================\n"); |
126 | 0 | MVM_jit_log(tc, "digraph {\n"); |
127 | 0 | MVM_jit_expr_tree_traverse(tc, tree, &traverser); |
128 | 0 | MVM_jit_log(tc, "}\n"); |
129 | 0 | MVM_jit_log(tc, "End dump of JIT expression tree\n" |
130 | 0 | "====================================\n"); |
131 | 0 | } |
132 | | |
133 | 253k | void MVM_jit_log_tile_list(MVMThreadContext *tc, MVMJitTileList *list) { |
134 | 253k | MVMint32 i, j; |
135 | 253k | FILE *f = tc->instance->jit_log_fh; |
136 | 253k | if (!f) |
137 | 253k | return; |
138 | 0 | fprintf(f, "Starting tile list log\n" |
139 | 0 | "======================\n"); |
140 | 0 | for (i = 0; i < list->blocks_num; i++) { |
141 | 0 | MVMint32 start = list->blocks[i].start, end = list->blocks[i].end; |
142 | 0 | fprintf(f, "Block{%d} [%d-%d)\n", i, start, end); |
143 | 0 | for (j = start; j < end; j++) { |
144 | 0 | MVMJitTile *tile = list->items[j]; |
145 | 0 | fprintf(f, " %d: %s\n", j, tile->debug_name ? tile->debug_name : ""); |
146 | 0 | } |
147 | 0 | if (list->blocks[i].num_succ == 2) { |
148 | 0 | fprintf(f, "-> { %d, %d }\n", list->blocks[i].succ[0], list->blocks[i].succ[1]); |
149 | 0 | } else if (list->blocks[i].num_succ == 1) { |
150 | 0 | fprintf(f, "-> { %d }\n", list->blocks[i].succ[0]); |
151 | 0 | } else { |
152 | 0 | fprintf(f, "-> {}\n"); |
153 | 0 | } |
154 | 0 |
|
155 | 0 | } |
156 | 0 | fprintf(f, "End of tile list log\n" |
157 | 0 | "======================\n"); |
158 | 0 |
|
159 | 0 | } |