From c3e1b5af8f348c833d937f69fbd5327da05f8427 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 12 Jun 2008 18:59:07 +0200 Subject: [PATCH] Move trap handlers to functions Remove goto's, switch trap-handlers to functions --- src/arch/avr32_jem.h | 5 +- src/interp/engine/interp_jem.c | 479 ++++++++++++++++++++++------------------- src/os/linux/avr32/init.c | 4 +- 3 files changed, 267 insertions(+), 221 deletions(-) diff --git a/src/arch/avr32_jem.h b/src/arch/avr32_jem.h index 3a0fcc2..18aed35 100644 --- a/src/arch/avr32_jem.h +++ b/src/arch/avr32_jem.h @@ -37,7 +37,8 @@ #define DESTORY_JEM_TRAPS enum { - JEM_TRAP_HANDLER_SYSEX = 2, + JEM_TRAP_HANDLER_FINISH = 1, + JEM_TRAP_HANDLER_SYSEX, JEM_TRAP_HANDLER_UNIMPL, }; @@ -49,7 +50,7 @@ struct jem_state { uint32_t jpc; }; -typedef int handler_fn(struct frame *Frame, struct jem_state *jem); +typedef int handler_fn(struct jem_state *jem); extern handler_fn *trap_handler_f[256]; //extern handler_fn *exception_handler_f[5]; diff --git a/src/interp/engine/interp_jem.c b/src/interp/engine/interp_jem.c index 298dc98..c4af645 100644 --- a/src/interp/engine/interp_jem.c +++ b/src/interp/engine/interp_jem.c @@ -43,37 +43,259 @@ unsigned long jos[8]; +/* These static variables come from the time when there was only one function in + * this file. So, we are pretty sure they must be shared. An attempt to pack + * them all in struct and pass a pointer to it around ended up in a way too ugly + * and suboptimal code. */ + +static CodePntr pc; +static MethodBlock *mb; +static uintptr_t *lvars_jem; +static uintptr_t *ostack; +static ConstantPool *cp; +static Object *this; +static MethodBlock *new_mb; +static uintptr_t *arg1; +static Frame *frame; +static uintptr_t *lvars; + #define min(x, y) ({ typeof(x) _x = (x); typeof(y) _y = (y); _x > _y ? _y : _x; }) +#define JEM_THROW_EXCEPTION(excep_name, message) \ +{ \ + frame->last_pc = pc; \ + signalException(excep_name, message); \ + jem_throwException(jem); \ +} + +#define JEM_NULL_POINTER_CHECK(ref) \ + if(!ref) JEM_THROW_EXCEPTION("java/lang/NullPointerException", NULL); + /********************************************* * JEM Trap Handlers ** * *******************************************/ -extern int trap_debug(struct frame *Frame, struct jem_state *jem); +extern int trap_debug(struct jem_state *jem); -static int do_javaExceptions(struct frame *Frame, struct jem_state *jem) +static int methodReturn(struct jem_state *jem) { - trap_debug(Frame, jem); + ExecEnv *ee = getExecEnv(); + /* Set interpreter state to previous frame */ + + if (frame->prev->mb == NULL) { + /* The previous frame is a dummy frame - this indicates + top of this Java invocation. */ + return 1; + } + + if (frame->lvars_jem != NULL) + sysFree(frame->lvars_jem - frame->mb->max_locals); + + frame = frame->prev; + + if (mb->access_flags & ACC_SYNCHRONIZED) { + Object *sync_ob = mb->access_flags & ACC_STATIC ? (Object*)mb->class : this; + objectUnlock(sync_ob); + } + + mb = frame->mb; + ostack = lvars; + lvars = frame->lvars; + lvars_jem = frame->lvars_jem - 1; + this = (Object*)(*lvars_jem); + jem->jpc = frame->last_pc; + cp = &(CLASS_CB(mb->class)->constant_pool); + + /* Pop frame */ + ee->last_frame = frame; + + return 0; +} + +static int invokeMethod(struct jem_state *jem) +{ + ExecEnv *ee = getExecEnv(); + uintptr_t *p = (new_mb->args_count > 8) ? arg1 : ostack; + Frame *new_frame = (Frame *)(p + new_mb->max_locals); + Object *sync_ob = NULL; + + jam_printf("[invokeMethod] with args count %d \n", new_mb->args_count); + jam_printf("[invokeMethod] new frame start %x\n", new_frame); + + frame->last_pc = pc; + ostack = (uintptr_t *)(new_frame + 1); + + if ((char*)(ostack + new_mb->max_stack) > ee->stack_end) { + if(ee->overflow++) { + /* Overflow when we're already throwing stack overflow. + Stack extension should be enough to throw exception, + so something's seriously gone wrong - abort the VM! */ + jam_printf("Fatal stack overflow! Aborting VM.\n"); + exitVM(1); + } + ee->stack_end += STACK_RED_ZONE_SIZE; + JEM_THROW_EXCEPTION("java/lang/StackOverflowError", NULL); + } + + //TODO + new_frame->mb = new_mb; + new_frame->lvars = arg1; + //TODO: it seemed lvars is in java stack,but jos[8] should be part of java stack + // lvars_jem requires that the highest pointer should refer to the first local variables LV0 + // Here still not touch the java stack,allocate lvars_jem from native heap + + new_frame->lvars_jem = sysMalloc(new_mb->max_locals * sizeof(uintptr_t)); + new_frame->lvars_jem = new_frame->lvars_jem + new_mb->max_locals; + jam_printf("[invokeMethod] new_frame -> lvars_jem %x\n", new_frame->lvars_jem); + + int i = 0; + do{ + uintptr_t *p1, *p2; + if (new_mb->args_count > 8){ + jam_printf("[invokeMethod] TODO : new_frame->lvars_jem \n"); + sysFree(new_frame->lvars_jem - new_mb->max_locals); + exitVM(1); + } else { + p1 = new_frame->lvars_jem - 1 - i; + p2 = arg1 + i; + *p1 = *p2; + i++; + } + } while (i < new_mb->args_count); + +#if 1 + new_frame->ostack = ostack; + new_frame->prev = frame; + + ee->last_frame = new_frame; + + if(new_mb->access_flags & ACC_SYNCHRONIZED) { + sync_ob = new_mb->access_flags & ACC_STATIC ? (Object*)new_mb->class : (Object*)*arg1; + objectLock(sync_ob); + } + + if(new_mb->access_flags & ACC_NATIVE) { + ostack = (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*)) + new_mb->native_invoker)(new_mb->class, new_mb, arg1); + + if(sync_ob) + objectUnlock(sync_ob); + + ee->last_frame = frame; + + if(exceptionOccured0(ee)){ + jam_printf("[invokeMethod] exceptio occured, goto throwException\n"); + return jem_throwException(jem); + //exitVM(1); + } + + jam_printf("[invokeMethod] finish native method invoke, return to loop\n"); + return 0; + } else { + frame = new_frame; + mb = new_mb; + lvars_jem = new_frame->lvars_jem - 1; + this = (Object*)(*lvars_jem); + jem->jpc = (unsigned long)mb->code & ~3; + cp = &(CLASS_CB(mb->class)->constant_pool); + + jam_printf("[invokeMethod] invoke virtual method: frame %x mb %x " + "lvars %x jpc %x cp %x \n", frame, mb, lvars_jem, jem->jpc, cp); + } + jam_printf("[invokeMethod] finish virtual method invoke, return to loop\n"); + + return 0; + //exitVM(1); +#endif +} + +static int invokespacial(struct jem_state *jem) +{ + int idx, cache; + Operand operand; + ExecEnv *ee = getExecEnv(); + + uintptr_t byte1 = (jem->jecr >> 8) & 0xff; + uintptr_t byte2 = jem->jecr & 0xff; + idx = (byte1 << 8) | byte2; + + jam_printf("[OPC_INVOKESPECIAL] constant pool index %d \n", idx); + + new_mb = resolveMethod(mb->class, idx); + + if (exceptionOccured0(ee)) + return jem_throwException(jem); + + /* Check if invoking a super method... */ + if ((CLASS_CB(mb->class)->access_flags & ACC_SUPER) && + ((new_mb->access_flags & ACC_PRIVATE) == 0) && (new_mb->name[0] != '<')) { + + operand.i = new_mb->method_table_index; +#if 0 /* FIXME: verify this whole "pc" chemistry is indeed unneeded */ + OPCODE_REWRITE(OPC_INVOKESUPER_QUICK, cache, operand); +#endif + } else { + operand.pntr = new_mb; +#if 0 /* FIXME: verify this whole "pc" chemistry is indeed unneeded */ + OPCODE_REWRITE(OPC_INVOKENONVIRTUAL_QUICK, cache, operand); +#endif + } + + return 0; +} + +static int invokesuper_quick(struct jem_state *jem) +{ + jam_printf("[OPC_INVOKESUPER_QUICK] method table indx %d\n", DOUBLE_INDEX(pc)); + new_mb = CLASS_CB(CLASS_CB(mb->class)->super)->method_table[DOUBLE_INDEX(pc)]; + jam_printf("[OPC_INVOKESUPER_QUICK] method args count %d \n", new_mb->args_count); + // set up jem operand stack + // TODO: the most latest 8 operands should reside in josp, while ostack + // should either the latest operand stack pointer or just the pointer to + // the 9th operand + arg1 = (new_mb->args_count > 8) ? (ostack - (new_mb->args_count - 8)) : + ((uintptr_t*)jos + (8 - new_mb->args_count)); + JEM_NULL_POINTER_CHECK(*arg1); + jam_printf("[OP_INVOKESUPER_QUICK] arg1 %x \n", *arg1); + return invokeMethod(jem); +} + +static int invokenonvirtual_quick(struct jem_state *jem) +{ + jam_printf("[OPC_INVOKENONVIRTUAL_QUICK]\n"); + new_mb = RESOLVED_METHOD(pc); + jam_printf("[OPC_INVOKENONVIRTUAL_QUICK] new methodblock %x with %d args\n", + new_mb, new_mb->args_count); + arg1 = (new_mb->args_count > 8) ? (ostack - (new_mb->args_count - 8)) : + ((uintptr_t*)jos + (8 - new_mb->args_count)); + jam_printf("[OP_INVOKENONVIRTUAL_QUICK] arg1 %x \n", *arg1); + JEM_NULL_POINTER_CHECK(*arg1); + return invokeMethod(jem); +} + +static int do_javaExceptions(struct jem_state *jem) +{ + trap_debug(jem); return JEM_TRAP_HANDLER_SYSEX; } -static int do_stackOverflow(struct frame *Frame, struct jem_state *jem) +static int do_stackOverflow(struct jem_state *jem) { - return trap_debug(Frame, jem); + return trap_debug(jem); } -static int do_stackUnderflow(struct frame *Frame, struct jem_state *jem) +static int do_stackUnderflow(struct jem_state *jem) { - return trap_debug(Frame, jem); + return trap_debug(jem); } -static int do_stackOverflow1(struct frame *Frame, struct jem_state *jem) +static int do_stackOverflow1(struct jem_state *jem) { - return trap_debug(Frame, jem); + return trap_debug(jem); } -static int do_stackUnderflow1(struct frame *Frame, struct jem_state *jem) +static int do_stackUnderflow1(struct jem_state *jem) { - return trap_debug(Frame, jem); + return trap_debug(jem); } static handler_fn *exception_handler_f[] = { @@ -186,23 +408,22 @@ int do_otherInstrps(uint32_t jecr, uint32_t trap_pc, uint32_t josp, uint32_t jpc jam_printf("do_otherInsptrps\n"); trap_debug(jecr,trap_pc,josp,jpc,pCurframe); - - return 0; } #endif -int do_jamInstrps(struct frame *Frame, struct jem_state *jem) +int do_jamInstrps(struct jem_state *jem) { jam_printf("do_jamInsptrps\n"); - trap_debug(Frame, jem); + trap_debug(jem); return JEM_TRAP_HANDLER_UNIMPL; } /******************************/ -uintptr_t *executeJava(void) { - +uintptr_t *executeJava(void) +{ +#if 0 /** * Using jamVm's direct threaded interpreting table to perform effective work */ @@ -267,27 +488,27 @@ uintptr_t *executeJava(void) { &&unused} DEF_HANDLER_TABLE(0, ENTRY); - +#endif /** * load trap entries to JEM trap table set when initializing JamVM */ int i; - static const void **handlers[] = {handlers_0_ENTRY}; +// static const void **handlers[] = {handlers_0_ENTRY}; - CodePntr pc; ExecEnv *ee = getExecEnv(); - Frame *frame = ee->last_frame; - MethodBlock *mb = frame->mb; - uintptr_t *lvars = frame->lvars; - uintptr_t *lvars_jem = frame->lvars_jem-1; - uintptr_t *ostack = frame->ostack; - ConstantPool *cp = &(CLASS_CB(mb->class)->constant_pool); - - Object *this = (Object*)lvars[0]; - MethodBlock *new_mb; + + /* Initialize interpreter's static environment */ + frame = ee->last_frame; + mb = frame->mb; + lvars_jem = frame->lvars_jem - 1; + ostack = frame->ostack; + cp = &(CLASS_CB(mb->class)->constant_pool); + lvars = frame->lvars; + this = (Object*)lvars[0]; + /* End enterpreter's static environment */ + Class *new_class; - uintptr_t *arg1; //fetch the original pc before prepare direct mb //TODO: @@ -298,6 +519,12 @@ uintptr_t *executeJava(void) { uint32_t jep; int done; + /* This is temporary. As we implement more handlers, we'll think of a better + * way to link them. */ + trap_handler_f[OPC_INVOKESPECIAL] = invokespacial; + trap_handler_f[OPC_INVOKESUPER_QUICK] = invokesuper_quick; + trap_handler_f[OPC_INVOKENONVIRTUAL_QUICK] = invokenonvirtual_quick; + jem.josp = 0; #if 0 @@ -376,15 +603,12 @@ jem_loop: jep = jem.trap_pc & 0xfff; if (jep < 0x280) - done = exception_handler_f[jep >> 7](frame, &jem); + done = exception_handler_f[jep >> 7](&jem); else - done = trap_handler_f[opcode](frame, &jem); + done = trap_handler_f[opcode](&jem); + } while (done != JEM_TRAP_HANDLER_FINISH); - /*handler trap using JamVM's optimized jump table*/ - if (done == JEM_TRAP_HANDLER_UNIMPL) { - goto *handlers_0_ENTRY[opcode]; - } - } while (!done); + return ostack; rewrite_lock: // DISPATCH_FIRST; @@ -426,7 +650,7 @@ unused: JEM_TRAP_MULTI_LEVEL_ENTRIES(0); #endif -#if 1 +#if 0 #define MULTI_LEVEL_OPCODES(level) \ DEF_OPC(OPC_ICONST_M1, level, \ PUSH_##level(-1, 1); \ @@ -1642,35 +1866,6 @@ unused: });) DEF_OPC_RW(OPC_INVOKESPECIAL, ({ -#ifdef JEM - int idx, cache; - Operand operand; - - uintptr_t byte1 = (jem.jecr >> 8) & 0xff; - uintptr_t byte2 = jem.jecr & 0xff; - idx = (byte1 << 8) | byte2; - - jam_printf("[OPC_INVOKESPECIAL] constant pool index %d \n", idx); - - new_mb = resolveMethod(mb->class, idx); - - if (exceptionOccured0(ee)) - goto throwException; - - /* Check if invoking a super method... */ - if ((CLASS_CB(mb->class)->access_flags & ACC_SUPER) && - ((new_mb->access_flags & ACC_PRIVATE) == 0) && (new_mb->name[0] != '<')) { - - operand.i = new_mb->method_table_index; - OPCODE_REWRITE(OPC_INVOKESUPER_QUICK, cache, operand); - } else { - operand.pntr = new_mb; - OPCODE_REWRITE(OPC_INVOKENONVIRTUAL_QUICK, cache, operand); - } - - REDISPATCH - -#else int idx, cache; Operand operand; @@ -1694,7 +1889,6 @@ unused: } REDISPATCH -#endif });) DEF_OPC_RW(OPC_INVOKESTATIC, ({ @@ -1815,41 +2009,17 @@ unused: DEF_OPC_210(OPC_INVOKESUPER_QUICK, { -#ifdef JEM - jam_printf("[OPC_INVOKESUPER_QUICK] method table indx %d\n", DOUBLE_INDEX(pc)); - new_mb = CLASS_CB(CLASS_CB(mb->class)->super)->method_table[DOUBLE_INDEX(pc)]; - jam_printf("[OPC_INVOKESUPER_QUICK] method args count %d \n", new_mb->args_count); - // set up jem operand stack - // TODO: the most latest 8 operands should reside in josp, while ostack - // should either the latest operand stack pointer or just the pointer to - // the 9th operand - arg1 = (new_mb->args_count>8) ? (ostack - (new_mb->args_count - 8)):((uintptr_t*)jos + (8 - new_mb->args_count)); - NULL_POINTER_CHECK(*arg1); - jam_printf("[OP_INVOKESUPER_QUICK] arg1 %x \n", *arg1); - goto invokeMethod; -#else new_mb = CLASS_CB(CLASS_CB(mb->class)->super)->method_table[DOUBLE_INDEX(pc)]; arg1 = ostack - (new_mb->args_count); NULL_POINTER_CHECK(*arg1); goto invokeMethod; -#endif }) DEF_OPC_210(OPC_INVOKENONVIRTUAL_QUICK, { -#ifdef JEM - jam_printf("[OPC_INVOKENONVIRTUAL_QUICK]\n"); - new_mb = RESOLVED_METHOD(pc); - jam_printf("[OPC_INVOKENONVIRTUAL_QUICK] new methodblock %x with %d args \n ", new_mb, new_mb->args_count); - arg1 = (new_mb->args_count>8) ? (ostack - (new_mb->args_count - 8)):((uintptr_t*)jos + (8 - new_mb->args_count)); - jam_printf("[OP_INVOKENONVIRTUAL_QUICK] arg1 %x \n", *arg1); - NULL_POINTER_CHECK(*arg1); - goto invokeMethod; -#else new_mb = RESOLVED_METHOD(pc); arg1 = ostack - (new_mb->args_count); NULL_POINTER_CHECK(*arg1); goto invokeMethod; -#endif }) DEF_OPC_210(OPC_INVOKESTATIC_QUICK, { @@ -2002,101 +2172,6 @@ unused: invokeMethod: { #ifdef JEM - jam_printf("[invokeMethod] with args count %d \n", new_mb->args_count); - - uintptr_t *p = (new_mb->args_count > 8) ? arg1 : ostack; - Frame *new_frame = (Frame *)(p + new_mb->max_locals); - jam_printf("[invokeMethod] new frame start %x\n", new_frame); - Object *sync_ob = NULL; - - frame->last_pc = pc; - ostack = (uintptr_t *)(new_frame + 1); - - if((char*)(ostack + new_mb->max_stack) > ee->stack_end) { - if(ee->overflow++) { - /* Overflow when we're already throwing stack overflow. - Stack extension should be enough to throw exception, - so something's seriously gone wrong - abort the VM! */ - jam_printf("Fatal stack overflow! Aborting VM.\n"); - exitVM(1); - } - ee->stack_end += STACK_RED_ZONE_SIZE; - THROW_EXCEPTION("java/lang/StackOverflowError", NULL); - } - - - //TODO - new_frame->mb = new_mb; - new_frame->lvars = arg1; - //TODO: it seemed lvars is in java stack,but jos[8] should be part of java stack - // lvars_jem requires that the highest pointer should refer to the first local variables LV0 - // Here still not touch the java stack,allocate lvars_jem from native heap - - new_frame->lvars_jem = sysMalloc(new_mb->max_locals*sizeof(uintptr_t)); - new_frame->lvars_jem = new_frame->lvars_jem + new_mb->max_locals; - jam_printf("[invokeMethod] new_frame -> lvars_jem %x\n",new_frame->lvars_jem); - - - int i = 0; - do{ - uintptr_t *p1,*p2; - if(new_mb->args_count > 8){ - jam_printf("[invokeMethod] TODO : new_frame->lvars_jem \n"); - sysFree(new_frame->lvars_jem-new_mb->max_locals); - exitVM(1); - }else{ - p1 = new_frame->lvars_jem - 1 - i; - p2 = arg1 + i; - *p1 = *p2; - i++; - } - }while(i < new_mb->args_count); - - -#if 1 - new_frame->ostack = ostack; - new_frame->prev = frame; - - ee->last_frame = new_frame; - - if(new_mb->access_flags & ACC_SYNCHRONIZED) { - sync_ob = new_mb->access_flags & ACC_STATIC ? (Object*)new_mb->class : (Object*)*arg1; - objectLock(sync_ob); - } - - if(new_mb->access_flags & ACC_NATIVE) { - ostack = (*(uintptr_t *(*)(Class*, MethodBlock*, uintptr_t*)) - new_mb->native_invoker)(new_mb->class, new_mb, arg1); - - if(sync_ob) - objectUnlock(sync_ob); - - ee->last_frame = frame; - - if(exceptionOccured0(ee)){ - jam_printf("[invokeMethod] exceptio occured, goto throwException\n"); - goto throwException; - //exitVM(1); - } - - jam_printf("[invokeMethod] finish native method invoke, return to loop\n"); - goto jem_loop; - } else { - - frame = new_frame; - mb = new_mb; - lvars_jem = new_frame->lvars_jem - 1; - this = (Object*)(*lvars_jem); - jem.jpc = (unsigned long)mb->code & ~3; - cp = &(CLASS_CB(mb->class)->constant_pool); - - jam_printf("[invokeMethod] invoke virtual method : frame %x mb %x lvars %x jpc %x cp %x \n", frame, mb, lvars_jem, jem.jpc, cp); - } - jam_printf("[invokeMethod] finish virtual method invoke, return to loop\n"); - goto jem_loop; - //exitVM(1); -#endif - #else /* Create new frame first. This is also created for natives so that they appear correctly in the stack trace */ @@ -2159,36 +2234,6 @@ invokeMethod: methodReturn: #ifdef JEM - /* Set interpreter state to previous frame */ - - if(frame->prev->mb == NULL) { - /* The previous frame is a dummy frame - this indicates - top of this Java invocation. */ - return ostack; - } - - if(frame->lvars_jem != NULL) - sysFree(frame->lvars_jem-frame->mb->max_locals); - - frame = frame->prev; - - if(mb->access_flags & ACC_SYNCHRONIZED) { - Object *sync_ob = mb->access_flags & ACC_STATIC ? (Object*)mb->class : this; - objectUnlock(sync_ob); - } - - mb = frame->mb; - ostack = lvars; - lvars = frame->lvars; - lvars_jem = frame->lvars_jem - 1; - this = (Object*)(*lvars_jem); - jem.jpc = frame->last_pc; - cp = &(CLASS_CB(mb->class)->constant_pool); - - /* Pop frame */ - ee->last_frame = frame; - - goto jem_loop; #else /* Set interpreter state to previous frame */ diff --git a/src/os/linux/avr32/init.c b/src/os/linux/avr32/init.c index ba3aafc..47edf35 100644 --- a/src/os/linux/avr32/init.c +++ b/src/os/linux/avr32/init.c @@ -43,7 +43,7 @@ extern size_t trap_h_size; handler_fn *trap_handler_f[256]; -int trap_debug(struct frame *Frame, struct jem_state *jem) +int trap_debug(struct jem_state *jem) { union { struct { @@ -88,7 +88,7 @@ static char *trap_handler(void) return trap; } -extern int do_jamInstrps(struct frame *Frame, struct jem_state *jem); +extern int do_jamInstrps(struct jem_state *jem); #endif void initialisePlatform(void) -- 2.11.4.GIT