/* src/vm/jit/intrp/engine.c - #included by engine1.c and engine2.c Copyright (C) 1996-2005, 2006, 2007, 2008 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* #define VM_DEBUG */ #include "config.h" #include #include "vm/types.h" #include "arch.h" #include "vm/jit/intrp/intrp.h" #include "md-abi.h" /* required for TRACE_ARGS_NUM */ #include "mm/memory.hpp" #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" #include "vm/loader.hpp" #include "vm/options.h" #include "vm/jit/methodheader.h" #include "vm/jit/patcher.h" #include "vm/jit/stacktrace.hpp" #if defined(ENABLE_THREADS) # include "threads/atomic.hpp" #endif #if !defined(STORE_ORDER_BARRIER) && !defined(ENABLE_THREADS) #define STORE_ORDER_BARRIER() /* nothing */ #endif /* threading macros */ #define GCC_PR15242_WORKAROUND #ifdef GCC_PR15242_WORKAROUND # define NEXT_P1_5 # define DO_GOTO goto before_goto #else # define NEXT_P1_5 # define DO_GOTO goto *ip[-1] #endif # define NEXT_P0 # define IP (ip) # define SET_IP(p) do {ip=(p); NEXT_P0;} while (0) # define NEXT_INST (*IP) # define INC_IP(const_inc) do { ip+=(const_inc);} while (0) # define DEF_CA # define NEXT_P1 (ip++) # define NEXT_P2 do {NEXT_P1_5; DO_GOTO;} while(0) #define NEXT ({DEF_CA NEXT_P1; NEXT_P2;}) #define IPTOS NEXT_INST #if defined(__POWERPC__) || defined(__POWERPC64__) || defined(__SPARC__) # define USE_spTOS #endif #if defined(USE_spTOS) #define IF_spTOS(x) x #else #define IF_spTOS(x) #define spTOS (sp[0]) #endif #if defined(__I386__) /* works with gcc-2.95.4 20011002 (Debian prerelease) without static supers */ #define SPREG /* __asm__("%esi") */ #define TOSREG /* __asm__("%ecx") */ #elif defined(__X86_64__) /* works with gcc-4.0.2 (Debian 4.0.2-2) */ #define SPREG /* __asm__("%r15") */ #define TOSREG #else #define SPREG #define TOSREG #endif /* conversion on fetch */ #ifdef VM_PROFILING #define SUPER_END vm_count_block(IP) #else #define SUPER_END #define vm_uncount_block(_ip) /* nothing */ #endif #define THROW0 goto throw #if 1 #define THROW(_ball) do { \ __asm__(""); /* work around gcc PR 25285 */ \ goto *throw_##_ball; \ } while (0) #else #define THROW(_ball) do { \ goto throw_##_ball##1; \ } while (0) #endif #define THROWCODE(_ball) \ throw_##_ball##1: \ global_sp = sp; \ *exceptionptr = (stacktrace_inline_##_ball(NULL, (u1 *) fp, (u1 *) IP, (u1 *) IP)); \ CLEAR_global_sp; \ THROW0; #define CHECK_NULL_PTR(ptr) \ { \ if ((ptr) == NULL) { \ THROW(nullpointerexception); \ } \ } #define THROW_CLASSCASTEXCEPTION(o) \ { \ classcastexception_object = o; \ THROW(classcastexception); \ } #define CHECK_OUT_OF_BOUNDS(_array, _idx) \ { \ if (length_array(_array) <= (u4) (_idx)) { \ arrayindexoutofbounds_index = (_idx); \ THROW(arrayindexoutofboundsexception); \ } \ } #define CHECK_ZERO_DIVISOR(_divisor) \ { if (_divisor == 0) \ THROW(arithmeticexception); \ } #if 0 /* !! alignment bug */ #define access_local_long(_offset) \ ( *(s8 *)(((u1 *)fp) + (_offset)) ) #endif #define length_array(array) \ ( ((java_arrayheader*)(array))->size ) #define access_array_int(array, index) \ ((((java_intarray*)(array))->data)[index]) #define access_array_long(array, index) \ ((((java_longarray*)(array))->data)[index]) #define access_array_char(array, index) \ ((((java_chararray*)(array))->data)[index]) #define access_array_short(array, index) \ ((((java_shortarray*)(array))->data)[index]) #define access_array_byte(array, index) \ ((((java_bytearray*)(array))->data)[index]) #define access_array_addr(array, index) \ ((((java_objectarray*)(array))->data)[index]) #define access_array_float(array, index) \ ((((java_floatarray*)(array))->data)[index]) /* (see createcompilerstub in codegen.c) */ #define FRAMESIZE(stub) (((Cell *)stub)[1]) #if 0 #define CLEARSTACK(_start, _end) \ do {Cell *__start=(_start); MSET(__start,0,u1,(_end)-__start); } while (0) #else #define CLEARSTACK(_start, _end) #endif #ifdef VM_DEBUG #define NAME(_x) if (vm_debug) {fprintf(vm_out, "%lx: %-20s, ", (long)(ip-1), _x); fprintf(vm_out,"fp=%p, sp=%p", fp, sp);} #else #define NAME(_x) #endif #define LABEL2(name) J_##name: __asm__(""); #define LABEL3(name) K_##name: __asm__(""); java_objectheader * engine(Inst *ip0, Cell * sp0, Cell * fp) { Inst *ip; register Cell *sp SPREG = sp0; /* Inst ca1; XXX unused? */ /* code address; this is the next dispatched instruction */ IF_spTOS(register Cell spTOS TOSREG;) static Inst labels[] = { #define INST_ADDR(_inst) (&&I_##_inst) #include #undef INST_ADDR NULL, #define INST_ADDR(_inst) (&&J_##_inst) #include #undef INST_ADDR #define INST_ADDR(_inst) (&&K_##_inst) #include #undef INST_ADDR (Label)&&after_last, (Label)&&before_goto, (Label)&&after_goto, #define INST_ADDR(_inst) (&&H_##_inst) #include #undef INST_ADDR }; /* local variables for the various throw codes; this helps make potentially throwing instructions relocatable (instead of a non-relocatable direct jump, they perform an indirect jump) */ Label throw_arithmeticexception = &&throw_arithmeticexception1; Label throw_arrayindexoutofboundsexception = &&throw_arrayindexoutofboundsexception1; Label throw_classcastexception = &&throw_classcastexception1; Label throw_nullpointerexception = &&throw_nullpointerexception1; Label throw_arraystoreexception = &&throw_arraystoreexception1; java_objectheader *classcastexception_object = NULL; s4 arrayindexoutofbounds_index = 0; /* pass the index to the throw code */ if (vm_debug) fprintf(vm_out,"entering engine(%p,%p,%p)\n",ip0,sp,fp); if (ip0 == NULL) { return (java_objectheader *)labels; } if (0) { before_goto: goto *ip[-1]; after_goto: /* ensure that gcc does not constant-propagate the contents of these variables and thus undo our relocatability work */ throw_arithmeticexception = 0; throw_arrayindexoutofboundsexception = 0; throw_classcastexception = 0; throw_nullpointerexception = 0; throw_arraystoreexception = 0; /* the actual codes jumped to through the ...exception variables */ THROWCODE(arithmeticexception); THROWCODE(nullpointerexception); THROWCODE(arraystoreexception); throw_classcastexception1: global_sp = sp; *exceptionptr = stacktrace_inline_classcastexception(NULL, (u1 *) fp, (u1 *) IP, (u1 *) IP, classcastexception_object); CLEAR_global_sp; THROW0; throw_arrayindexoutofboundsexception1: global_sp = sp; *exceptionptr = stacktrace_inline_arrayindexoutofboundsexception(NULL, (u1 *) fp, (u1 *) IP, (u1 *) IP, arrayindexoutofbounds_index); CLEAR_global_sp; THROW0; } /* I don't have a clue where these things come from, but I've put them in macros.h for the moment */ IF_spTOS(spTOS = sp[0]); SET_IP(ip0); NEXT; #define INST_ADDR(_inst) (&&I_##_inst) #include #undef NAME after_last: return NULL; } /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where * Emacs will automagically detect them. * --------------------------------------------------------------------- * Local variables: * mode: c * indent-tabs-mode: t * c-basic-offset: 4 * tab-width: 4 * End: * vim:noexpandtab:sw=4:ts=4: */