memory. All functions writing values into the data area return the offset
relative the begin of the code area (start of procedure).
- $Id: codegen-common.c 5088 2006-07-08 20:16:05Z twisti $
+ $Id: codegen-common.c 5703 2006-10-05 20:21:04Z edwin $
*/
#include "vm/jit/stacktrace.h"
#include "vm/jit/replace.h"
+#if defined(ENABLE_INTRP)
+#include "vm/jit/intrp/intrp.h"
+#endif
+
/* in this tree we store all method addresses *********************************/
cd->superstarts = NULL;
}
#endif
-
- cd->dsegtop = DMNEW(u1, DSEGINITSIZE);
- cd->dsegsize = DSEGINITSIZE;
- cd->dsegtop += cd->dsegsize;
- cd->dseglen = 0;
+
+ cd->dseg = NULL;
+ cd->dseglen = 0;
cd->jumpreferences = NULL;
patchref *pr;
s4 branchpos;
- branchpos = (u1 *) cd->mcodeptr - cd->mcodebase;
+ branchpos = cd->mcodeptr - cd->mcodebase;
pr = DNEW(patchref);
the basic block code generation is completed, we check the
range and maybe generate some nop's. */
- cd->lastmcodeptr = ((u1 *) cd->mcodeptr) + PATCHER_CALL_SIZE;
+ cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
#endif
}
}
-/* codegen_findmethod **********************************************************
+/* codegen_get_pv_from_pc ******************************************************
- Find the PV for the given PC by searching in the AVL tree of methods.
+ Find the PV for the given PC by searching in the AVL tree of
+ methods.
*******************************************************************************/
-u1 *codegen_findmethod(u1 *pc)
+u1 *codegen_get_pv_from_pc(u1 *pc)
{
methodtree_element mtepc;
methodtree_element *mte;
mte = avl_find(methodtree, &mtepc);
if (mte == NULL) {
-/* fprintf(stderr, "Cannot find Java function at %p\n", (void *) (ptrint) pc); */
+ /* No method was found. Let's dump a stacktrace. */
- return NULL;
+ log_println("We received a SIGSEGV and tried to handle it, but we were");
+ log_println("unable to find a Java method at:");
+ log_println("");
+#if SIZEOF_VOID_P == 8
+ log_println("PC=0x%016lx", pc);
+#else
+ log_println("PC=0x%08x", pc);
+#endif
+ log_println("");
+ log_println("Dumping the current stacktrace:");
+
+ stacktrace_dump_trace();
+
+ vm_abort("Exiting...");
}
return mte->startpc;
}
+/* codegen_get_pv_from_pc_nocheck **********************************************
+
+ Find the PV for the given PC by searching in the AVL tree of
+ methods. This method does not check the return value and is used
+ by the profiler.
+
+*******************************************************************************/
+
+u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
+{
+ methodtree_element mtepc;
+ methodtree_element *mte;
+
+ /* allocation of the search structure on the stack is much faster */
+
+ mtepc.startpc = pc;
+ mtepc.endpc = pc;
+
+ mte = avl_find(methodtree, &mtepc);
+
+ if (mte == NULL)
+ return NULL;
+ else
+ return mte->startpc;
+}
+
+
/* codegen_finish **************************************************************
Finishes the code generation. A new memory, large enough for both
/* calculate the code length */
- mcodelen = (s4) ((u1 *) cd->mcodeptr - cd->mcodebase);
+ mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
#if defined(ENABLE_THREADS)
extralen = sizeof(critical_section_node_t) * cd->threadcritcount;
/* allocate new memory */
code->mcodelength = mcodelen + cd->dseglen;
- code->mcode = CNEW(u1, alignedlen + extralen);
-
- /* copy data and code to their new location */
-
- MCOPY((void *) code->mcode, cd->dsegtop - cd->dseglen, u1, cd->dseglen);
- MCOPY((void *) (code->mcode + cd->dseglen), cd->mcodebase, u1, mcodelen);
+ code->mcode = CNEW(u1, alignedlen + extralen);
/* set the entrypoint of the method */
assert(code->entrypoint == NULL);
code->entrypoint = epoint = (code->mcode + cd->dseglen);
+ /* fill the data segment (code->entrypoint must already be set!) */
+
+ dseg_finish(jd);
+
+ /* copy code to the new location */
+
+ MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
+
#if defined(ENABLE_INTRP)
/* relocate native dynamic superinstruction code (if any) */
/* set the flags for the current JIT run */
+ if (opt_prof)
+ jd->flags |= JITDATA_FLAG_INSTRUMENT;
+
if (opt_verbosecall)
jd->flags |= JITDATA_FLAG_VERBOSECALL;
*******************************************************************************/
-s4 codegen_reg_of_var(registerdata *rd, u2 opcode, stackptr v, s4 tempregnum)
+inline s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
{
- varinfo *var;
#if 0
/* Do we have to generate a conditional move? Yes, then always
return tempregnum;
#endif
- switch (v->varkind) {
- case TEMPVAR:
- if (!(v->flags & INMEMORY))
- return(v->regoff);
- break;
-
- case STACKVAR:
- var = &(rd->interfaces[v->varnum][v->type]);
- v->regoff = var->regoff;
- if (!(var->flags & INMEMORY))
- return(var->regoff);
- break;
-
- case LOCALVAR:
- var = &(rd->locals[v->varnum][v->type]);
- v->regoff = var->regoff;
- if (!(var->flags & INMEMORY)) {
+ if (!(v->flags & INMEMORY)) {
#if defined(__ARM__) && defined(__ARMEL__)
- if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(var->regoff) == REG_SPLIT))
- return(PACK_REGS(GET_LOW_REG(var->regoff), GET_HIGH_REG(tempregnum)));
+ if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->vv.regoff) == REG_SPLIT))
+ return PACK_REGS(GET_LOW_REG(v->vv.regoff),
+ GET_HIGH_REG(tempregnum));
#endif
#if defined(__ARM__) && defined(__ARMEB__)
- if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(var->regoff) == REG_SPLIT))
- return(PACK_REGS(GET_LOW_REG(tempregnum), GET_HIGH_REG(var->regoff)));
+ if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->vv.regoff) == REG_SPLIT))
+ return PACK_REGS(GET_LOW_REG(tempregnum),
+ GET_HIGH_REG(v->vv.regoff));
#endif
- return(var->regoff);
- }
- break;
-
- case ARGVAR:
- if (!(v->flags & INMEMORY)) {
-#if defined(__ARM__) && defined(__ARMEL__)
- if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->regoff) == REG_SPLIT))
- return(PACK_REGS(GET_LOW_REG(v->regoff), GET_HIGH_REG(tempregnum)));
-#endif
-#if defined(__ARM__) && defined(__ARMEB__)
- if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->regoff) == REG_SPLIT))
- return(PACK_REGS(GET_LOW_REG(tempregnum), GET_HIGH_REG(v->regoff)));
-#endif
- return(v->regoff);
- }
- break;
+ return v->vv.regoff;
}
#if defined(ENABLE_STATISTICS)
count_spills_read++;
#endif
- v->flags |= INMEMORY;
-
return tempregnum;
}
+/* codegen_reg_of_dst **********************************************************
+
+ This function determines a register, to which the result of an
+ operation should go, when it is ultimatively intended to store the
+ result in iptr->dst.var. If dst.var is assigned to an actual
+ register, this register will be returned. Otherwise (when it is
+ spilled) this function returns tempregnum. If not already done,
+ regoff and flags are set in the stack location.
+
+ On ARM we have to check if a long/double variable is splitted
+ across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
+ register of dst.var for LOW_REG and the tempregnum for HIGH_REG in such
+ cases. (michi 2005/07/24)
+
+*******************************************************************************/
+
+s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
+{
+ return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
+}
+
#if defined(ENABLE_THREADS)
void codegen_threadcritrestart(codegendata *cd, int offset)