/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); |