/* Default maximum size of bytecode we'll inline. */ #define MVM_SPESH_DEFAULT_MAX_INLINE_SIZE 192 /* The maximum number of locals an inliner can reach, and maximum number of * inlines we can reach, before we stop inlining; this is to prevent us * reaching sizes where the analysis becomes hugely costly. */ #define MVM_SPESH_INLINE_MAX_LOCALS 512 #define MVM_SPESH_INLINE_MAX_INLINES 128 /* Inline table entry. The data is primarily used in deopt. */ struct MVMSpeshInline { /* Start and end position in the bytecode where we're inside of this * inline. */ MVMuint32 start; MVMuint32 end; /* The static frame that was inlined. */ MVMStaticFrame *sf; /* The register holding the inlined code ref. */ MVMuint16 code_ref_reg; /* Start position of the locals and lexicals, so we can extract them * to the new frame. */ MVMuint16 locals_start; MVMuint16 lexicals_start; /* The number of locals in the inline. */ MVMuint16 num_locals; /* Result register and result type at the point of the call that has been * inlined. */ MVMuint16 res_reg; MVMReturnType res_type; /* Deopt index used to find return address of the caller if we uninline. */ MVMuint32 return_deopt_idx; /* If the inline became unreachable after being made, we'll mark it as * such, so we won't try and fix it up later. */ MVMuint8 unreachable; /* Flag that we set if the inline has an instruction that may deopt. */ MVMuint8 may_cause_deopt; /* The size of the bytecode that was inlined. Note that we only hold * this for *immediate* inlines, and zero it for nested ones, so we do * not count them multiple times. */ MVMuint16 bytecode_size; /* The callsite that we were invoked with. */ MVMCallsite *cs; /* Bit field of named args used to put in place during deopt, since we * typically don't update the array in specialized code. */ MVMuint64 deopt_named_used_bit_field; /* Indices of first and last spesh resume initialization records that * are set up by the inlined call, or both set to -1 if none. */ MVMint16 first_spesh_resume_init; MVMint16 last_spesh_resume_init; }; MVMSpeshGraph * MVM_spesh_inline_try_get_graph(MVMThreadContext *tc, MVMSpeshGraph *inliner, MVMStaticFrame *target_sf, MVMSpeshCandidate *cand, MVMSpeshIns *runbytecode_ins, char **no_inline_reason, MVMuint32 *effective_size, MVMOpInfo const **no_inline_info); MVMSpeshGraph * MVM_spesh_inline_try_get_graph_from_unspecialized(MVMThreadContext *tc, MVMSpeshGraph *inliner, MVMStaticFrame *target_sf, MVMSpeshIns *invoke_ins, MVMCallsite *cs, MVMSpeshOperand *args, MVMSpeshStatsType *type_tuple, char **no_inline_reason, MVMOpInfo const **no_inline_info); void MVM_spesh_inline(MVMThreadContext *tc, MVMSpeshGraph *inliner, MVMCallsite *cs, MVMSpeshOperand *args, MVMSpeshBB *runbytecode_bb, MVMSpeshIns *runbytecode_ins, MVMSpeshGraph *inlinee, MVMStaticFrame *inlinee_sf, MVMSpeshOperand code_ref_reg, MVMSpeshIns *resume_init, MVMuint16 bytecode_size); MVMuint32 MVM_spesh_inline_get_max_size(MVMThreadContext *tc, MVMStaticFrame *sf);