-/* src/vm/optimizing/escape.c
+/* src/vm/optimizing/e&scape.c
Copyright (C) 2008
CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
#include "vmcore/classcache.h"
#include "vm/jit/optimizing/escape.h"
+#include <stdarg.h>
+
+#if defined(ENABLE_ESCAPE_REASON)
+#define ENABLE_REASON
+#endif
+
+#if defined(ENABLE_REASON)
+#define I2(why, tov, es) escape_analysis_record_reason(e, why, iptr, tov, es);
+#else
+#define I2(why, tov, es)
+#endif
+#define I(why, to, from) I2(why, instruction_ ## to (iptr), escape_analysis_get_state(e, instruction_ ## from (iptr)))
+#define E2(why, var) I2(why, var, ESCAPE_GLOBAL)
+#define E(why, which) E2(why, instruction_ ## which (iptr))
+
+typedef enum {
+ RED = 31,
+ GREEN,
+ YELLOW,
+ BLUE,
+ MAGENTA,
+ CYAN,
+ WHITE,
+ COLOR_END
+} color_t;
+
+#define ENABLE_COLOR
+
+static void color_start(color_t color) {
+#if defined(ENABLE_COLOR)
+ if (RED <= color && color < COLOR_END) {
+ printf("\033[%dm", color);
+ }
+#endif
+}
+
+static void color_end() {
+#if defined(ENABLE_COLOR)
+ printf("\033[m");
+ fflush(stdout);
+#endif
+}
+
+static void color_printf(color_t color, const char *fmt, ...) {
+ va_list ap;
+ color_start(color);
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+ color_end();
+}
+
+
/*** escape_state *************************************************************/
const char *escape_state_to_string(escape_state_t escape_state) {
/*** var_extra ***************************************************************/
+#if defined(ENABLE_REASON)
+typedef struct reason {
+ const char *why;
+ instruction *iptr;
+ struct reason *next;
+} reason_t;
+#endif
+
typedef struct var_extra {
instruction *allocation;
escape_state_t escape_state;
unsigned contains_arg:1;
unsigned contains_only_args:1;
/*signed adr_arg_num:30;*/
+#if defined(ENABLE_REASON)
+ reason_t *reasons;
+#endif
} var_extra_t;
static void var_extra_init(var_extra_t *ve) {
ve->contains_arg = false;
ve->contains_only_args = false;
/*ve->adr_arg_num = -1;*/
+#if defined(ENABLE_REASON)
+ ve->reasons = NULL;
+#endif
}
static inline var_extra_t *var_extra_get_no_alloc(const escape_analysis_t *e, s4 var) {
e->adr_args_count = 0;
- e->verbose = (
- strcmp(e->jd->m->clazz->name->text, "gnu/java/util/regex/RESyntax") == 0
- && strcmp(e->jd->m->name->text, "<clinit>") == 0
- );
e->verbose = 1;
+ e->verbose = strcmp(jd->m->name->text, "<init>") == 0;
+ e->verbose = getenv("EV") != NULL;
}
+#if defined(ENABLE_REASON)
+static void escape_analysis_record_reason(escape_analysis_t *e, const char *why, instruction *iptr, s4 var, escape_state_t es) {
+ var_extra_t *ve;
+ reason_t *re;
+ if (es == ESCAPE_GLOBAL || es == ESCAPE_METHOD_RETURN) {
+ var = var_extra_get_representant(e, var);
+ ve = var_extra_get(e, var);
+ re = NEW(reason_t);
+ re->why = why;
+ re->iptr= iptr;
+ re->next = ve->reasons;
+ ve->reasons = re;
+ if (e->verbose) {
+ printf("%d escapes because %s\n", var, why);
+ }
+ }
+}
+#endif
+
static void escape_analysis_set_allocation(escape_analysis_t *e, s4 var, instruction *iptr) {
var_extra_get(e, var)->allocation = iptr;
}
}
static void escape_analysis_set_contains_argument(escape_analysis_t *e, s4 var) {
+ var = var_extra_get_representant(e, var);
var_extra_get(e, var)->contains_arg = true;
}
static bool escape_analysis_get_contains_argument(escape_analysis_t *e, s4 var) {
+ var = var_extra_get_representant(e, var);
return var_extra_get(e, var)->contains_arg;
}
static void escape_analysis_set_contains_only_arguments(escape_analysis_t *e, s4 var) {
+ var = var_extra_get_representant(e, var);
var_extra_get(e, var)->contains_only_args = true;
}
static bool escape_analysis_get_contains_only_arguments(escape_analysis_t *e, s4 var) {
+ var = var_extra_get_representant(e, var);
return var_extra_get(e, var)->contains_only_args;
}
dependency_list_item_get_dependency(it),
escape_state
);
+ {
+ instruction *iptr = NULL;
+ I2("propagated by dependency", dependency_list_item_get_dependency(it), escape_state);
+ }
}
}
}
return;
}
+ if (e->verbose) printf("Merging (%d,%d)\n", var1, var2);
+
ve1 = var_extra_get(e, var1);
ve2 = var_extra_get(e, var2);
dependency_list_item_get_dependency(itd),
ESCAPE_GLOBAL
);
+ {
+ instruction *iptr = NULL;
+ E2("has become arg", dependency_list_item_get_dependency(itd));
+ }
}
}
ve1->adr_arg_num = -1;
}
*/
+#if defined(ENABLE_REASON)
+ if (ve1->reasons) {
+ reason_t *re = ve1->reasons;
+ while (re->next != NULL) {
+ re = re->next;
+ }
+ re->next = ve2->reasons;
+ } else {
+ ve1->reasons = ve2->reasons;
+ }
+#endif
}
static void escape_analysis_add_dependency(escape_analysis_t *e, instruction *store) {
dependency_list_add(dl, store);
if (e->verbose) {
- printf("dependency_list_add\n");
+ printf("dependency_list_add: %d.dependency_list.add( { ", obj);
+ show_icmd(e->jd, store, 0, 3);
+ printf(" } )\n");
}
}
instruction **iarg;
methodinfo *mi;
escape_state_t es;
+ const char *why;
if (e->verbose) {
- printf("processing %s@%d\n", icmd_table[iptr->opc].name, iptr->line);
+ color_start(CYAN);
+ printf("%d: ", iptr->line);
+ show_icmd(e->jd, iptr, 0, 3);
+ color_end();
+ printf("\n");
}
switch (instruction_get_opcode(iptr)) {
if (c == NULL) {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E("unresolved class", dst)
} else if (c->finalizer != NULL) {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E("finalizer", dst)
} else {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
}
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
instruction_list_add(e->allocations, iptr);
-
+ E("untracked array", dst)
break;
case ICMD_PUTSTATIC:
if (instruction_field_type(iptr) == TYPE_ADR) {
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+ E("putstatic", s1)
}
break;
/* If s1 is currently not an argument, but can contain one later because
of a phi function, the merge function takes care to make all
dependencies escape globally. */
+ E("putfield into argument", s2)
} else {
+ I("putfield inherit", s2, s1);
escape_analysis_ensure_state(e, instruction_s2(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
escape_analysis_add_dependency(e, iptr);
}
case ICMD_AASTORE:
if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
+ if (e->verbose) printf("Contains argument.\n");
escape_analysis_ensure_state(e, instruction_s3(iptr), ESCAPE_GLOBAL);
+ E("aastore into argument", s3)
} else {
+ if (e->verbose) printf("Contains no argument.\n");
+ I("aastore", s3, s1)
escape_analysis_ensure_state(e, instruction_s3(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
escape_analysis_add_dependency(e, iptr);
}
case ICMD_GETSTATIC:
if (instruction_field_type(iptr) == TYPE_ADR) {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E("loaded from static var", dst)
escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
}
break;
x.bar = y;
=> y escapes globally. */
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E("loaded from arg", dst)
} else {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
}
if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
/* If store into argument, escapes globally. See ICMD_GETFIELD. */
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E("aaload from argument", dst)
} else {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
}
case ICMD_IFNULL:
case ICMD_IFNONNULL:
+ escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
+ break;
+
case ICMD_CHECKNULL:
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
+ escape_analysis_merge(e, instruction_s1(iptr), instruction_dst(iptr));
break;
case ICMD_CHECKCAST:
count = instruction_arg_count(iptr);
mi = instruction_local_methodinfo(iptr);
paramescape = NULL;
+ why = "???";
if (mi != NULL) {
/* If the method could be resolved, it already is. */
paramescape = mi->paramescape;
+ if (e->verbose) {
+ if (paramescape) {
+ printf("Paramescape for callee available.\n");
+ }
+ }
+
+ if (paramescape) why = "Available param escape";
+
if (paramescape == NULL) {
if (e->verbose) {
- printf("BC escape analyzing callee %s/%s.\n", mi->clazz->name->text, mi->name->text);
+ printf("BC escape analyzing callee.\n");
}
+ why = "BC param escape";
bc_escape_analysis_perform(mi);
paramescape = mi->paramescape;
}
if (e->verbose) {
printf("Unresolved callee.\n");
}
+ why = "Unresolved callee";
}
if (iptr->opc == ICMD_INVOKEVIRTUAL || iptr->opc == ICMD_INVOKEINTERFACE) {
- if (mi != NULL && !method_profile_is_monomorphic(mi)) {
+ if (mi != NULL && !escape_is_monomorphic(e->jd->m, mi)) {
+ if (e->verbose) {
+ printf("Not monomorphic.\n");
+ }
+ why = "Polymorphic";
paramescape = NULL;
}
}
if (instruction_return_type(iptr) == TYPE_ADR) {
if (paramescape == NULL) {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E(why, dst);
} else {
es = escape_state_from_u1(paramescape[-1]);
+ I2(why, instruction_dst(iptr), es)
escape_analysis_ensure_state(e, instruction_dst(iptr), es);
}
escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
}
-
+
for (i = 0; i < count; ++i) {
if (instruction_arg_type(iptr, i) == TYPE_ADR) {
instruction_arg(iptr, i),
ESCAPE_GLOBAL
);
- } else if (escape_state_from_u1(*paramescape) < ESCAPE_METHOD) {
+ E2(why, instruction_arg(iptr, i));
+ } else if (escape_state_from_u1(*paramescape) <= ESCAPE_METHOD) {
es = escape_state_from_u1(*paramescape);
if (es < ESCAPE_METHOD) {
es = ESCAPE_METHOD;
}
+ I2(why, instruction_arg(iptr, i), es);
escape_analysis_ensure_state(e, instruction_arg(iptr, i), es);
if (*paramescape & 0x80) {
If the return value escapes, the ES of the parameter needs
to be adjusted. */
escape_analysis_merge(e, instruction_arg(iptr, i), instruction_dst(iptr));
+ I2("return alias", instruction_arg(iptr, i), instruction_dst(iptr));
}
+ } else {
+ escape_analysis_ensure_state(e, instruction_arg(iptr, i), ESCAPE_GLOBAL);
+ E2(why, instruction_arg(iptr, i));
}
if (paramescape != NULL) {
case ICMD_ATHROW:
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+ E("throw", s1)
break;
case ICMD_ARETURN:
ESCAPE_METHOD for now, and check later, if a different value than an
argument is possibly returned. */
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD_RETURN);
+ E("return", s1)
instruction_list_add(e->returns, iptr);
break;
FOR_EACH_BASICBLOCK(e->jd, bptr) {
+ if (e->verbose) {
+ color_printf(CYAN, "=== BB %d ===\n", bptr->nr);
+ }
+
for (iptr = bptr->phis; iptr != bptr->phis + bptr->phicount; ++iptr) {
escape_analysis_process_instruction(e, iptr);
}
instruction_list_item_t *iti;
instruction *iptr;
+ if (e->verbose) printf("Post processing returns:\n");
+
FOR_EACH_INSTRUCTION_LIST(e->getfields, iti) {
iptr = iti->instr;
if (! escape_analysis_get_contains_only_arguments(e, instruction_s1(iptr))) {
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+ E("return of not argument", s1)
}
}
}
instruction *iptr;
dependency_list_t *dl;
+ if (e->verbose) printf("Post processing getfields:\n");
+
FOR_EACH_INSTRUCTION_LIST(e->getfields, iti) {
iptr = iti->instr;
dependency_list_item_get_dependency(itd),
escape_analysis_get_state(e, instruction_dst(iptr))
);
+ I2("post process getfield", dependency_list_item_get_dependency(itd), escape_analysis_get_state(e, instruction_dst(iptr)));
}
}
}
/* TODO if argument does not escape, mark. */
if (escape_analysis_get_state(e, instruction_arg(iptr, 0)) != ESCAPE_GLOBAL) {
- printf("Monitor on thread local object!\n");
- }
- }
-}
-
-static void display_allocation(escape_analysis_t *e, const char *prefix, const instruction *iptr, escape_state_t es) {
- const char *cl = "WTF";
- classinfo *c;
-
- if (instruction_get_opcode(iptr) == ICMD_NEW) {
- c = escape_analysis_classinfo_in_var(e, instruction_arg(iptr, 0));
- if (c) {
- cl = c->name->text;
+ if (e->verbose) {
+ printf("Monitor on thread local object!\n");
+ }
}
}
-
-
- printf(
- " %s %s %s: %s %s @%d %s\n",
- prefix,
- e->jd->m->clazz->name->text,
- e->jd->m->name->text,
- icmd_table[iptr->opc].name,
- cl,
- iptr->line,
- escape_state_to_string(es)
- );
}
static void escape_analysis_mark_allocations(escape_analysis_t *e) {
instruction_list_item_t *iti;
+ instruction *iptr;
escape_state_t es;
-/*
FOR_EACH_INSTRUCTION_LIST(e->allocations, iti) {
- es = escape_analysis_get_state(e, instruction_dst(iti->instr));
- if (es < ESCAPE_GLOBAL_THROUGH_METHOD) {
- display_allocation(e, "****", iti->instr, es);
+ iptr = iti->instr;
+ es = escape_analysis_get_state(e, instruction_dst(iptr));
+
+#if defined(ENABLE_REASON)
+ if (instruction_get_opcode(iptr) == ICMD_NEW) {
+ var_extra_t *ve;
+ iptr->sx.s23.s3.bte = builtintable_get_internal(BUILTIN_escape_reason_new);
+ ve = var_extra_get(e, var_extra_get_representant(e, instruction_dst(iptr)));
+ iptr->escape_reasons = ve->reasons;
+ if (es < ESCAPE_METHOD_RETURN) {
+ assert(!ve->reasons);
+ reason_t *r = NEW(reason_t);
+ r->why = "No escape\n";
+ r->iptr = NULL;
+ r->next = NULL;
+ iptr->escape_reasons = r;
+ } else {
+ assert(iptr->escape_reasons);
+ }
}
- if (es == ESCAPE_GLOBAL_THROUGH_METHOD) {
- display_allocation(e, "!!!!", iti->instr, es);
+#endif
+
+/*
+ if (instruction_get_opcode(iptr) == ICMD_NEW) {
+ es = escape_analysis_get_state(e, instruction_dst(iptr));
+ if (es < ESCAPE_METHOD_RETURN) {
+ iptr->sx.s23.s3.bte = builtintable_get_internal(BUILTIN_tlh_new);
+ e->jd->code->flags |= CODE_FLAG_TLH;
+ }
}
- }
*/
+ }
}
static void escape_analysis_process_arguments(escape_analysis_t *e) {
}
}
+#if defined(ENABLE_REASON)
+void print_escape_reasons() {
+ reason_t *re = THREADOBJECT->escape_reasons;
+
+ fprintf(stderr, "DYN_REASON");
+
+ for (; re; re = re->next) {
+ fprintf(stderr,":%s", re->why);
+ }
+
+ fprintf(stderr, "\n");
+}
+
+void set_escape_reasons(void *vp) {
+ THREADOBJECT->escape_reasons = vp;
+}
+#endif
+
static void escape_analysis_display(escape_analysis_t *e) {
instruction_list_item_t *iti;
var_extra_t *ve;
FOR_EACH_INSTRUCTION_LIST(e->allocations, iti) {
iptr = iti->instr;
- ve = var_extra_get(e, instruction_dst(iptr));
+ ve = var_extra_get(e, var_extra_get_representant(e, instruction_dst(iptr)));
+ show_icmd(e->jd, iptr-1, 0, 3);
+ printf("\n");
+ show_icmd(e->jd, iptr, 0, 3);
+ printf("\n");
printf(
- "%s@%d: %s\n",
+ "%s@%d: --%s-- %d\n\n",
icmd_table[iptr->opc].name,
iptr->line,
- escape_state_to_string(ve->escape_state)
+ escape_state_to_string(ve->escape_state),
+ ve->representant
);
+#if defined(ENABLE_REASON)
+ {
+ reason_t *re;
+ for (re = ve->reasons; re; re = re->next) {
+ printf("ESCAPE_REASON: %s\n", re->why);
+ }
+ }
+#endif
}
}
escape_analysis_init(e, jd);
if (e->verbose)
- printf("==== %s/%s ====\n", e->jd->m->clazz->name->text, e->jd->m->name->text);
+ color_printf(RED, "\n\n==== %s/%s ====\n\n", e->jd->m->clazz->name->text, e->jd->m->name->text);
escape_analysis_process_arguments(e);
escape_analysis_process_instructions(e);
escape_analysis_export_arguments(e);
if (e->verbose) escape_analysis_display(e);
+ if (e->verbose) {
+ int i, j, r;
+ for (i = 0; i < jd->vartop; ++i) {
+ r = var_extra_get_representant(e, i);
+ if (i == r) {
+ printf("EES of %d: ", i);
+ for (j = 0; j < jd->vartop; ++j) {
+ if (var_extra_get_representant(e, j) == r) {
+ printf("%d, ", j);
+ }
+ }
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+
escape_analysis_mark_allocations(e);
escape_analysis_mark_monitors(e);
/*** monomorphic *************************************************************/
-monomorphic_t monomorphic_get(methodinfo *caller, methodinfo *callee) {
- monomorphic_t res = { 0, 0 };
-}
+bool escape_is_monomorphic(methodinfo *caller, methodinfo *callee) {
+
+ /* Non-speculative case */
+
+ if (callee->flags & (ACC_STATIC | ACC_FINAL | ACC_PRIVATE)) {
+ return true;
+ }
+
+ if (
+ (callee->flags & (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED| ACC_ABSTRACT))
+ == (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED)
+ ) {
+
+ /* Mark that we have used the information about monomorphy. */
+
+ callee->flags |= ACC_METHOD_MONOMORPHY_USED;
+
+ /* We assume the callee is monomorphic. */
+
+ method_add_assumption_monomorphic(caller, callee);
+
+ return true;
+ }
-bool method_profile_is_monomorphic(methodinfo *m) {
-return 0;
+ return false;
}
/*** vars *******************************************************************/
-#define VARS_CATEGORY_SHIFT 29
-#define VARS_INDEX_MASK 0x1FFFFFFF
+#define VARS_CATEGORY_SHIFT 28
+#define VARS_INDEX_MASK 0x0FFFFFFF
#define VARS_CATEGORY_LOCAL 0
#define VARS_CATEGORY_STACK 1
}
#endif
-static inline void phis_copy_to(const phis_t *ps, instruction *dst) {
- MCOPY(
- dst,
- ps->items,
- instruction,
- ps->count
- );
+static inline unsigned phis_copy_to(const phis_t *ps, instruction *dst) {
+ instruction *it;
+ instruction *out = dst;
+
+ FOR_EACH_PHI_FUNCTION(ps, it) {
+ *(out++) = *it;
+ }
+
+ return (out - dst);
}
/*** state_array ************************************************************/
basicblock_chain_t chain;
basicblock *last = NULL;
basicblock *marker = NULL;
+ s4 vartop;
+ unsigned i;
if (jd->exceptiontablelength == 0) {
return;
basicblock_chain_init(&chain);
- /* We need to allocate new iovars */
+ /* Remember, where we started adding IO variables. */
- avail_vars = (jd->varcount - jd->vartop);
- add_vars = jd->exceptiontablelength;
-
- if (add_vars > avail_vars) {
- add_vars -= avail_vars;
- jd->var = DMREALLOC(jd->var, varinfo, jd->varcount, jd->varcount + add_vars);
- jd->varcount += add_vars;
- }
+ vartop = jd->vartop;
/* For each exception handler block, create one block with a prologue block */
FOR_EACH_BASICBLOCK(jd, bptr) {
if (bptr->type == BBTYPE_EXH) {
+ /*
+
+ +---- EXH (exh)-------+
+ | in0 in1 in2 exc |
+ | ..... |
+ +---------------------+
+
+ === TRANSFORMED TO ===>
+
+ +---- PROL (exh) -------+
+ | in0 in1 in2 |
+ | GETEXECEPTION => OU3 |
+ | GOTO REAL_EXH |
+ | in0 in1 in2 OU3 |
+ +-----------------------+
+
+ +---- REAL_EXH (std) -+
+ | in0 in1 in2 exc |
+ | ...... |
+ +---------------------+
+
+ */
+
bptr->type = BBTYPE_STD;
bptr->predecessorcount = 0; /* legacy */
iptr = DMNEW(instruction, 2);
MZERO(iptr, instruction, 2);
+
+ /* Create outvars */
+
+ exh->outdepth = bptr->indepth;
+
+ if (exh->outdepth > 0) {
+ exh->outvars = DMNEW(s4, exh->outdepth);
+ for (i = 0; i < exh->outdepth; ++i) {
+ exh->outvars[i] = vartop++;
+ }
+ }
+
+ /* Create invars */
+
+ exh->indepth = exh->outdepth - 1;
+ exh->invars = exh->outvars;
+#if 0
/* Create new outvar */
assert(jd->vartop < jd->varcount);
jd->vartop += 1;
jd->var[v].type = TYPE_ADR;
jd->var[v].flags = INOUT;
+#endif
exh->nr = jd->basicblockcount;
jd->basicblockcount += 1;
exh->type = BBTYPE_EXH;
exh->icount = 2;
exh->iinstr = iptr;
+/*
exh->outdepth = 1;
exh->outvars = DNEW(s4);
exh->outvars[0] = v;
+*/
exh->predecessorcount = -1; /* legacy */
exh->flags = BBFINISHED;
exh->method = jd->m;
/* Get exception */
iptr->opc = ICMD_GETEXCEPTION;
- iptr->dst.varindex = v;
+ iptr->dst.varindex = exh->outvars[exh->outdepth - 1];
iptr += 1;
/* Goto real exception handler */
}
}
+ /* We need to allocate the new iovars in the var array */
+
+ avail_vars = (jd->varcount - jd->vartop);
+ add_vars = (vartop - jd->vartop);
+
+ if (add_vars > avail_vars) {
+ add_vars -= avail_vars;
+ jd->var = DMREALLOC(jd->var, varinfo, jd->varcount, jd->varcount + add_vars);
+ jd->varcount += add_vars;
+ }
+
+ jd->vartop = vartop;
+
/* Put the chain of exception handlers between just before the last
basic block (end marker). */
for (ee = jd->exceptiontable; ee; ee = ee->down) {
assert(ee->handler->vp);
- ee->handler = ee->handler->vp;
+
+ bptr = ee->handler;
+ exh = (basicblock *)ee->handler->vp;
+
+ ee->handler = exh;
+
+ /* Set up IO variables in newly craeted exception handlers. */
+
+ for (i = 0; i < exh->outdepth; ++i) {
+ v = exh->outvars[i];
+
+ jd->var[v].flags = INOUT;
+ jd->var[v].type = jd->var[ bptr->invars[i] ].type;
+ }
}
}
basicblock *bptr;
basicblock_info_t *bbi;
instruction *itph;
+
+ /* XXX */
+ return;
+
FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
if (basicblock_reached(bptr)) {
bbi = bb_info(bptr);
basicblock_get_ex_predecessor_index(bb, pei, *itsucc),
ssa->locals
);
+
+ ssa_enter_merge(
+ bbi->stack,
+ succi->stack,
+ *itsucc,
+ basicblock_get_ex_predecessor_index(bb, pei, *itsucc),
+ ssa->stack
+ );
}
}
instruction *itph;
bool ret = false;
+ /* XXX */
+ return;
+
FOR_EACH_PHI_FUNCTION(t->phis, itph) {
phi_calculate_redundancy(itph);
state_array_allocate_items(bbi->stack->state_array);
}
+#if 0
/* Exception handlers have a clean stack. */
+ /* Not true with inlining. */
+
if (bb->type == BBTYPE_EXH) {
state_array_assert_no_items(bbi->stack->state_array);
state_array_allocate_items(bbi->stack->state_array);
}
+#endif
/* Some in/out vars get marked as INOUT in simplereg,
and are not marked at this point.
FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
bbi = bb_info(bptr);
if (bbi != NULL) {
- bptr->phicount =
- bbi->locals->phis->count +
- bbi->stack->phis->count;
-
- bptr->phis = DMNEW(instruction, bptr->phicount);
+ bptr->phis = DMNEW(instruction, bbi->locals->phis->count + bbi->stack->phis->count);
dst = bptr->phis;
- phis_copy_to(bbi->locals->phis, dst);
+ dst += phis_copy_to(bbi->locals->phis, dst);
- dst += bbi->locals->phis->count;
+ dst += phis_copy_to(bbi->stack->phis, dst);
- phis_copy_to(bbi->stack->phis, dst);
+ bptr->phicount = dst - bptr->phis;
}
}
}
}
instruction_set_uses(iptr, ssa->s_buf, uses, uses_count);
}
+ bptr->phicount = 0;
}
unfix_exception_handlers(ssa->jd);
ssa->jd->localcount = ssa->original.localcount;
}
+#include "vmcore/rt-timing.h"
+
void yssa(jitdata *jd) {
basicblock *it;
basicblock_info_t *iti;
ssa_info *ssa;
+ struct timespec bs, es, be, ee;
+
+ RT_TIMING_GET_TIME(bs);
+
#ifdef SSA_VERBOSE
bool verb = true;
if (verb) {
/*ssa_enter_create_phi_graph(ssa);*/
- /*escape_analysis_perform(ssa->jd);*/
+ RT_TIMING_GET_TIME(be);
+ escape_analysis_perform(ssa->jd);
+ RT_TIMING_GET_TIME(ee);
/*
ssa_leave_create_phi_moves(ssa);
}
#endif
+ RT_TIMING_GET_TIME(es);
+
+ RT_TIMING_TIME_DIFF(bs, es, RT_TIMING_1);
+ RT_TIMING_TIME_DIFF(be, ee, RT_TIMING_2);
}
void eliminate_subbasicblocks(jitdata *jd) {