Coverage Report

Created: 2018-07-03 15:31

/home/travis/build/MoarVM/MoarVM/src/spesh/graph.h
Line
Count
Source
1
294k
#define MVMPhiNodeCacheSize             48
2
1.08M
#define MVMPhiNodeCacheSparseBegin      32
3
4
/* Top level of a spesh graph, representing a particular static frame (and
5
 * potentially having others inlined into it). */
6
struct MVMSpeshGraph {
7
    /* The static frame this is the spesh graph for. */
8
    MVMStaticFrame *sf;
9
10
    /* The callsite this spesh graph has been tailored to. */
11
    MVMCallsite *cs;
12
13
    /* The bytecode we're building the graph out of. */
14
    MVMuint8 *bytecode;
15
16
    /* Exception handler map for that bytecode. */
17
    MVMFrameHandler *handlers;
18
19
    /* Handlers that have become unreachable due to dead code removal. */
20
    MVMint8 *unreachable_handlers;
21
22
    /* The size of the bytecode we're building the graph out of. */
23
    MVMuint32 bytecode_size;
24
25
    /* Number of exception handlers. */
26
    MVMuint32 num_handlers;
27
28
    /* The entry basic block. */
29
    MVMSpeshBB *entry;
30
31
    /* Gathered facts about each version of a local (top-level array is per
32
     * local, then array hanging off it is per version). */
33
    MVMSpeshFacts **facts;
34
35
    /* Number of fact entries per local. */
36
    MVMuint16 *fact_counts;
37
38
    /* Log-based guards added. */
39
    MVMSpeshLogGuard *log_guards;
40
41
    /* Number of log-based guards we have. */
42
    MVMint32 num_log_guards;
43
44
    /* Region allocator for spesh nodes */
45
    MVMRegionAlloc region_alloc;
46
47
    /* Values placed in spesh slots. */
48
    MVMCollectable **spesh_slots;
49
50
    /* Number of spesh slots we have used and allocated. */
51
    MVMint32 num_spesh_slots;
52
    MVMint32 alloc_spesh_slots;
53
54
    /* De-opt indexes, as pairs of integers. The first integer, set when we
55
     * build the graph, is the return address in the original bytecode. The
56
     * code-gen phase for the specialized bytecode will fill in the second
57
     * integers afterwards, which are the return address in the specialized
58
     * bytecode. */
59
    MVMint32 *deopt_addrs;
60
    MVMint32  num_deopt_addrs;
61
    MVMint32  alloc_deopt_addrs;
62
63
    /* Bit field of named args used to put in place during deopt, since we
64
     * don't typically don't update the array in specialized code. */
65
    MVMuint64 deopt_named_used_bit_field;
66
67
    /* Table of information about inlines, laid out in order of nesting
68
     * depth. Thus, going through the table in order and finding when we
69
     * are within the bounds will show up each call frame that needs to
70
     * be created in deopt. */
71
    MVMSpeshInline *inlines;
72
    MVMint32 num_inlines;
73
74
    /* Number of basic blocks we have. */
75
    MVMint32 num_bbs;
76
77
    /* The list of local types (only set up if we do inlines). */
78
    MVMuint16 *local_types;
79
80
    /* The list of lexical types (only set up if we do inlines). */
81
    MVMuint16 *lexical_types;
82
83
    /* The total number of locals, accounting for any inlining done and
84
     * added temporaries. */
85
    MVMuint16 num_locals;
86
87
    /* The total number of lexicals, accounting for any inlining done. */
88
    MVMuint16 num_lexicals;
89
90
    /* Temporary local registers added to aid transformations, along with a
91
     * count of the number we have and have allocated space for so far. */
92
    MVMuint16          num_temps;
93
    MVMuint16          alloc_temps;
94
    MVMSpeshTemporary *temps;
95
96
    /* We need to create new MVMOpInfo structs for each number of
97
     * arguments a PHI node can take. We cache them here, so that we
98
     * allocate fewer of them across our spesh alloc blocks.
99
     */
100
    MVMOpInfo *phi_infos;
101
102
    /* If this graph was formed from a spesh candidate rather than an
103
     * original static frame, the candidate will be stored here. */
104
    MVMSpeshCandidate *cand;
105
106
    /* Did we specialize on the invocant type? */
107
    MVMuint8 specialized_on_invocant;
108
};
109
110
/* A temporary register, added to support transformations. */
111
struct MVMSpeshTemporary {
112
    /* The number of the local along with the current SSA index. */
113
    MVMuint16 orig;
114
    MVMuint16 i;
115
116
    /* What kind of register is it? */
117
    MVMuint16 kind;
118
119
    /* Is it currently in use? */
120
    MVMuint16 in_use;
121
};
122
123
/* A basic block in the graph (sequences of instructions where control will
124
 * always enter at the start and leave at the end). */
