diff -aruN shujit-0.3.5/ChangeLog shujit/ChangeLog --- shujit-0.3.5/ChangeLog Tue Aug 17 17:07:22 1999 +++ shujit/ChangeLog Fri Aug 20 17:27:03 1999 @@ -1,5 +1,25 @@ $Id$ +[19990820] + +make 時に config.h が存在しない場合、./configure を実行するのを止め、 +警告して終了するようにした。 +(GNUmakefile.in) + +0.3.6 リリース。 + +[19990818] + +fmul, dmul, fdiv, ddiv 命令の strictfp 版である、 +内部命令 fmul_strict, ... を用意した。 +Java Grande Forum の Numerical Working Group が推奨する技法を実装。 +FP-strict の文脈では、overflow を検出するための store-reload technique、 +underflow を検出し、きちんと gradual underflow させるための scale down and up +を行うようにした。 +参考: Improving Java for Numerical Computation, + http://math.nist.gov/javanumerics/ +(compiler.h, code.c) + [19990817] invokeinterface 命令で getInterfaceMethod() (runtime.c) を呼び出した後、 @@ -10,6 +30,20 @@ (GNUmakefile.in) 0.3.5 リリース。 + +例外発生時にスタックをクリアする方法を誤っていた。 +(code.c) + +strictfp が指定されたメソッドでは、 +メソッドの頭で FPU の丸め精度を倍精度にし、 +末尾で元の control word に戻すようにした。 +そのために、内部命令 strictenter, strictexit を用意。 +strictfp 対応の準備。 +(code.c, compiler.h, compile.c) + +オプション ignstrictfp を用意。 +class, method modifier、strictfp を無視する。 +(compiler.h, compiler.c, compile.c) [19990816] diff -aruN shujit-0.3.5/GNUmakefile shujit/GNUmakefile --- shujit-0.3.5/GNUmakefile Tue Aug 17 17:06:24 1999 +++ shujit/GNUmakefile Fri Aug 20 17:25:31 1999 @@ -99,9 +99,14 @@ all: ${TARGET} -${TARGET}: config.h subdir ${OBJ} ${GENEDOBJ} +${TARGET}: do_config ${OBJ} ${GENEDOBJ} ${LD_DYNAMIC} -o $@ ${OBJ} ${GENEDOBJ} ${LIBS} +do_config: + @if [ ! -f config.h ]; then \ + (echo 'Type ./configure then make.'; false) \ + fi + subdir: ifdef SUBDIR @for subdir in ${SUBDIR}; do \ @@ -131,9 +136,6 @@ ${CC} -S -fno-omit-frame-pointer ${NOOPTCFLAGS} $< endif - -config.h: configure.in - ./configure ${GENEDHDR}: code.o ${GENCONST} ${OBJDUMP} -dx $< | ${RUBY} ${GENCONST} diff -aruN shujit-0.3.5/GNUmakefile.in shujit/GNUmakefile.in --- shujit-0.3.5/GNUmakefile.in Tue Aug 17 17:05:40 1999 +++ shujit/GNUmakefile.in Fri Aug 20 17:24:56 1999 @@ -99,9 +99,14 @@ all: ${TARGET} -${TARGET}: config.h subdir ${OBJ} ${GENEDOBJ} +${TARGET}: do_config ${OBJ} ${GENEDOBJ} ${LD_DYNAMIC} -o $@ ${OBJ} ${GENEDOBJ} ${LIBS} +do_config: + @if [ ! -f config.h ]; then \ + (echo 'Type ./configure then make.'; false) \ + fi + subdir: ifdef SUBDIR @for subdir in ${SUBDIR}; do \ @@ -131,9 +136,6 @@ ${CC} -S -fno-omit-frame-pointer ${NOOPTCFLAGS} $< endif - -config.h: configure.in - ./configure ${GENEDHDR}: code.o ${GENCONST} ${OBJDUMP} -dx $< | ${RUBY} ${GENCONST} diff -aruN shujit-0.3.5/code.c shujit/code.c --- shujit-0.3.5/code.c Tue Aug 17 16:03:07 1999 +++ shujit/code.c Thu Aug 19 03:10:59 1999 @@ -33,6 +33,19 @@ #endif /* METAVM */ +/* + * Global Variables + */ +unsigned char double_scale_pos[10] = + { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0x7b }; /* 2^ (16383 - 1023) */ +unsigned char double_scale_neg[10] = + { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0x03 }; /* 2^ -(16383 - 1023) */ +unsigned char single_scale_pos[10] = + { 0, 0, 0, 0, 0, 0, 0, 0x80, 0x7f, 0x7f }; /* 2^ (16383 - 127) */ +unsigned char single_scale_neg[10] = + { 0, 0, 0, 0, 0, 0, 0, 0x80, 0x7f, 0x00 }; /* 2^ -(16383 - 127) */ + + #define COMPILEDCODE(DST) \ asm("movl %0,%" #DST : : "m" (mb)); /* DST = mb */\ METHOD_COMPILEDCODE(DST,DST); /* DST = mb->CompiledCode */ @@ -45,8 +58,11 @@ , int runtime_debug #endif ) { - int32_t bytepcoff; /* -4(%ebp) */ - /* to handle exceptions */ + int32_t bytepcoff; /* -4(%ebp) */ + /* for handling exceptions */ + uint16_t preserved_fpucw; /* -6(%ebp) */ + uint16_t fpucw; /* -8(%ebp) */ + /* %esi: stack_item *vars */ @@ -226,11 +242,12 @@ */ /* method head */ +#define LOCAL_VAR_AREA 32 /* 4 * #local_var */ +#define SAVED_REG_AREA 8 /* 8 bytes: edi,esi */ CODE_WITHOUT_DEBUG(opc_methodhead, head, STANY, STSTA, 0) { asm("pushl %ebp\n\t" "movl %esp,%ebp\n\t" - "subl $4,%esp\n\t" /* 4 * #local_var */ -#define SAVED_REG_AREA 8 /* 16 bytes: ecx,edx,edi,esi */ + "subl $" STR(LOCAL_VAR_AREA) ",%esp\n\t" "pushl %edi\n\t" "pushl %esi"); @@ -303,7 +320,7 @@ /* method tail */ CODE(opc_methodtail, tail, STANY, STSTA, 0) { - asm("leal -4-" STR(SAVED_REG_AREA) "(%ebp),%esp"); + asm("leal -" STR(LOCAL_VAR_AREA) "-" STR(SAVED_REG_AREA) "(%ebp),%esp"); /* -4 * (#local_var + #registers_on_stack) */ asm("popl %esi\n\t" "popl %edi"); @@ -311,88 +328,6 @@ "ret"); } - /* enter synchronized method */ -#ifdef METAVM -# define METAVM_MONITOR(OPTOP1_REG, METAVM_FUNCNAME, LABEL, STATE) \ - JUMP_IF_NOT_PROXY(OPTOP1_REG, LABEL "_local");\ - JUMP_IF_NOT_REMOTE(LABEL "_local");\ - \ - FUNCCALL_IN(STATE);\ - \ - asm("movl %0,%%edi" : : "m" (ee)); /* edi = ee*/\ - \ - asm("pushl " #OPTOP1_REG "\n\t"\ - "pushl %edi\n\t"\ - "call " SYMBOL(METAVM_FUNCNAME) "@PLT\n\t"\ - "popl %edi\n\t" /* edi = ee */\ - "addl $4,%esp");\ - \ - FUNCCALL_OUT(STATE);\ - \ - JUMP_IF_EXC_HASNT_OCCURRED(%edi /* is ee */, LABEL "_done");\ -DEBUG_IN;\ -PUSH_CONSTSTR("METAVM_MONITOR exc. occurred.\n");\ -asm("call " SYMBOL(printf) "@PLT\n\t"\ - "addl $4,%esp");\ -FFLUSH;\ -DEBUG_OUT;\ - SIGNAL_ERROR_JUMP(STATE);\ - asm(LABEL "_local:") -#else -# define METAVM_MONITOR(OPTOP1_REG, METAVM_FUNCNAME, LABEL, STATE) -#endif /* METAVM */ - -#if JDK_VER >= 12 -# define CALL_MONITOR0(MON, FUNCNAME) \ - asm("pushl " #MON);\ - asm("pushl %0" : : "m" (ee)); /* ee */\ - asm("call " SYMBOL(FUNCNAME) "@PLT\n\t"\ - "addl $8,%esp") -#else -# define CALL_MONITOR0(MON, FUNCNAME) \ - asm("pushl " #MON "\n\t"\ - "call " SYMBOL(FUNCNAME) "@PLT\n\t"\ - "addl $4,%esp") -#endif /* JDK_VER */ -# define CALL_MONITOR(MON, FUNCNAME, STATE) \ - FUNCCALL_IN(STATE);\ - CALL_MONITOR0(MON, FUNCNAME);\ - FUNCCALL_OUT(STATE) - - CODE(opc_syncenter, syncenter, STANY, STSTA, 0) { - /* monitorEnter(obj_monitor(o)); */ -#ifdef SET_FRAME_MONITOR - /* frame->monitor = (struct sys_mon *)o */ - asm("movl %0,%%edi" : : "m" (ee)); /* edi = ee */ - asm("movl " EE_CURRENTFRAME(%edi) ",%edi"); -#endif - asm("movl %0,%%eax" : : "m" (o)); -#ifdef SET_FRAME_MONITOR - asm("movl %eax," FRAME_MONITOR(%edi)); -#endif - METAVM_MONITOR(%eax, proxy_monitorenter, "syncenter", 0); - OBJ_MONITOR(%eax, %eax); -#if JDK_VER >= 12 - CALL_MONITOR(%eax, monitorEnter2, 0); -#else - CALL_MONITOR(%eax, monitorEnter, 0); -#endif - asm("syncenter_done:"); - } - - /* exit synchronized method */ - CODE(opc_syncexit, syncexit, STANY, STSTA, 0) { - /* monitorExit(obj_monitor(o)); */ - asm("movl %0,%%eax" : : "m" (o)); - METAVM_MONITOR(%eax, proxy_monitorexit, "syncexit", 0); - OBJ_MONITOR(%eax, %eax); -#if JDK_VER >= 12 - CALL_MONITOR(%eax, monitorExit2, 0); -#else - CALL_MONITOR(%eax, monitorExit, 0); -#endif - } - /* exception handler */ /* eax,edx may be ename,DetailMessage */ CODE(opc_exc_handler, exc_handler, STANY, STSTA, 0) { @@ -434,7 +369,7 @@ "jz exc_through"); /* clear the stack */ - asm("leal -" STR(SAVED_REG_AREA) "(%ebp),%esp"); + asm("leal -" STR(LOCAL_VAR_AREA) "-" STR(SAVED_REG_AREA) "(%ebp),%esp"); { /* place the exception object on TOS */ register ExecEnv *cur_ee asm("edi"); @@ -495,6 +430,113 @@ asm("exc_through:"); } + /* enter synchronized method */ +#ifdef METAVM +# define METAVM_MONITOR(OPTOP1_REG, METAVM_FUNCNAME, LABEL, STATE) \ + JUMP_IF_NOT_PROXY(OPTOP1_REG, LABEL "_local");\ + JUMP_IF_NOT_REMOTE(LABEL "_local");\ + \ + FUNCCALL_IN(STATE);\ + \ + asm("movl %0,%%edi" : : "m" (ee)); /* edi = ee*/\ + \ + asm("pushl " #OPTOP1_REG "\n\t"\ + "pushl %edi\n\t"\ + "call " SYMBOL(METAVM_FUNCNAME) "@PLT\n\t"\ + "popl %edi\n\t" /* edi = ee */\ + "addl $4,%esp");\ + \ + FUNCCALL_OUT(STATE);\ + \ + JUMP_IF_EXC_HASNT_OCCURRED(%edi /* is ee */, LABEL "_done");\ +DEBUG_IN;\ +PUSH_CONSTSTR("METAVM_MONITOR exc. occurred.\n");\ +asm("call " SYMBOL(printf) "@PLT\n\t"\ + "addl $4,%esp");\ +FFLUSH;\ +DEBUG_OUT;\ + SIGNAL_ERROR_JUMP(STATE);\ + asm(LABEL "_local:") +#else +# define METAVM_MONITOR(OPTOP1_REG, METAVM_FUNCNAME, LABEL, STATE) +#endif /* METAVM */ + +#if JDK_VER >= 12 +# define CALL_MONITOR0(MON, FUNCNAME) \ + asm("pushl " #MON);\ + asm("pushl %0" : : "m" (ee)); /* ee */\ + asm("call " SYMBOL(FUNCNAME) "@PLT\n\t"\ + "addl $8,%esp") +#else +# define CALL_MONITOR0(MON, FUNCNAME) \ + asm("pushl " #MON "\n\t"\ + "call " SYMBOL(FUNCNAME) "@PLT\n\t"\ + "addl $4,%esp") +#endif /* JDK_VER */ +# define CALL_MONITOR(MON, FUNCNAME, STATE) \ + FUNCCALL_IN(STATE);\ + CALL_MONITOR0(MON, FUNCNAME);\ + FUNCCALL_OUT(STATE) + + CODE(opc_syncenter, syncenter, STANY, STSTA, 0) { + /* monitorEnter(obj_monitor(o)); */ +#ifdef SET_FRAME_MONITOR + /* frame->monitor = (struct sys_mon *)o */ + asm("movl %0,%%edi" : : "m" (ee)); /* edi = ee */ + asm("movl " EE_CURRENTFRAME(%edi) ",%edi"); +#endif + asm("movl %0,%%eax" : : "m" (o)); +#ifdef SET_FRAME_MONITOR + asm("movl %eax," FRAME_MONITOR(%edi)); +#endif + METAVM_MONITOR(%eax, proxy_monitorenter, "syncenter", 0); + OBJ_MONITOR(%eax, %eax); +#if JDK_VER >= 12 + CALL_MONITOR(%eax, monitorEnter2, 0); +#else + CALL_MONITOR(%eax, monitorEnter, 0); +#endif + asm("syncenter_done:"); + } + + /* exit synchronized method */ + CODE(opc_syncexit, syncexit, STANY, STSTA, 0) { + /* monitorExit(obj_monitor(o)); */ + asm("movl %0,%%eax" : : "m" (o)); + METAVM_MONITOR(%eax, proxy_monitorexit, "syncexit", 0); + OBJ_MONITOR(%eax, %eax); +#if JDK_VER >= 12 + CALL_MONITOR(%eax, monitorExit2, 0); +#else + CALL_MONITOR(%eax, monitorExit, 0); +#endif + } + + /* enter strictfp method */ + CODE(opc_strictenter, strictenter, STANY, STSTA, 0) { + /* save FPU control word */ + asm("fstcw %0" : "=m" (preserved_fpucw)); + } + + /* exit strictfp method */ + CODE(opc_strictexit, strictexit, STANY, STSTA, 0) { + /* restore FPU control word */ + asm("fldcw %0" : : "m" (preserved_fpucw)); + } + + /* set FPU rounding precision to single, double, extended */ +#define CODE_FPPC(PC, CHANGE_CW) \ + CODE(opc_fppc_##PC, fppc_##PC, STANY, STSTA, 0) {\ + asm("movw %0,%%ax" : "=m" (preserved_fpucw));\ + asm(CHANGE_CW);\ + asm("movw %%ax,%0\n\t"\ + "fldcw %0" : "=m" (fpucw));\ + } + + CODE_FPPC(single, "andl $0xfcff,%eax"); + CODE_FPPC(double, "andl $0xfcff,%eax\n\torl $0x0200,%eax"); + CODE_FPPC(ext, "orl $0x0300,%eax"); + /* nop */ CODE(opc_nop, nop, STANY, STSTA, 0) { } @@ -2138,19 +2180,23 @@ #define CODE_ARITH_FLOAT(VOP, ROP, SYM) \ CODE(opc_f##VOP, f##VOP, ST0, ST0, 0) {\ ARITH_FLOAT_DEBUG1(SYM);\ - asm("flds 4(%esp)\n\t"\ - "f" #ROP "s (%esp)\n\t"\ - "addl $4,%esp\n\t"\ - "fstps (%esp)");\ + asm("flds 4(%esp)");\ + ARITH_FLOAT_SCALE_DOWN;\ + asm("f" #ROP "s (%esp)\n\t"\ + "addl $4,%esp");\ + ARITH_FLOAT_SCALE_UP;\ + asm("fstps (%esp)");\ ARITH_FLOAT_DEBUG2;\ }\ CODE(opc_f##VOP, f##VOP, ST1, ST0, 0) {\ asm("flds (%esp)\n\t"\ "pushl %edx");\ ARITH_FLOAT_DEBUG1(SYM);\ + ARITH_FLOAT_SCALE_DOWN;\ asm("f" #ROP "s (%esp)\n\t"\ - "addl $4,%esp\n\t"\ - "fstps (%esp)");\ + "addl $4,%esp");\ + ARITH_FLOAT_SCALE_UP;\ + asm("fstps (%esp)");\ ARITH_FLOAT_DEBUG2;\ }\ CODE(opc_f##VOP, f##VOP, ST2, ST0, 0) {\ @@ -2158,35 +2204,57 @@ "flds (%esp)\n\t"\ "pushl %ecx");\ ARITH_FLOAT_DEBUG1(SYM);\ + ARITH_FLOAT_SCALE_DOWN;\ asm("f" #ROP "s (%esp)\n\t"\ - "addl $4,%esp\n\t"\ - "fstps (%esp)");\ + "addl $4,%esp");\ + ARITH_FLOAT_SCALE_UP;\ + asm("fstps (%esp)");\ ARITH_FLOAT_DEBUG2;\ }\ CODE(opc_f##VOP, f##VOP, ST3, ST0, 0) {\ asm("flds (%esp)\n\t"\ "pushl %ecx");\ ARITH_FLOAT_DEBUG1(SYM);\ + ARITH_FLOAT_SCALE_DOWN;\ asm("f" #ROP "s (%esp)\n\t"\ - "addl $4,%esp\n\t"\ - "fstps (%esp)");\ + "addl $4,%esp");\ + ARITH_FLOAT_SCALE_UP;\ + asm("fstps (%esp)");\ ARITH_FLOAT_DEBUG2;\ }\ CODE(opc_f##VOP, f##VOP, ST4, ST0, 0) {\ asm("pushl %ecx\n\t"\ "flds (%esp)\n\t"\ - "pushl %edx\n\t"\ - "f" #ROP "s (%esp)\n\t"\ - "addl $4,%esp\n\t"\ - "fstps (%esp)");\ + "pushl %edx");\ + ARITH_FLOAT_DEBUG1(SYM);\ + ARITH_FLOAT_SCALE_DOWN;\ + asm("f" #ROP "s (%esp)\n\t"\ + "addl $4,%esp");\ + ARITH_FLOAT_SCALE_UP;\ + asm("fstps (%esp)");\ ARITH_FLOAT_DEBUG2;\ } +#define ARITH_FLOAT_SCALE_DOWN +#define ARITH_FLOAT_SCALE_UP + CODE_ARITH_FLOAT(add, add, "+"); CODE_ARITH_FLOAT(sub, sub, "-"); CODE_ARITH_FLOAT(mul, mul, "*"); CODE_ARITH_FLOAT(div, div, "/"); +#undef ARITH_FLOAT_SCALE_DOWN +#undef ARITH_FLOAT_SCALE_UP +#define ARITH_FLOAT_SCALE_DOWN \ + asm("fldt %0\n\t"\ + "fmulp" : : "m" (*single_scale_neg) : "edx","ecx","esi") +#define ARITH_FLOAT_SCALE_UP \ + asm("fldt %0\n\t"\ + "fmulp" : : "m" (*single_scale_pos) : "edx","ecx","esi") + + CODE_ARITH_FLOAT(mul_strict, mul, "*"); + CODE_ARITH_FLOAT(div_strict, div, "/"); + /* dadd, dsub, dmul, ddiv */ #ifdef RUNTIME_DEBUG # define ARITH_DOUBLE_DEBUG1(OPTOP1_REG, OPTOP2_REG, SYM) \ @@ -2223,11 +2291,13 @@ #define DOUBLE_ST24(ROP, OPTOP1_REG, OPTOP2_REG, SYM) \ ARITH_DOUBLE_DEBUG1(OPTOP1_REG, OPTOP2_REG, SYM);\ asm("fldl (%esp)\n\t" /* load v1[0:63] */\ - "addl $8,%esp\n\t"\ - "pushl " #OPTOP2_REG "\n\t" /* v2[32:63] */\ + "addl $8,%esp");\ + ARITH_DOUBLE_SCALE_DOWN;\ + asm("pushl " #OPTOP2_REG "\n\t" /* v2[32:63] */\ "pushl " #OPTOP1_REG "\n\t" /* v2[0:31] */\ - "f" #ROP "l (%esp)\n\t"\ - "fstpl (%esp)");\ + "f" #ROP "l (%esp)");\ + ARITH_DOUBLE_SCALE_UP;\ + asm("fstpl (%esp)");\ ARITH_DOUBLE_DEBUG2 /* now state 0 */ @@ -2252,10 +2322,25 @@ DOUBLE_ST24(ROP, %edx, %ecx, SYM);\ } +#define ARITH_DOUBLE_SCALE_DOWN +#define ARITH_DOUBLE_SCALE_UP + CODE_ARITH_DOUBLE(add, add, "+"); CODE_ARITH_DOUBLE(sub, sub, "-"); CODE_ARITH_DOUBLE(mul, mul, "*"); CODE_ARITH_DOUBLE(div, div, "/"); + +#undef ARITH_DOUBLE_SCALE_DOWN +#undef ARITH_DOUBLE_SCALE_UP +#define ARITH_DOUBLE_SCALE_DOWN \ + asm("fldt %0\n\t"\ + "fmulp" : : "m" (*double_scale_neg) : "edx","ecx","esi") +#define ARITH_DOUBLE_SCALE_UP \ + asm("fldt %0\n\t"\ + "fmulp" : : "m" (*double_scale_pos) : "edx","ecx","esi") + + CODE_ARITH_DOUBLE(mul_strict, mul, "*"); + CODE_ARITH_DOUBLE(div_strict, div, "/"); /* frem */ #define FREM_ST0 \ diff -aruN shujit-0.3.5/code.h shujit/code.h --- shujit-0.3.5/code.h Sun Aug 15 18:12:53 1999 +++ shujit/code.h Wed Aug 18 00:59:16 1999 @@ -190,7 +190,7 @@ * for each opcode of JVM. * * 0xf1 (0x82, 0xd6, 0xf1 is not defined in x86 insn. set) - * 0xe9, opcode(2 byte), initial state(1 byte), last state(1 byte) + * 0xe9, opcode(2 byte), initial state(4 bit), last state(4 bit) */ #ifdef RUNTIME_DEBUG diff -aruN shujit-0.3.5/compile.c shujit/compile.c --- shujit-0.3.5/compile.c Mon Aug 16 23:09:45 1999 +++ shujit/compile.c Thu Aug 19 03:39:48 1999 @@ -327,6 +327,14 @@ if (processAnOpcode(cc, opc_methodhead, &state, &dummy_byteoff)) return 1; + if (!is_fpupc_double && !OPT_SETQ(OPT_IGNSTRICTFP) && + (mb->fb.access & ACC_STRICT)) { + if (processAnOpcode(cc, opc_strictenter, &state, &dummy_byteoff)) + return 1; + if (processAnOpcode(cc, opc_fppc_double, &state, &dummy_byteoff)) + return 1; + } + if (mb->fb.access & ACC_SYNCHRONIZED) if (processAnOpcode(cc, opc_syncenter, &state, &dummy_byteoff)) return 1; @@ -416,6 +424,12 @@ if (processAnOpcode(cc, opc_syncexit, &state, &dummy_byteoff)) return 1; + if (!is_fpupc_double && !OPT_SETQ(OPT_IGNSTRICTFP) && + (mb->fb.access & ACC_STRICT)) { + if (processAnOpcode(cc, opc_strictexit, &state, &dummy_byteoff)) + return 1; + } + if (processAnOpcode(cc, opc_methodtail, &state, &dummy_byteoff)) return 1; @@ -454,7 +468,7 @@ return 1; /* failure */ } - /* find the opcode for native code */ + /* translate an opcode to an internal opcode */ switch (opcode) { case opc_aconst_null: case opc_fconst_0: @@ -630,6 +644,22 @@ code_opcode = opcode; break; } /* switch (opcode) */ + + if (!OPT_SETQ(OPT_IGNSTRICTFP) && (mb->fb.access & ACC_STRICT)) { + switch (code_opcode) { + case opc_fmul: + code_opcode = opc_fmul_strict; break; + case opc_dmul: + code_opcode = opc_dmul_strict; break; + case opc_fdiv: + code_opcode = opc_fdiv_strict; break; + case opc_ddiv: + code_opcode = opc_ddiv_strict; break; + } + } + + +#if 1 /* adjust to invokespecial if invokevirtual private method */ if (opcode == opc_invokevirtual) { unsigned index = GET_UINT16(bytepc + 1); @@ -664,6 +694,8 @@ code_opcode = opc_invokespecial; } } +#endif /* #if 0 or 1 */ + #if 1 /* translate invokevirtual Object# to invokeignored_quick */ @@ -723,6 +755,7 @@ } } #endif /* #if 0 or 1 */ + #ifdef COMPILE_DEBUG if (code_opcode != opcode) { diff -aruN shujit-0.3.5/compiler.c shujit/compiler.c --- shujit-0.3.5/compiler.c Sun Aug 15 18:35:14 1999 +++ shujit/compiler.c Thu Aug 19 03:48:02 1999 @@ -53,6 +53,8 @@ bool_t compiler_enabled = TRUE; #endif /* IGNORE_DISABLE */ +bool_t is_fpupc_double = FALSE; + #if (defined(EXC_BY_SIGNAL) || defined(GET_SIGCONTEXT)) && defined(SEARCH_SIGCONTEXT) # ifdef linux unsigned short reg_gs; @@ -88,6 +90,7 @@ {"codedb", OPT_CODEDB}, #endif /* CODE_DB */ {"cmplatload", OPT_CMPLATLOAD}, + {"ignstrictfp", OPT_IGNSTRICTFP}, {NULL, -1} }; int options = 0; @@ -323,13 +326,16 @@ } -#if defined(RUNTIME_DEBUG) || defined(COMPILE_DEBUG) + /* check the FPU roundig precision */ { - char fpuenv[28]; - fillFPUEnv(fpuenv); - showFPUEnv(stderr, " ", fpuenv); - } + uint16_t cw; + asm("fstcw %0" : "=m" (cw)); + is_fpupc_double = ((cw & 0x0300) == 0x0200); +#if defined(RUNTIME_DEBUG) || defined(COMPILE_DEBUG) + printf("FPU rounding precision is%s double.\n", + (is_fpupc_double?"":" not")); #endif + } #if (defined(EXC_BY_SIGNAL) || defined(GET_SIGCONTEXT))&& defined(SEARCH_SIGCONTEXT) diff -aruN shujit-0.3.5/compiler.h shujit/compiler.h --- shujit-0.3.5/compiler.h Mon Aug 16 23:16:40 1999 +++ shujit/compiler.h Thu Aug 19 03:14:33 1999 @@ -34,37 +34,48 @@ */ #define opc_invokeignored_static 230 /* 0xe6 */ -#define opc_getstatic2 231 /* 0xe7 */ -#define opc_putstatic2 232 -#define opc_getfield2 233 -#define opc_putfield2 234 - -#define opc_methodhead 235 /* 0xeb */ -#define opc_epilogue 236 -#define opc_methodtail 237 -#define opc_syncenter 238 /* 0xee */ -#define opc_syncexit 239 -#define opc_exc_handler 240 - -#define opc_fill_cache 241 /* 0xf1 */ -#define opc_array_check 242 - -#define opc_iastore1 243 /* 0xf3 */ -#define opc_lastore1 244 - -#define opc_stateto0 245 /* 0xf5 */ -#define opc_stateto1 246 -#define opc_stateto2 247 -#define opc_stateto3 248 -#define opc_stateto4 249 - -#define opc_goto_st0 250 /* 0xfa */ -#define opc_goto_st1 251 -#define opc_goto_st2 252 -#define opc_goto_st3 253 -#define opc_goto_st4 254 +#define opc_fmul_strict 231 /* 0xe7 */ +#define opc_dmul_strict 232 +#define opc_fdiv_strict 233 +#define opc_ddiv_strict 234 + +#define opc_getstatic2 235 /* 0xeb */ +#define opc_putstatic2 236 +#define opc_getfield2 237 +#define opc_putfield2 238 + +#define opc_methodhead 239 /* 0xef */ +#define opc_epilogue 240 +#define opc_exc_handler 241 +#define opc_methodtail 242 +#define opc_syncenter 243 +#define opc_syncexit 244 +#define opc_strictenter 245 +#define opc_strictexit 246 + +#define opc_fppc_single 247 /* 0xf7 */ +#define opc_fppc_double 248 +#define opc_fppc_ext 249 + +#define opc_fill_cache 250 /* 0xfa */ +#define opc_array_check 251 + +#define opc_iastore1 252 /* 0xfc */ +#define opc_lastore1 253 + +#define opc_stateto0 254 /* 0xfe */ +#define opc_stateto1 255 +#define opc_stateto2 256 +#define opc_stateto3 257 +#define opc_stateto4 258 + +#define opc_goto_st0 259 /* 0x103 */ +#define opc_goto_st1 260 +#define opc_goto_st2 261 +#define opc_goto_st3 262 +#define opc_goto_st4 263 -#define NOPCODES 255 +#define NOPCODES 264 /* offerred by Sun */ @@ -224,6 +235,7 @@ #endif #if JDK_VER < 12 +# define ACC_STRICT 0x0800 /* ACC_XXUNUSED1*/ /* strictfp */ # define monitorEnter2(EE, KEY) monitorEnter(KEY) # define monitorExit2(EE, KEY) monitorExit(KEY) # define JVM_LoadLibrary(NAME) sysAddDLSegment(NAME) @@ -378,6 +390,25 @@ extern bool_t compiler_enabled; #endif /* IGNORE_DISABLE */ +extern bool_t is_fpupc_double; + /* Is the FPU rounding precision double? */ + +/* in code.c */ +/* for strictfp */ +extern unsigned char double_scale_pos[10]; /* 2^ (16383 - 1023) */ +extern unsigned char double_scale_neg[10]; /* 2^ -(16383 - 1023) */ +extern unsigned char single_scale_pos[10]; /* 2^ (16383 - 127) */ +extern unsigned char single_scale_neg[10]; /* 2^ -(16383 - 127) */ +#if 0 +extern struct methodtable *object_methodtable; + /* for the macro OBJ_ARRAY_METHODTABLE in code.h */ +#endif + +#ifdef METAVM +/* in proxy.c */ +extern struct methodtable *proxy_methodtable; +#endif /* METAVM */ + #if (defined(EXC_BY_SIGNAL) || defined(GET_SIGCONTEXT)) && defined(SEARCH_SIGCONTEXT) # ifdef linux extern unsigned short reg_gs; @@ -423,8 +454,10 @@ OPT_CODEDB, /* save and re-use generated native code */ #endif /* CODE_DB */ - OPT_CMPLATLOAD + OPT_CMPLATLOAD, /* compile the whole class when the class is loaded */ + OPT_IGNSTRICTFP + /* ignore `strictfp' method modifier */ }; extern int options; extern int opt_cmplthreshold; @@ -453,15 +486,6 @@ extern datum (*sym_dbm_fetch)(DBM *,datum); # endif #endif /* CODE_DB */ - -/* in code.c */ -extern struct methodtable *object_methodtable; - /* for the macro OBJ_ARRAY_METHODTABLE in code.h */ - -#ifdef METAVM -/* in proxy.c */ -extern struct methodtable *proxy_methodtable; -#endif /* METAVM */ /* diff -aruN shujit-0.3.5/gentable.rb shujit/gentable.rb --- shujit-0.3.5/gentable.rb Sun Aug 15 14:50:40 1999 +++ shujit/gentable.rb Thu Aug 19 02:52:19 1999 @@ -4,7 +4,7 @@ CONST_C_FNAME = 'constants.c' CONST_H_FNAME = 'constants.h' -NOPCODES = 255 +NOPCODES = 264 NSTATES = 5 STANY = 5 STSTA = 5 diff -aruN shujit-0.3.5/txt/memo shujit/txt/memo --- shujit-0.3.5/txt/memo Tue Aug 17 16:53:46 1999 +++ shujit/txt/memo Fri Aug 20 17:04:51 1999 @@ -59,6 +59,31 @@ - Address Generation Interlock(AGI) (MMX 本 pp.95,99) を避ける。 - invokeignored_quick にて、スタックのキャッシュ内容を無駄に push している。 +strictfp 対応 + - 参考。 + mantissa の精度 single: 24, double: 53, extended: 64 + mantissa のbit 数 single: 23, double: 52, extended: 64 + exponent のbit 数 single: 8, double: 11, extended: 15 + - 丸め精度を倍精度にして単精度の除算を行った場合、丸めは 2度起こり得るか? + JGFNW の推奨する技法で、 + 0 〜 0x00ffffff / 0x3f800001 (1.0 + e) and 0x3f7fffff (1.0 - e) では、 + 丸め精度が single でも double でも差は出ない。 + - strictfp。 + native と両立する? + - 対象となるバイトコード命令。 + (fadd, dadd, fsub, dsub,) fmul, dmul, fdiv, ddiv, frem, drem + frem, drem はどうすべき? + - test suite が欲しい。 + overflow, underflow およびそれに起因する 2度丸め。 + - クラスが strictfp だった場合、コンストラクタが strictfp になるか確認。 + - javac ではいつでも strictfp にしてしまう? + JDK 1.2 pre-release 2 for Linux はだめ。 + - C, Fortran などで strictfp。 + - 参考文献。 + - Proving the IEEE Correctness of Iterative + Floating-Point Square Root, Divide, and Remainder Algorithms, + http://www.intel.co.uk/technology/itj/q21998/articles/art_3.htm + Idea - JVM の挙動を変更する手段としての JIT compiler。 javac の、フックをかけられる箇所を探す。-> Jikes を改造?