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 8215 2007-07-18 20:31:21Z michi $
-
*/
# include "codegen.h"
#endif
+#include "md-abi.h"
+
#include "mm/memory.h"
#include "toolbox/avl.h"
#include "toolbox/logging.h"
#include "native/jni.h"
+#include "native/llni.h"
+#include "native/localref.h"
#include "native/native.h"
+#include "native/include/java_lang_Class.h"
+
#include "threads/threads-common.h"
+#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/stringlocal.h"
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
#include "vm/jit/md.h"
+#include "vm/jit/methodheader.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
#if defined(ENABLE_SSA)
# include "vm/jit/optimizing/ssa.h"
#endif
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trace.h"
#if defined(ENABLE_INTRP)
#include "vm/jit/intrp/intrp.h"
bptr->branchrefs = NULL;
}
+ /* We need to clear all the patcher references from the codeinfo
+ since they all will be regenerated */
+
+ patcher_list_reset(code);
+
#if defined(ENABLE_REPLACEMENT)
code->rplpoints = NULL;
code->rplpointcount = 0;
if (opt_shownops)
PATCHER_NOPS;
- /* If the codegen provides a PACHER_LONGBRANCHES_NOPS macro, honour it. */
-
-#if defined(PATCHER_LONGBRANCHES_NOPS)
- if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
- PATCHER_LONGBRANCHES_NOPS;
- }
-#endif
-
#if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__MIPS__) \
|| defined(__SPARC_64__) || defined(__X86_64__))
}
+/* codegen_generate_stub_builtin ***********************************************
+
+ Wrapper for codegen_emit_stub_builtin.
+
+*******************************************************************************/
+
+void codegen_generate_stub_builtin(methodinfo *m, builtintable_entry *bte)
+{
+#if defined(__ARM__) || defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__SPARC64__) || defined(__X86_64__)
+ jitdata *jd;
+ codeinfo *code;
+ s4 dumpsize;
+
+ /* mark dump memory */
+
+ dumpsize = dump_size();
+
+ jd = DNEW(jitdata);
+
+ jd->m = m;
+ jd->cd = DNEW(codegendata);
+ jd->rd = NULL;
+ jd->flags = 0;
+
+ /* Allocate codeinfo memory from the heap as we need to keep them. */
+
+ jd->code = code_codeinfo_new(m); /* XXX check allocation */
+
+ /* get required compiler data */
+
+ code = jd->code;
+
+ /* setup code generation stuff */
+
+ codegen_setup(jd);
+
+ /* generate the code */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp) {
+# endif
+ assert(bte->fp != NULL);
+ codegen_emit_stub_native(jd, bte->md, bte->fp);
+# if defined(ENABLE_INTRP)
+ }
+# endif
+#endif
+
+ /* reallocate the memory and finish the code generation */
+
+ codegen_finish(jd);
+
+ /* set the stub entry point in the builtin table */
+
+ bte->stub = code->entrypoint;
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_stub_native += code->mcodelength;
+#endif
+
+#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
+ /* disassemble native stub */
+
+ if (opt_DisassembleStubs) {
+ codegen_disassemble_stub(m,
+ (u1 *) (ptrint) code->entrypoint,
+ (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
+
+ /* show data segment */
+
+ if (opt_showddatasegment)
+ dseg_display(jd);
+ }
+#endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
+
+ /* release memory */
+
+ dump_release(dumpsize);
+#endif /* architecture list */
+}
+
+
/* codegen_generate_stub_native ************************************************
Wrapper for codegen_emit_stub_native.
size_stub_native += code->mcodelength;
#endif
-#if !defined(NDEBUG)
+#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
/* disassemble native stub */
- if (opt_shownativestub) {
-#if defined(ENABLE_DEBUG_FILTER)
+ if (opt_DisassembleStubs) {
+# if defined(ENABLE_DEBUG_FILTER)
if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
-#endif
+# endif
{
-#if defined(ENABLE_DISASSEMBLER)
- codegen_disassemble_nativestub(m,
- (u1 *) (ptrint) code->entrypoint,
- (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
-#endif
+ codegen_disassemble_stub(m,
+ (u1 *) (ptrint) code->entrypoint,
+ (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
/* show data segment */
dseg_display(jd);
}
}
-#endif /* !defined(NDEBUG) */
+#endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
/* release memory */
/* codegen_disassemble_nativestub **********************************************
- Disassembles the generated native stub.
+ Disassembles the generated builtin or native stub.
*******************************************************************************/
#if defined(ENABLE_DISASSEMBLER)
-void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
+void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
{
- printf("Native stub: ");
- utf_fprint_printable_ascii_classname(stdout, m->class->name);
+ printf("Stub code: ");
+ if (m->class != NULL)
+ utf_fprint_printable_ascii_classname(stdout, m->class->name);
+ else
+ printf("NULL");
printf(".");
utf_fprint_printable_ascii(stdout, m->name);
utf_fprint_printable_ascii(stdout, m->descriptor);
- printf("\n\nLength: %d\n\n", (s4) (end - start));
+ printf("\nLength: %d\n\n", (s4) (end - start));
DISASSEMBLE(start, end);
}
The layout of the native stub stackframe should look like this:
- +---------------------------+ <- SP (of parent Java function)
+ +---------------------------+ <- java SP (of parent Java function)
| return address |
- +---------------------------+
+ +---------------------------+ <- data SP
| |
| stackframe info structure |
| |
| |
+---------------------------+
| |
+ | saved registers (if any) |
+ | |
+ +---------------------------+
+ | |
| arguments (if any) |
| |
- +---------------------------+ <- SP (native stub)
+ +---------------------------+ <- current SP (native stub)
*******************************************************************************/
-void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
+java_handle_t *codegen_start_native_call(u1 *currentsp, u1 *pv)
{
stackframeinfo *sfi;
localref_table *lrt;
+ codeinfo *code;
+ methodinfo *m;
+ int32_t framesize;
+
+ uint8_t *datasp;
+ uint8_t *javasp;
+ uint8_t *javara;
+ uint64_t *arg_regs;
+ uint64_t *arg_stack;
STATISTICS(count_calls_java_to_native++);
+ /* get information from method header */
+
+ code = *((codeinfo **) (pv + CodeinfoPointer));
+ framesize = *((int32_t *) (pv + FrameSize));
+ assert(code);
+ assert(framesize > sizeof(stackframeinfo) + sizeof(localref_table));
+
+ /* get the methodinfo */
+
+ m = code->m;
+ assert(m);
+
+ /* calculate needed values */
+
+#if defined(__ALPHA__) || defined(__ARM__)
+ datasp = currentsp + framesize - SIZEOF_VOID_P;
+ javasp = currentsp + framesize;
+ javara = *((uint8_t **) datasp);
+ arg_regs = (uint64_t *) currentsp;
+ arg_stack = (uint64_t *) javasp;
+#elif defined(__MIPS__) || defined(__S390__)
+ /* MIPS and S390 always uses 8 bytes to store the RA */
+ datasp = currentsp + framesize - 8;
+ javasp = currentsp + framesize;
+ javara = *((uint8_t **) datasp);
+#elif defined(__I386__) || defined (__M68K__) || defined (__X86_64__)
+ datasp = currentsp + framesize;
+ javasp = currentsp + framesize + SIZEOF_VOID_P;
+ javara = *((uint8_t **) datasp);
+ arg_regs = (uint64_t *) currentsp;
+ arg_stack = (uint64_t *) javasp;
+#elif defined(__POWERPC__) || defined(__POWERPC64__)
+ datasp = currentsp + framesize;
+ javasp = currentsp + framesize;
+ javara = *((uint8_t **) (datasp + LA_LR_OFFSET));
+ arg_regs = (uint64_t *) (currentsp + LA_SIZE + 4 * SIZEOF_VOID_P);
+ arg_stack = (uint64_t *) javasp;
+#else
+ /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
+ /* XXX maybe we need to pass the RA as argument there */
+ vm_abort("codegen_start_native_call: unsupported architecture");
+#endif
+
+#if !defined(NDEBUG)
+# if defined(__POWERPC__) || defined (__X86_64__)
+ /* print the call-trace if necesarry */
+
+ if (opt_TraceJavaCalls)
+ trace_java_call_enter(m, arg_regs, arg_stack);
+# endif
+#endif
+
/* get data structures from stack */
sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
lrt = (localref_table *) (datasp - sizeof(stackframeinfo) -
sizeof(localref_table));
- /* add a stackframeinfo to the chain */
-
- stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
-
#if defined(ENABLE_JNI)
/* add current JNI local references table to this thread */
- lrt->capacity = LOCALREFTABLE_CAPACITY;
- lrt->used = 0;
- lrt->localframes = 1;
- lrt->prev = LOCALREFTABLE;
-
- /* clear the references array (memset is faster the a for-loop) */
+ localref_table_add(lrt);
+#endif
- MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
+#if defined(ENABLE_HANDLES)
+ /* place all references into the local reference table */
- LOCALREFTABLE = lrt;
+ localref_fill(m, arg_regs, arg_stack);
#endif
+
+ /* add a stackframeinfo to the chain */
+
+ stacktrace_create_native_stackframeinfo(sfi, pv, javasp, javara);
+
+ /* return a wrapped classinfo for static native methods */
+
+ if (m->flags & ACC_STATIC)
+ return LLNI_classinfo_wrap(m->class);
+ else
+ return NULL;
}
*******************************************************************************/
-java_objectheader *codegen_finish_native_call(u1 *datasp)
+java_object_t *codegen_finish_native_call(u1 *currentsp, u1 *pv)
{
- stackframeinfo *sfi;
- stackframeinfo **psfi;
-#if defined(ENABLE_JNI)
- localref_table *lrt;
- localref_table *plrt;
- s4 localframes;
+ stackframeinfo *sfi;
+ java_handle_t *e;
+ java_object_t *o;
+ codeinfo *code;
+ methodinfo *m;
+ int32_t framesize;
+
+ uint8_t *datasp;
+ uint64_t *ret_regs;
+
+ /* get information from method header */
+
+ code = *((codeinfo **) (pv + CodeinfoPointer));
+ framesize = *((int32_t *) (pv + FrameSize));
+ assert(code);
+
+ /* get the methodinfo */
+
+ m = code->m;
+ assert(m);
+
+ /* calculate needed values */
+
+#if defined(__ALPHA__) || defined(__ARM__)
+ datasp = currentsp + framesize - SIZEOF_VOID_P;
+ ret_regs = (uint64_t *) currentsp;
+#elif defined(__MIPS__) || defined(__S390__)
+ /* MIPS and S390 always uses 8 bytes to store the RA */
+ datasp = currentsp + framesize - 8;
+#elif defined(__I386__)
+ datasp = currentsp + framesize;
+ ret_regs = (uint64_t *) (currentsp + 2 * SIZEOF_VOID_P);
+#elif defined (__M68K__) || defined (__X86_64__)
+ datasp = currentsp + framesize;
+ ret_regs = (uint64_t *) currentsp;
+#elif defined(__POWERPC__) || defined(__POWERPC64__)
+ datasp = currentsp + framesize;
+ ret_regs = (uint64_t *) (currentsp + LA_SIZE + 2 * SIZEOF_VOID_P);
+#else
+ vm_abort("codegen_finish_native_call: unsupported architecture");
#endif
- java_objectheader *e;
-
- /* get data structures from stack */
-
- sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
-
- /* remove current stackframeinfo from chain */
- psfi = &STACKFRAMEINFO;
- *psfi = sfi->prev;
-
-#if defined(ENABLE_JNI)
- /* release JNI local references tables for this thread */
-
- lrt = LOCALREFTABLE;
+#if !defined(NDEBUG)
+# if defined(__POWERPC__) || defined (__X86_64__)
+ /* print the call-trace if necesarry */
- /* release all current local frames */
+ if (opt_TraceJavaCalls)
+ trace_java_call_exit(m, ret_regs);
+# endif
+#endif
- for (localframes = lrt->localframes; localframes >= 1; localframes--) {
- /* get previous frame */
+ /* get data structures from stack */
- plrt = lrt->prev;
+ sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
- /* Clear all reference entries (only for tables allocated on
- the Java heap). */
+ /* remove current stackframeinfo from chain */
- if (localframes > 1)
- MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
+ stacktrace_remove_stackframeinfo(sfi);
- lrt->prev = NULL;
+ /* XXX unfill lrt here!!! */
- /* set new local references table */
+ /* get and unwrap the exception */
+ /* ATTENTION: do the this _after_ the stackframeinfo was
+ removed but _before_ the localref_table gets removed! */
- lrt = plrt;
- }
+ e = exceptions_get_and_clear_exception();
+ o = LLNI_UNWRAP(e);
- /* now store the previous local frames in the thread structure */
+#if defined(ENABLE_JNI)
+ /* release JNI local references table for this thread */
- LOCALREFTABLE = lrt;
+ localref_frame_pop_all();
+ localref_table_remove();
#endif
- /* get the exception and return it */
-
- e = exceptions_get_and_clear_exception();
-
- return e;
+ return o;
}