75 #define INLINE_KNAPSACK
79 #if defined(INLINE_KNAPSACK)
81 #define INLINE_COUNTDOWN_INIT 1000
82 #define INLINE_COST_OFFSET -16
83 #define INLINE_COST_BUDGET 100
93 #if defined(INLINE_DEPTH_FIRST)
95 #define INLINE_MAX_DEPTH 3
96 #define INLINE_MAX_BLOCK_EXPANSION 10
104 #if defined(INLINE_BREADTH_FIRST)
107 #define INLINE_MAX_ICMD_EXPANSION 5
115 #define INLINE_VERBOSE
116 #define DOLOG(code) do{ if (opt_TraceInlining >= 2) { code; } }while(0)
117 #define DOLOG_SHORT(code) do{ if (opt_TraceInlining >= 1) { code; } }while(0)
122 #if defined(ENABLE_VERIFIER) && !defined(NDEBUG)
277 #define INLINE_STATISTICS
280 #if defined(INLINE_STATISTICS)
288 printf(
"inlining statistics:\n");
376 #if defined(ENABLE_JIT)
377 # if defined(ENABLE_INTRP)
400 assert(parent && child);
450 assert(child->
parent == parent);
452 if (child->
prev == child) {
468 #if defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST)
478 #if defined(INLINE_DIVIDE_COST_BY_FREQ)
483 #if defined(INLINE_KNAPSACK)
486 #if defined(INLINE_BREADTH_FIRST)
495 for (link = &(ctx->
candidates); ; link = &((*link)->next)) {
505 #if defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST)
519 #if !defined(NDEBUG) && (defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST))
522 printf(
"%10g (%5d / %5d) depth %2d ",
529 #if !defined(NDEBUG) && (defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST))
551 newcount = jd->
vartop * 2;
569 v = &(origjd->
var[origidx]);
618 for (t=0; t<5; ++t) {
623 v = &(callee->
jd->
var[varindex]);
634 varmap[varindex] = avail;
642 assert(n_javaindex >= 0);
665 #define INLINE_RETURN_REFERENCE(callee) \
666 ( (basicblock *) (ptrint) (0x333 + (callee)->depth) )
682 static void inline_add_blocknr_reference(
inline_node *iln,
s4 *nrp)
728 if (bm->
o_block == o_block && bm->
iln == targetiln)
747 for (ref = *refs; ref != NULL; ref = ref->
next) {
796 assert(indepth >= 0);
805 n_bptr->
next = n_bptr + 1;
822 for (i=0; i<indepth; ++
i)
828 while (outer != NULL) {
839 n_bptr->
invars[depth +
i] = newvaridx;
840 outer->
varmap[varidx] = newvaridx;
880 inline_add_blocknr_reference(iln, &(jl[i]));
980 for (i=0; i<outdepth; ++
i)
989 while (outer != NULL) {
1045 assert(retidx >= 0);
1062 n_iptr->
opc = opcode;
1088 syncvar = instancevar;
1099 n_ins->
sx.
s23.s2.args[0] = syncvar;
1116 assert(iln && callee && o_iptr);
1118 calleem = callee->
m;
1151 n_ins->
sx.
s23.s3.inlineinfo = insinfo;
1171 varindex = varmap[o_iptr->
sx.
s23.s2.args[
i]];
1183 if (!callee->
isstatic && i == 0 && calleem->
name != utf8::init) {
1247 n_ins->
sx.
s23.s3.inlineinfo = insinfo;
1258 assert(iln && callee && o_iptr);
1276 n_ins->
sx.
s23.s3.inlineinfo->javalocals_end = jl;
1283 #define TRANSLATE_VAROP(vo) \
1284 n_iptr->vo.varindex = inline_translate_variable(jd, origjd, varmap, n_iptr->vo.varindex)
1331 n_iptr->
sx.
s23.s2.args[
i] =
1333 o_iptr->
sx.
s23.s2.args[i]);
1344 n_iptr->
sx.
s23.s2.args[
i] =
1346 o_iptr->
sx.
s23.s2.args[i]);
1348 for (scope = iln; scope != NULL; scope = scope->
parent) {
1350 n_iptr->
sx.
s23.s2.args[i++] =
1359 bte = n_iptr->
sx.
s23.s3.bte;
1381 i = n_iptr->
sx.
s23.s3.tablehigh - n_iptr->
sx.
s23.s2.tablelow + 1 + 1 ;
1396 i = n_iptr->
sx.
s23.s2.lookupcount;
1410 switch (n_iptr->
opc) {
1414 inline_add_blocknr_reference(iln, &(n_iptr->
sx.
s23.s2.retaddrnr));
1455 for (i=0; i<iln->
depth; ++
i)
1461 printf(
"%s(passthrough: %d+%d)\n",
1477 for (; o_bptr; o_bptr = o_bptr->
next) {
1483 if (o_bptr->
icount == 0 && o_bptr->
next == NULL) {
1490 printf(
"%s* skipping old L%03d (flags=%d, type=%d, oid=%d) of ",
1494 method_println(iln->
m);
1511 printf(
"%s* rewriting old L%03d (flags=%d, type=%d, oid=%d) of ",
1515 method_println(iln->
m);
1554 while (--len >= 0) {
1561 if (nextcall && o_iptr == nextcall->
callerins) {
1632 nextcall = nextcall->
next;
1638 switch (o_iptr->
opc) {
1640 if (iln->
depth == 0)
1649 if (iln->
depth == 0)
1671 else if ((retidx < resultjd->localcount && iln->
blockafter)
1743 #if !defined(NDEBUG)
1770 assert(prevextable);
1776 child = child->
next;
1781 for (; et != NULL; et = et->
down) {
1790 (*prevextable)->down = n_extable;
1792 *prevextable = n_extable;
1807 (*prevextable)->down = n_extable;
1809 *prevextable = n_extable;
1816 for (scope = iln; scope->
parent != NULL; scope = scope->
parent) {
1819 assert(activehandlers);
1821 while (*activehandlers) {
1829 (*activehandlers)->handler,
1831 n_extable->
catchtype = (*activehandlers)->catchtype;
1834 (*prevextable)->down = n_extable;
1836 *prevextable = n_extable;
1860 child = child->
next;
1943 child = child->
next;
1985 n_ins->
sx.
s23.s2.args[0] = syncvar;
1989 n_ins->
sx.
s23.s3.bte = bte;
2020 #if defined(INLINE_VERIFY_RESULT)
2021 static int debug_verify_inlined_code = 1;
2023 #if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
2024 static int debug_counter = 0;
2027 DOLOG( dump_inline_tree(iln, 0); );
2066 #if defined(INLINE_VERIFY_RESULT)
2067 if (debug_verify_inlined_code) {
2107 #if !defined(NDEBUG)
2121 prevext->
down = NULL;
2145 #if defined(INLINE_VERIFY_RESULT)
2146 if (debug_verify_inlined_code) {
2147 debug_verify_inlined_code = 0;
2148 DOLOG(
printf(
"VERIFYING INLINED RESULT...\n"); fflush(stdout); );
2151 DOLOG(
printf(
"XXX INLINED RESULT DID NOT PASS VERIFIER XXX\n") );
2157 debug_verify_inlined_code = 1;
2165 #if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
2169 if (debug_counter < opt_InlineCount)
2180 #if !defined(NDEBUG)
2184 printf(
"==== %d.INLINE ==================================================================\n",
2186 printf(
"\ninline tree:\n");
2187 dump_inline_tree(iln, 0);
2190 printf(
"-------- DONE -----------------------------------------------------------\n");
2196 #if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
2229 #if defined(INLINE_MAX_DEPTH)
2230 if (caller->
depth >= INLINE_MAX_DEPTH)
2279 #if defined(INLINE_MAX_ICMD_EXPANSION) || defined(INLINE_MAX_BLOCK_EXPANSION)
2282 #if defined(INLINE_DEPTH_FIRST)
2290 #
if defined(INLINE_MAX_BLOCK_EXPANSION)
2294 #
if defined(INLINE_MAX_ICMD_EXPANSION)
2393 for (active = caller; active; active = active->
parent) {
2394 if (callee == active->
m) {
2572 DOLOG(
printf(
"PASSING THROUGH LOCAL VARIABLE %d\n", idx); );
2675 #if defined(INLINE_CANCEL_ON_THRESHOLD)
2687 #if defined(INLINE_DEPTH_FIRST)
2691 #if defined(INLINE_BREADTH_FIRST)
2809 handlers[nhandlers++] = ex;
2812 handlers[nhandlers] = NULL;
2822 for (; --len >= 0; ++iptr) {
2824 switch (iptr->
opc) {
2831 callee = iptr->
sx.
s23.s3.fmiref->p.method;
2837 site.
pc = blockendpc - len - 1;
2842 #if defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST)
2888 child = child->
next;
2910 #if defined(INLINE_KNAPSACK)
2914 #if defined(INLINE_COST_BUDGET)
2916 # define BUDGETMEMBER cost
2918 #if defined(INLINE_WEIGHT_BUDGET)
2919 double budget = INLINE_WEIGHT_BUDGET;
2920 # define BUDGETMEMBER weight
2930 if (cand->BUDGETMEMBER <= budget) {
2936 #if !defined(INLINE_ADD_NEGATIVE_TO_BUDGET)
2937 if (cand->BUDGETMEMBER > 0)
2939 budget -= cand->BUDGETMEMBER;
2950 #if defined(INLINE_DEPTH_FIRST)
2958 #if defined(INLINE_BREADTH_FIRST)
2984 #if defined(INLINE_STATISTICS)
2998 child = child->
next;
3005 #if defined(INLINE_STATISTICS)
3017 #define POSTPROCESS_SRC(varindex) live[varindex]--
3018 #define POSTPROCESS_DST(varindex) live[varindex]++
3020 #define POSTPROCESS_SRCOP(s) POSTPROCESS_SRC(iptr->s.varindex)
3021 #define POSTPROCESS_DSTOP(d) POSTPROCESS_DST(iptr->d.varindex)
3023 #define MARKSAVED(varindex) jd->var[varindex].flags |= SAVEDVAR
3025 #define MARK_ALL_SAVED \
3027 for (i=0; i<jd->vartop; ++i) \
3070 iend = iptr + bptr->
icount;
3072 for (; iptr < iend; ++iptr) {
3130 bte = iptr->
sx.
s23.s3.bte;
3132 goto post_process_call;
3145 #if !defined(NDEBUG)
3147 assert(live[i] == 0);
3202 DOLOG(
printf(
"==== INLINE ==================================================================\n");
3205 #if defined(INLINE_STATISTICS)
3218 DOLOG(
printf(
"==== INLINE TRANSFORM ========================================================\n"); );
3223 #if defined(INLINE_STATISTICS)
3228 DOLOG(
printf(
"-------- DONE -----------------------------------------------------------\n");
static void close_body_block(inline_node *iln, basicblock *n_bptr, basicblock *o_bptr, s4 *varmap, s4 retcount, s4 retidx)
static void inline_cumulate_counters(inline_node *caller, const inline_node *cn)
basicblock * handler_monitorexit
inline_block_map * blockmap
union inline_target_ref::@10 ref
#define BASICBLOCK_INIT(bptr, m)
static bool inline_make_inlining_plan(inline_node *iln)
int epilog_instructioncount
static bool inline_afterwards_heuristics(const inline_node *caller, const inline_node *callee)
exception_entry ** handlers
exception_entry * exceptiontable
#define INLINE_COST_OFFSET
static void inline_block_translation(inline_node *iln, basicblock *o_bptr, basicblock *n_bptr)
int cumul_exceptiontablelength
bool inline_inline(jitdata *jd)
#define POSTPROCESS_DST(varindex)
static bool inline_jit_compile(inline_node *iln)
static exception_entry * inline_exception_tables(inline_node *iln, exception_entry *n_extable, exception_entry **prevextable)
static void inline_candidates_println(inline_context *ctx)
static inline_candidate * inline_pick_best_candidate(inline_context *ctx)
insinfo_inline * inlineinfo
static void inline_insert_inline_node(inline_node *parent, inline_node *child)
static void inline_write_exception_handlers(inline_node *master, inline_node *iln)
static basicblock * inline_map_block(inline_node *iln, basicblock *o_block, inline_node *targetiln)
bool typecheck(jitdata *jd)
typedef void(JNICALL *jvmtiEventSingleStep)(jvmtiEnv *jvmti_env
static void close_prolog_block(inline_node *iln, basicblock *n_bptr, inline_node *nextcall)
int extra_exceptiontablelength
static s4 inline_new_temp_variable(jitdata *jd, Type type)
static bool inline_jit_compile_intern(jitdata *jd)
static void code_unflag_leafmethod(codeinfo *code)
static void inline_post_process(jitdata *jd)
static void inline_set_callee_properties(const inline_node *caller, inline_node *cn, const inline_site *site)
static inline_node * inline_create_callee_node(const inline_node *caller, methodinfo *callee)
static bool inline_post_parse_heuristics(const inline_node *caller, const inline_node *callee)
void inline_print_stats()
#define MZERO(ptr, type, num)
static s4 inline_new_variable_clone(jitdata *jd, jitdata *origjd, s4 origidx)
void(* functionptr)(void)
void link(basicblock *v, basicblock *w)
#define IS_2_WORD_TYPE(a)
int prolog_instructioncount
#define JITDATA_FLAG_SHOWINTERMEDIATE
static bool inline_is_monomorphic(const methodinfo *callee, const instruction *call, inline_site *site)
static inline_node * inline_analyse_callee(inline_node *caller, methodinfo *callee, inline_site *site)
jlong jlong jlong jlong jint depth
void show_basicblock(jitdata *jd, basicblock *bptr, int stage)
#define INLINE_RETURN_REFERENCE(callee)
#define MARKSAVED(varindex)
inline_candidate * candidates
builtintable_entry * builtintable_get_internal(functionptr fp)
basicblock * inlined_basicblocks_cursor
int cumul_basicblockcount_root
static bool inline_analyse_code(inline_node *iln)
static void emit_inlining_epilog(inline_node *iln, inline_node *callee, instruction *o_iptr)
#define POSTPROCESS_DSTOP(d)
#define DOLOG_SHORT(code)
static void inline_generate_sync_builtin(inline_node *iln, inline_node *callee, instruction *o_iptr, s4 instancevar, functionptr func)
instruction * inlined_iinstr
jitdata * jit_jitdata_new(methodinfo *m)
#define LOCK_monitor_enter
#define INLINE_COUNTDOWN_INIT
void method_println(methodinfo *m)
bool stack_analyse(jitdata *jd)
int inline_stat_inlined_nodes
static basicblock * create_epilog_block(inline_node *caller, inline_node *callee, s4 *varmap)
This file contains the statistics framework.
int inline_stat_roots_transformed
static void * reallocate(void *src, size_t len1, size_t len2)
Stupid realloc implementation for dump memory.
void reg_setup(jitdata *jd)
#define POSTPROCESS_SRC(varindex)
int extra_instructioncount
Type
Types used internally by JITTED code.
static bool inline_can_inline(const inline_node *caller, const methodinfo *callee, const instruction *call, inline_site *site)
instruction * inlined_iinstr_cursor
classref_or_classinfo catchtype
static basicblock * create_body_block(inline_node *iln, basicblock *o_bptr, s4 *varmap)
static void inline_candidate_println(inline_candidate *cand)
int cumul_instructioncount
int inline_stat_max_depth
#define INLINE_COST_BUDGET
#define VERIFIER_EXTRA_LOCALS
int32_t * javalocals_start
int n_selfpassthroughcount
union instruction::@12 sx
static void inline_rewrite_method(inline_node *iln)
#define LOCK_monitor_exit
static void inline_gather_statistics(inline_node *iln)
void stack_javalocals_store(instruction *iptr, s4 *javalocals)
icmdtable_entry_t icmd_table[256]
#define INSTRUCTION_GET_METHODDESC(iptr, md)
static void inline_remove_inline_node(inline_node *parent, inline_node *child)
exception_entry ** o_handlers
static inline_node * inline_create_root_node(jitdata *jd)
static void inline_add_candidate(inline_context *ctx, inline_node *caller, methodinfo *callee, inline_site *site)
static bool inline_transform(inline_node *iln, jitdata *jd)
void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage)
static void inline_interface_variables(inline_node *iln)
static s4 inline_translate_variable(jitdata *jd, jitdata *origjd, s4 *varmap, s4 index)
static bool inline_pre_parse_heuristics(const inline_node *caller, const methodinfo *callee, inline_site *site)
interface_info * interface_map
static basicblock * create_block(inline_node *container, inline_node *iln, inline_node *inner, int indepth)
int cumul_basicblockcount
#define TRANSLATE_VAROP(vo)
static void * allocate(size_t size)
static void inline_cumulate_counters_recursive(inline_node *iln)
void exceptions_clear_exception(void)
#define INSTRUCTION_IS_UNRESOLVED(iptr)
struct instruction::@12::@13 s23
void unlock()
Unlocks the given mutex object and checks for errors.
void jit_check_basicblock_numbers(jitdata *jd)
#define POSTPROCESS_SRCOP(s)
#define JAVALOCAL_FROM_RETADDR(nr)
#define JITDATA_FLAG_SHOWDISASSEMBLE
basicblock * inlined_basicblocks
void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
static void inline_add_block_reference(inline_node *iln, basicblock **blockp)
static s4 emit_inlining_prolog(inline_node *iln, inline_node *callee, instruction *o_iptr, s4 *varmap)
#define MCOPY(dest, src, type, num)
static instruction * inline_instruction(inline_node *iln, ICMD opcode, instruction *o_iptr)
instruction * inline_start_instruction
static s4 * translate_javalocals(inline_node *iln, s4 *javalocals)
static void inline_gather_statistics_recursive(inline_node *iln)
instruction * instructions
static bool inline_process_candidate(inline_candidate *cand)
static s4 inline_new_variable(jitdata *jd, Type type, s4 flags)
void log_message_class(const char *msg, classinfo *c)
void lock()
Locks the given mutex object and checks for errors.
static void inline_locals(inline_node *iln)
static void inline_clone_instruction(inline_node *iln, jitdata *jd, jitdata *origjd, s4 *varmap, instruction *o_iptr, instruction *n_iptr)
#define VERIFIER_EXTRA_VARS
static s4 * create_variable_map(inline_node *callee)
static void close_block(inline_node *iln, inline_node *inner, basicblock *n_bptr, s4 outdepth)
static void inline_resolve_block_refs(inline_target_ref **refs, basicblock *o_bptr, basicblock *n_bptr, bool returnref)