125
struct MVMSpeshBB {
126
    /* Head/tail of doubly linked list of instructions. */
127
    MVMSpeshIns *first_ins;
128
    MVMSpeshIns *last_ins;
129
130
    /* Basic blocks we may go to after this one. */
131
    MVMSpeshBB **succ;
132
133
    /* Basic blocks that we may arrive into this one from. */
134
    MVMSpeshBB **pred;
135
136
    /* Children in the dominator tree. */
137
    MVMSpeshBB **children;
138
139
    /* Dominance frontier set. */
140
    MVMSpeshBB **df;
141
142
    /* Basic blocks that we may go to if we throw. */
143
    MVMSpeshBB **handler_succ;
144
145
    /* Counts for the above, grouped together to avoid alignment holes. */
146
    MVMuint16    num_succ;
147
    MVMuint16    num_pred;
148
    MVMuint16    num_children;
149
    MVMuint16    num_df;
150
    MVMuint16    num_handler_succ;
151
152
    /* The next basic block in original linear code order. */
153
    MVMSpeshBB *linear_next;
154
155
    /* Index (just an ascending integer along the linear_next chain), used as
156
     * the block identifier in dominance computation and for debug output. */
157
    MVMint32 idx;
158
159
    /* The block's reverse post-order index, assinged when computing
160
     * dominance. */
161
    MVMint32 rpo_idx;
162
163
    /* We cache the instruction pointer of the very first instruction so that
164
     * we can output a line number for every BB */
165
    MVMuint32 initial_pc;
166
167
    /* Is this block an inlining of another one? */
168
    MVMint8 inlined;
169
170
    /* Is this basic block part of a jump list? */
171
    MVMint8 jumplist;
172
173
    /* Is this basic block dead (removed due to being unreachable)? */
174
    MVMint8 dead;
175
};
176
177
/* The SSA phi instruction. */
178
42.1M
#define MVM_SSA_PHI 32767
179
180
/* An instruction in the spesh graph. */
181
struct MVMSpeshIns {
182
    /* Instruction information. */
183
    const MVMOpInfo *info;
184
185
    /* Operand information. */
186
    MVMSpeshOperand *operands;
187
188
    /* Previous and next instructions, within a basic block boundary. */
189
    MVMSpeshIns *prev;
190
    MVMSpeshIns *next;
191
192
    /* Any annotations on the instruction. */
193
    MVMSpeshAnn *annotations;
194
};
195
196
/* Union type of operands in a spesh instruction; the op info and phase of the
197
 * optimizer we're in determines which of these we look at. */
198
union MVMSpeshOperand {
199
    MVMint64     lit_i64;
200
    MVMint32     lit_i32;
201
    MVMuint16    lit_ui32;
202
    MVMint16     lit_i16;
203
    MVMuint16    lit_ui16;
204
    MVMint8      lit_i8;
205
    MVMnum64     lit_n64;
206
    MVMnum32     lit_n32;
207
    MVMuint32    lit_str_idx;
208
    MVMuint16    callsite_idx;
209
    MVMuint16    coderef_idx;
210
    MVMuint32    ins_offset;
211
    MVMSpeshBB  *ins_bb;
212
    struct {
213
        MVMuint16 idx;
214
        MVMuint16 outers;
215
    } lex;
216
    struct {
217
        MVMint32  i;    /* SSA-computed version. */
218
        MVMuint16 orig; /* Original register number. */
219
    } reg;
220
};
221
222
/* Annotations base. */
223
struct MVMSpeshAnn {
224
    /* The next annotation in the chain, if any. */
225
    MVMSpeshAnn *next;
226
227
    /* The type of annotation we have. */
228
    MVMint32 type;
229
230
    /* Data (meaning depends on type). */
231
    union {
232
        MVMint32 frame_handler_index;
233
        MVMint32 deopt_idx;
234
        MVMint32 inline_idx;
235
        MVMuint32 bytecode_offset;
236
        struct {
237
            MVMuint32 filename_string_index;
238
            MVMuint32 line_number;
239
        } lineno;
240
    } data;
241
};
242
243
/* Annotation types. */
244
242k
#define MVM_SPESH_ANN_FH_START      1
245
231k
#define MVM_SPESH_ANN_FH_END        2
246
232k
#define MVM_SPESH_ANN_FH_GOTO       3
247
921k
#define MVM_SPESH_ANN_DEOPT_ONE_INS 4
248
293k
#define MVM_SPESH_ANN_DEOPT_ALL_INS 5
249
43.4k
#define MVM_SPESH_ANN_INLINE_START  6
250
231k
#define MVM_SPESH_ANN_INLINE_END    7
251
206k
#define MVM_SPESH_ANN_DEOPT_INLINE  8
252
31.1k
#define MVM_SPESH_ANN_DEOPT_OSR     9
253
10.8k
#define MVM_SPESH_ANN_LINENO        10
254
287k
#define MVM_SPESH_ANN_LOGGED        11
255
256
/* Functions to create/destroy the spesh graph. */
257
MVMSpeshGraph * MVM_spesh_graph_create(MVMThreadContext *tc, MVMStaticFrame *sf,
258
    MVMuint32 cfg_only, MVMuint32 insert_object_nulls);
259
MVMSpeshGraph * MVM_spesh_graph_create_from_cand(MVMThreadContext *tc, MVMStaticFrame *sf,
260
    MVMSpeshCandidate *cand, MVMuint32 cfg_only);
261
MVMSpeshBB * MVM_spesh_graph_linear_prev(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshBB *search);
262
void MVM_spesh_graph_grow_deopt_table(MVMThreadContext *tc, MVMSpeshGraph *g);
263
void MVM_spesh_graph_add_deopt_annotation(MVMThreadContext *tc, MVMSpeshGraph *g,
264
    MVMSpeshIns *ins_node, MVMuint32 deopt_target, MVMint32 type);
265
void MVM_spesh_graph_recompute_dominance(MVMThreadContext *tc, MVMSpeshGraph *g);
266
void MVM_spesh_graph_mark(MVMThreadContext *tc, MVMSpeshGraph *g, MVMGCWorklist *worklist);
267
void MVM_spesh_graph_destroy(MVMThreadContext *tc, MVMSpeshGraph *g);
268
MVM_PUBLIC void * MVM_spesh_alloc(MVMThreadContext *tc, MVMSpeshGraph *g, size_t bytes);
269
MVMOpInfo *get_phi(MVMThreadContext *tc, MVMSpeshGraph *g, MVMuint32 nrargs);