diff -aruN shujit-0.6.3/ChangeLog shujit/ChangeLog --- shujit-0.6.3/ChangeLog Tue Aug 29 20:47:54 2000 +++ shujit/ChangeLog Sun Sep 3 18:06:03 2000 @@ -1,8 +1,55 @@ $Id$ +[20000903] + +バイトコード命令 invokespecial, invokestatic で呼び出しを +省略できる場合に、バイトコード命令を JVM に存在しない shuJIT 内部命令 +(invokeignored_static, invokeignored_static_quick) に書き換えてしまっていた。 +修整。 +(compile.c) + +呼ばれたメソッドが例外を throw したかどうかの判定を、 +callee から caller に移した。 +これまで JIT compiled code からの return 時に、 +%eax に !exceptionOccurred(ee) を入れていたが、これを省いた。 +return 後に %eax が空いた。 +(code.c) + +0.6.4 リリース。 + +[20000902] + +dstore, fstore, dastore, fastore についても、直前の内部命令 dst, fst と +combine する peephole 最適化を実装した。 +Linpack benchmark の結果が 13.205 に向上 (Pentium II / 333 MHz)。 +(optimize.c, code.c) + +[20000901] + +浮動小数点数の配列から faload, daload で値を得る際に、 +スタックや整数レジスタを経由させないための peephole 最適化を実装した。 +内部命令列 laload, flush_cache, dld を daload_dld に変換する。 +Linpack benchmark の結果が 9.035 -> 11.257 と向上 (Pentium II / 333 MHz)。 +(optimize.c, code.c) + +内部命令列 dst, fill_cache, lstore を dst_dstore に変換する +peephole 最適化を実装。 +(code.c, optimize.c) + [20000829] 0.6.3 リリース。 + +これまで内部命令の番号は 256 から始めていたところ、 +230 から 253 までの値も使うことにして、 +内部命令の最大番号を 333 から 309 と小さくした。 +libshujit.so のサイズが約 4 KB 減少。 +内部命令ひとつあたり 200 バイト消費している。 +(opcodes_internal.h) + +ループの先頭を 16 バイト境界に align するために、これまで単に +0x90 (nop) を詰めていたところ、0xeb XX (jmp XX) を詰めるようにした。 +(compile.c) [20000828] diff -aruN shujit-0.6.3/GNUmakefile shujit/GNUmakefile --- shujit-0.6.3/GNUmakefile Tue Aug 29 20:48:27 2000 +++ shujit/GNUmakefile Sun Sep 3 19:14:15 2000 @@ -49,7 +49,7 @@ INCDIR = -I${J_INCDIR} -I${J_INCDIR}/genunix -I${J_INCDIR}/linux -I${J_INCDIR}/freebsd -I/usr/local/include OPTFLAGS = -O2 -CDEBUGFLAGS =# -g -DDEBUG -DCOMPILE_DEBUG# -DRUNTIME_DEBUG# -DNO_CHECK +CDEBUGFLAGS =# -g -DDEBUG -DCOMPILE_DEBUG# -DRUNTIME_DEBUG NOOPTCFLAGS = -pipe -fPIC ${CDEBUGFLAGS} ${INCDIR} CFLAGS = ${OPTFLAGS} ${NOOPTCFLAGS} LIBS = diff -aruN shujit-0.6.3/GNUmakefile.in shujit/GNUmakefile.in --- shujit-0.6.3/GNUmakefile.in Mon Aug 14 11:01:10 2000 +++ shujit/GNUmakefile.in Thu Aug 31 23:40:17 2000 @@ -49,7 +49,7 @@ INCDIR = -I${J_INCDIR} -I${J_INCDIR}/genunix -I${J_INCDIR}/linux -I${J_INCDIR}/freebsd -I/usr/local/include OPTFLAGS = -O2 -CDEBUGFLAGS =# -g -DDEBUG -DCOMPILE_DEBUG# -DRUNTIME_DEBUG# -DNO_CHECK +CDEBUGFLAGS =# -g -DDEBUG -DCOMPILE_DEBUG# -DRUNTIME_DEBUG NOOPTCFLAGS = -pipe -fPIC ${CDEBUGFLAGS} ${INCDIR} CFLAGS = ${OPTFLAGS} ${NOOPTCFLAGS} LIBS = diff -aruN shujit-0.6.3/README shujit/README --- shujit-0.6.3/README Tue Aug 29 20:18:22 2000 +++ shujit/README Sun Sep 3 18:27:46 2000 @@ -13,8 +13,8 @@ Working on the following platforms is confirmed. - Linux - - Blackdown JDK 1.2.2 FCS, pgcc 2.95.3, glibc2.1.3 and Linux 2.4.0-test8-pre1 - - JDK 1.1.8v1, pgcc 2.95.3, glibc2.1.3 and Linux 2.4.0-test8-pre1 + - Blackdown JDK 1.2.2 FCS, pgcc 2.95.3, glibc2.1.3 and Linux 2.4.0-test8-pre2 + - JDK 1.1.8v1, pgcc 2.95.3, glibc2.1.3 and Linux 2.4.0-test8-pre2 - JDK 1.1.7v1a, egcs 1.1.2, libc5.4.38 and Linux 2.0.35 - FreeBSD diff -aruN shujit-0.6.3/code.c shujit/code.c --- shujit-0.6.3/code.c Mon Aug 28 18:33:55 2000 +++ shujit/code.c Sun Sep 3 16:33:53 2000 @@ -366,9 +366,11 @@ asm("leal -" STR(LOCAL_VAR_AREA) "-" STR(SAVED_REG_AREA) "(%ebp),%esp"); // -4 * (#local_var + #registers_on_stack) +#if 0 // disuse // eax = !exceptionOccurred(ee) asm("movl %0,%%edi" : : "m" (ee)); // edi = ee asm("movl " EE_EXCEPTIONKIND(%edi) ",%eax"); +#endif asm("popl %esi\n\t" "popl %edi"); @@ -897,7 +899,7 @@ } #ifdef OPTIMIZE_INTERNAL_CODE - CODE(opc_fload_fld, fload_fld, STANY, STSTA, OPC_NONE) { + CODE(opc_fload_fld, fload_fld, ST0, STSTA, OPC_NONE) { asm("subl $4,%esp\n\t"); // to simulate the true value of %esp asm("flds " STR(CONST) "(%esi)"); #ifdef RUNTIME_DEBUG @@ -969,7 +971,7 @@ } #ifdef OPTIMIZE_INTERNAL_CODE - CODE(opc_dload_dld, dload_dld, STANY, STSTA, OPC_NONE) { + CODE(opc_dload_dld, dload_dld, ST0, STSTA, OPC_NONE) { asm("subl $8,%esp\n\t"); // to simulate the true value of %esp asm("fldl " STR(CONST) "(%esi)"); #ifdef RUNTIME_DEBUG @@ -1145,16 +1147,18 @@ #ifdef OPTIMIZE_INTERNAL_CODE - CODE(opc_faload_fld, [ifa]aload, ST2, ST0, OPC_THROW) { + CODE(opc_faload_fld, faload_fld, ST2, ST1, OPC_THROW) { METAVM_ALOAD(%edx, %ecx, %edx, "faload_fld_st2", 0); UNHAND(%edx, %eax); asm("flds (%eax,%ecx,4)"); + // omit asm("subl $4,%esp"); asm("faload_fld_st2_done:"); } - CODE(opc_faload_fld, [ifa]aload, ST4, ST0, OPC_THROW) { + CODE(opc_faload_fld, faload_fld, ST4, ST1, OPC_THROW) { METAVM_ALOAD(%ecx, %edx, %ecx, "faload_fld_st4", 0); UNHAND(%ecx, %eax); asm("flds (%eax,%edx,4)"); + // omit asm("subl $4,%esp"); asm("faload_fld_st4_done:"); } #endif // OPTIMIZE_INTERNAL_CODE @@ -1225,16 +1229,18 @@ #ifdef OPTIMIZE_INTERNAL_CODE - CODE(opc_daload_dld, [ld]aload, ST2, ST4, OPC_THROW) { + CODE(opc_daload_dld, [ld]aload, ST2, ST2, OPC_THROW) { METAVM_ALOAD2(%edx, %ecx, %edx, %ecx, "daload_dld_st2", 2); UNHAND(%edx, %eax); asm("fldl (%eax,%ecx,8)"); + // omit asm("subl $8,%esp"); asm("daload_dld_st2_done:"); } CODE(opc_daload_dld, [ld]aload, ST4, ST2, OPC_THROW) { METAVM_ALOAD2(%ecx, %edx, %ecx, %edx, "daload_dld_st4", 4); UNHAND(%ecx, %eax); asm("fldl (%eax,%edx,8)"); + // omit asm("subl $8,%esp"); asm("daload_dld_st4_done:"); } #endif // OPTIMIZE_INTERNAL_CODE @@ -1319,10 +1325,17 @@ ILOAD_DEBUG1(%edx);\ } -CODE_ISTORE(istore, ST0, ST0, ST1, ST0, ST3); + CODE_ISTORE(istore, ST0, ST0, ST1, ST0, ST3); #ifdef OPTIMIZE_INTERNAL_CODE -CODE_ISTORE(istld, ST1, ST1, ST2, ST3, ST4); -#endif // OPTIMIZE_INTERNAL_CODE + CODE_ISTORE(istld, ST1, ST1, ST2, ST3, ST4); +#endif + +#ifdef OPTIMIZE_INTERNAL_CODE + CODE(opc_fst_fstore, fst_fstore, ST0, ST0, OPC_NONE) { + asm("addl $4,%esp"); + asm("fstps " STR(CONST) "(%esi)"); + } +#endif // lstore @@ -1340,10 +1353,17 @@ LLOAD_DEBUG1(%edx, %ecx);\ } -CODE_LSTORE(lstore, ST0, ST0); + CODE_LSTORE(lstore, ST0, ST0); #ifdef OPTIMIZE_INTERNAL_CODE -CODE_LSTORE(lstld, ST2, ST4); -#endif // OPTIMIZE_INTERNAL_CODE + CODE_LSTORE(lstld, ST2, ST4); +#endif + +#ifdef OPTIMIZE_INTERNAL_CODE + CODE(opc_dst_dstore, dst_dstore, ST0, ST0, OPC_NONE) { + asm("addl $8,%esp"); // substitution for fill_cache + asm("fstpl " STR(CONST) "(%esi)"); + } +#endif // iastore @@ -1431,6 +1451,17 @@ asm("iastore_st4_done:"); } +#if defined(OPTIMIZE_INTERNAL_CODE) && !defined(METAVM) + CODE(opc_fst_fastore, fst_fastore, ST0, ST0, OPC_NONE) { + asm("popl %eax"); // eax = value + asm("popl %ecx\n\t" // ecx = index + "popl %edx"); // edx = handle of array + ARRAY_CHECK(%edx, %ecx, "fst_fastore"); + UNHAND(%edx, %edi); + asm("fstps (%edi,%ecx,4)"); + } +#endif // OPTIMIZE_INTERNAL_CODE && !METAVM + // aastore // compile: iastore1, fill_cache, array_check, aastore @@ -1570,6 +1601,19 @@ CODE_LASTORE(%ecx, %edx, 2); CODE_LASTORE(%edx, %ecx, 4); +#if defined(OPTIMIZE_INTERNAL_CODE) && !defined(METAVM) + CODE(opc_dst_dastore, dst_dastore, ST0, ST0, OPC_SIGNAL) { + asm("movl 8(%esp),%eax\n\t" + "movl 12(%esp),%edi"); + ARRAY_CHECK(%edi, %eax, "dst_dastore"); + asm("movl 12(%esp),%edi"); + UNHAND(%edi, %edi); + asm("leal (%edi,%eax,8),%edi\n\t" + "fstpl (%edi)"); + asm("addl $16,%esp"); + } +#endif OPTIMIZE_INTERNAL_CODE && !METAVM + // bastore // compile: iastore1, fill_cache, array_check, bastore @@ -2247,6 +2291,12 @@ "addl $4,%esp"); } +#ifdef OPTIMIZE_INTERNAL_CODE + CODE(opc_fadd, fadd, ST1, ST0, OPC_NONE) { asm("fadds (%esp)"); } + CODE(opc_fmul, fmul, ST1, ST0, OPC_NONE) { asm("fmuls (%esp)"); } +#endif + + #ifdef STRICT_USE_FSCALE # ifdef STRICT_PRELOAD # define ARITH_FLOAT_SCALE_PREPARE asm("fld %st(1)") @@ -2367,6 +2417,12 @@ "addl $8,%esp"); } +#ifdef OPTIMIZE_INTERNAL_CODE + CODE(opc_dadd, dadd, ST2, ST0, OPC_NONE) { asm("faddl (%esp)"); } + CODE(opc_dmul, dmul, ST2, ST0, OPC_NONE) { asm("fmull (%esp)"); } +#endif + + #ifdef STRICT_USE_FSCALE # ifdef STRICT_PRELOAD # define ARITH_DOUBLE_SCALE_PREPARE asm("fld %st(0)") @@ -2433,9 +2489,10 @@ // frem - // compile: flush_cache, fld, frem, fst + // compile: flush_cache, frem, fst CODE(opc_frem, frem, ST0, ST0, OPC_NONE) { - asm("flds 4(%esp)"); // fld optop[-2].f (value1) + asm("flds (%esp)\n\t" // fld optop[-1].f (value2) + "flds 4(%esp)"); // fld optop[-2].f (value1) FUNCCALL_IN(0); asm("subl $16,%esp"); asm("fstpl (%esp)\n\t" // stack top = optop[-2] (value1) @@ -2530,6 +2587,12 @@ CODE(opc_fneg, fneg, ST0, ST0, OPC_NONE) { asm("fchs"); } +#ifdef OPTIMIZE_INTERNAL_CODE + CODE(opc_fneg, fneg, ST1, ST0, OPC_NONE) { + asm("subl $4,%esp\n\t" + "fchs"); + } +#endif // dneg @@ -2537,6 +2600,12 @@ CODE(opc_dneg, dneg, ST0, ST0, OPC_NONE) { asm("fchs"); } +#ifdef OPTIMIZE_INTERNAL_CODE + CODE(opc_dneg, dneg, ST2, ST0, OPC_NONE) { + asm("subl $8,%esp\n\t" + "fchs"); + } +#endif // ishl @@ -2890,6 +2959,11 @@ CODE(opc_f2d, f2d, ST0, ST0, OPC_NONE) { asm("subl $4,%esp"); } +#ifdef OPTIMIZE_INTERNAL_CODE + CODE(opc_f2d, f2d, ST1, ST0, OPC_NONE) { + asm("subl $8,%esp"); + } +#endif // d2f @@ -2897,6 +2971,11 @@ CODE(opc_d2f, d2f, ST0, ST0, OPC_NONE) { asm("addl $4,%esp"); } +#ifdef OPTIMIZE_INTERNAL_CODE + CODE(opc_d2f, d2f, ST2, ST0, OPC_NONE) { + asm("subl $4,%esp"); + } +#endif // i2b, i2c, i2s @@ -3808,18 +3887,19 @@ \ asm("movl %eax," FRAME_CURRENTMETHOD(%edi));\ /* current_frame->current_method = callee */\ + \ asm("call *%ecx");\ /* must keep: return value (%eax)\ return value of Java method (%edx, %ecx) */\ + \ asm("movl %ebp," FRAME_VARS(%edi));\ /* current_frame->vars = %ebp */\ /* for CompiledFramePrev() */\ - asm("pushl 12(%ebp)\n\t"\ - "popl " FRAME_CURRENTMETHOD(%edi));\ + asm("movl 12(%ebp),%eax"); /* %eax = caller method */\ + asm("movl %eax," FRAME_CURRENTMETHOD(%edi));\ /* current_frame->current_method = caller */\ - /* no available registers:\ + /* filled registers: %edx & %ecx: return value of Java method\ - %eax: return value of compiled code\ %edi: current frame */\ \ asm("jmp " LABEL "_invoke_done") @@ -3899,17 +3979,20 @@ INVOKE_CORE_DEBUG1; - asm("popl %edi"); // restore - asm("addl %edi,%esp"); // free local var space + asm("popl %eax"); // restore + asm("addl %eax,%esp"); // free local var space asm(".globl inv_core_done\n\t.type inv_core_done,@function"); asm("inv_core_done:"); + asm("movl %0,%%edi" : : "m" (ee)); // edi = ee + // adjust optop - asm("movl $" STR(CONST) ",%edi\n\t" // edi = args_size - "leal (%esp,%edi,4),%esp"); // esp += (args_size * 4) + asm("movl $" STR(CONST) ",%eax\n\t" // eax = args_size + "leal (%esp,%eax,4),%esp"); // esp += (args_size * 4) - // if (eax == 0) goto exc_handler + // eax = !exceptionOccurred(ee) + asm("movl " EE_EXCEPTIONKIND(%edi) ",%eax"); asm("testl %eax,%eax\n\t" "jnz " STR(ADDR_EXC)); } diff -aruN shujit-0.6.3/compile.c shujit/compile.c --- shujit-0.6.3/compile.c Mon Aug 28 18:34:07 2000 +++ shujit/compile.c Sun Sep 3 15:02:20 2000 @@ -90,7 +90,7 @@ if (!mb->code) { /* mb->code is NULL */ #ifdef COMPILE_DEBUG - printf(" mb->code is NULL: %s#%s\n", + printf(" mb->code is NULL: %s#%s %s\n", cbName(fieldclass(&mb->fb)), mb->fb.name, mb->fb.signature); fflush(stdout); #endif @@ -151,39 +151,29 @@ // compile #ifdef COUNT_TSC - cc->tsc[0] = rdtsc(); - cc->tsc[0] = rdtsc(); +# define CALL_RDTSC(N) cc->tsc[N] = rdtsc() +#else +# define CALL_RDTSC(N) #endif + + CALL_RDTSC(0); + CALL_RDTSC(0); if (makePCTable(cc)) goto compile_failed; -#ifdef COUNT_TSC - cc->tsc[1] = rdtsc(); -#endif + CALL_RDTSC(1); makeBlockStructure(cc); -#ifdef COUNT_TSC - cc->tsc[2] = rdtsc(); -#endif + CALL_RDTSC(2); #ifdef OPTIMIZE_INTERNAL_CODE optimizeInternalCode(cc); #endif -#ifdef COUNT_TSC - cc->tsc[3] = rdtsc(); -#endif + CALL_RDTSC(3); updateStates(cc); -#ifdef COUNT_TSC - cc->tsc[4] = rdtsc(); -#endif + CALL_RDTSC(4); if (writeCode(cc)) goto compile_failed; -#ifdef COUNT_TSC - cc->tsc[5] = rdtsc(); -#endif + CALL_RDTSC(5); resolveJumpInstructions(cc); -#ifdef COUNT_TSC - cc->tsc[6] = rdtsc(); -#endif + CALL_RDTSC(6); resolveExcRetSwitch(cc); -#ifdef COUNT_TSC - cc->tsc[7] = rdtsc(); -#endif + CALL_RDTSC(7); // set generated code to methodblock { @@ -214,25 +204,17 @@ writeCompiledCode(db, db_page, cc); #endif // CODE_DB -#ifdef COUNT_TSC - cc->tsc[8] = rdtsc(); -#endif + CALL_RDTSC(8); static_part_done: resolveDynamicConstants(cc); -#ifdef COUNT_TSC - cc->tsc[9] = rdtsc(); -#endif + CALL_RDTSC(9); makeExcTable(cc); -#ifdef COUNT_TSC - cc->tsc[10] = rdtsc(); -#endif + CALL_RDTSC(10); resolveFunctionSymbols(cc); -#ifdef COUNT_TSC - cc->tsc[11] = rdtsc(); -#endif + CALL_RDTSC(11); mb->invoker = (bool_t (*)(JHandle *, struct methodblock *, int, struct execenv *)) @@ -243,9 +225,8 @@ #endif + CALL_RDTSC(12); #ifdef COUNT_TSC - cc->tsc[12] = rdtsc(); - printf("%s#%s %s\n", cbName(fieldclass(&mb->fb)), mb->fb.name, mb->fb.signature); { @@ -557,7 +538,7 @@ } break; - case opc_i2f: case opc_l2f: + case opc_i2f: case opc_l2f: case opc_frem: processAnOpcode(cc, opc_flush_cache, byteoff); byteinc = processAnOpcode(cc, opcode, byteoff); processAnOpcode(cc, opc_fst, byteoff); @@ -571,7 +552,6 @@ byteoff += byteinc; break; - case opc_frem: case opc_fneg: processAnOpcode(cc, opc_flush_cache, byteoff); processAnOpcode(cc, opc_fld, byteoff); @@ -776,38 +756,38 @@ if (!(method->fb.access & (ACC_NATIVE | ACC_ABSTRACT)) && (method->code[0] == opc_return)) { unsigned char *bytepc = methodcode + byteoff; - int toNullCheck = (((method->fb.access & ACC_STATIC) == 0) && - strcmp(method->fb.name, "")); + int toNullCheck = ((method->fb.access & ACC_STATIC) == 0) && + (strcmp(method->fb.name, "") != 0); // condition: !static && !constructor // omit null checks for constructors #ifdef NO_CHECK - bytepc[0] = opcode = opc_invokeignored_static_quick; - processAnOpcode(cc, opcode, byteoff); + processAnOpcode(cc, opc_invokeignored_static_quick, byteoff); #else -# if JDK_VER >= 12 - CODE_LOCK(EE2SysThread(cc->ee)); -# else - BINCLASS_LOCK(); -# endif // JDK_VER if (toNullCheck) { - bytepc[0] = opcode = opc_invokeignored_quick; - bytepc[1] = method->args_size; - bytepc[2] = (unsigned char)toNullCheck; - // indicates whether to be checked or not - processAnOpcode(cc, opcode, byteoff); + processAnOpcode(cc, opc_invokeignored_quick, byteoff); } else { - bytepc[0] = opcode = - ((CB_INITIALIZED(fieldclass(&method->fb))) ? + opcode = ((CB_INITIALIZED(fieldclass(&method->fb))) ? opc_invokeignored_static_quick : opc_invokeignored_static); processAnOpcode(cc, opcode, byteoff); } -# if JDK_VER >= 12 +#endif // NO_CHECK + + // rewrite bytecode instruction +#if JDK_VER >= 12 + CODE_LOCK(EE2SysThread(cc->ee)); +#else + BINCLASS_LOCK(); +#endif // JDK_VER + bytepc[0] = opc_invokeignored_quick; + bytepc[1] = method->args_size; + bytepc[2] = (unsigned char)toNullCheck; + // indicates whether to be checked or not +#if JDK_VER >= 12 CODE_UNLOCK(EE2SysThread(cc->ee)); -# else +#else BINCLASS_UNLOCK(); -# endif // JDK_VER -#endif // NO_CHECK +#endif // JDK_VER goto makepc_invoke_done; } @@ -1839,10 +1819,9 @@ #ifdef ALIGN_JUMP_TARGET // align a jump target to 16-byte boundary #define ALIGN_BOUND 16 +#define ALIGN_THRESHOLD 4 + // have to >= 2 if (pcentryLoopTop(pctable)) { - static unsigned char code_pad[] = - {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90}; int pad = ((-nativeoff - (ALIGN_BOUND-1)) % ALIGN_BOUND) + (ALIGN_BOUND-1); #ifdef COMPILE_DEBUG @@ -1855,8 +1834,24 @@ #endif sysAssert((0 <= pad) && (pad < ALIGN_BOUND)); - writeToBuffer(cc, code_pad, pad); - nativeoff += pad; + if (pad >= ALIGN_THRESHOLD) { + char code_pad[2]; + + pad -= 2; + code_pad[0] = (unsigned char)0xeb; + code_pad[1] = (unsigned char)pad; + + writeToBuffer(cc, code_pad, 2); + nativeoff += 2; + } + + { + static unsigned char nops[] = + {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90}; + writeToBuffer(cc, nops, pad); + nativeoff += pad; + } } #endif // ALIGN_JUMP_TARGET @@ -1987,7 +1982,7 @@ nextoff += 6; } else { - // jXX 5 + // jXX (length_of_stateTo0 + 5) { unsigned char code_jp[] = { rop_rev, transcodep->length + 5 }; writeToBuffer(cc, code_jp, 2); @@ -2123,7 +2118,7 @@ break; case opc_iload: case opc_fload_fld: - case opc_istore: case opc_istld: + case opc_istore: case opc_istld: case opc_fst_fstore: case opc_ret: { int32_t index; @@ -2135,7 +2130,7 @@ index = operand * -4; memcpy(bufp + constant_table[opcode][state][0], &index, 4); #ifdef RUNTIME_DEBUG - if (opcode != opc_fload_fld) { + if ((opcode != opc_fload_fld) && (opcode != opc_fst_fstore)) { memcpy(bufp + constant_table[opcode][state][1], &operand, 4); } #endif @@ -2143,7 +2138,7 @@ break; case opc_lload: case opc_dload_dld: - case opc_lstore: case opc_lstld: + case opc_lstore: case opc_lstld: case opc_dst_dstore: { int32_t index; sysAssert(operand != -1); @@ -2153,7 +2148,7 @@ index = (operand + 1) * -4; memcpy(bufp + constant_table[opcode][state][0], &index, 4); - if (opcode != opc_dload_dld) { + if ((opcode != opc_dload_dld) && (opcode != opc_dst_dstore)) { index += 4; memcpy(bufp + constant_table[opcode][state][1], &index, 4); #ifdef RUNTIME_DEBUG diff -aruN shujit-0.6.3/compiler.h shujit/compiler.h --- shujit-0.6.3/compiler.h Mon Aug 28 18:46:29 2000 +++ shujit/compiler.h Sun Sep 3 17:42:58 2000 @@ -88,6 +88,7 @@ #undef NO_REWRITE #undef INITCLASS_IN_COMPILING #undef IGNORE_DISABLE +#undef NO_CHECK #if defined(NULLEXC_BY_SIGNAL) || defined(ARITHEXC_BY_SIGNAL) #define EXC_BY_SIGNAL diff -aruN shujit-0.6.3/gentable.rb shujit/gentable.rb --- shujit-0.6.3/gentable.rb Mon Aug 28 11:46:59 2000 +++ shujit/gentable.rb Sun Sep 3 13:29:45 2000 @@ -4,7 +4,7 @@ CONST_C_FNAME = 'constants.c' CONST_H_FNAME = 'constants.h' -NOPCODES = 333 +NOPCODES = 313 NSTATES = 5 STANY = 5 STSTA = 5 diff -aruN shujit-0.6.3/invoker.c shujit/invoker.c --- shujit-0.6.3/invoker.c Mon Aug 28 17:33:22 2000 +++ shujit/invoker.c Fri Sep 1 12:11:41 2000 @@ -603,6 +603,15 @@ else if ((!strcmp(cbName(fieldclass(&mb->fb)), "java/security/Security")) && (!strcmp(mb->fb.name, "initialize"))) runtime_debug = 1; + else if ((!strcmp(cbName(fieldclass(&mb->fb)), "Linpack")) + && (!strcmp(mb->fb.name, "daxpy"))) + runtime_debug = 1; + else if ((!strcmp(cbName(fieldclass(&mb->fb)), "Linpack")) + && (!strcmp(mb->fb.name, "dgesl"))) + runtime_debug = 1; + else if ((!strcmp(cbName(fieldclass(&mb->fb)), "SinBenchmark")) + && (!strcmp(mb->fb.name, "main"))) + runtime_debug = 1; else if (!strcmp(mb->fb.name, "dtoa")) runtime_debug = 1; #if 0 diff -aruN shujit-0.6.3/opcodes_internal.h shujit/opcodes_internal.h --- shujit-0.6.3/opcodes_internal.h Mon Aug 28 18:42:47 2000 +++ shujit/opcodes_internal.h Sun Sep 3 13:29:41 2000 @@ -25,103 +25,111 @@ // Internal Opcodes // #define opc_impdep1 254 // 0xfe -#define opc_impdep2 255 +#define opc_impdep2 255 // 0xff -#define opc_methodhead 256 // 0x100 -#define opc_epilogue 257 -#define opc_exc_handler 258 -#define opc_methodtail 259 -#define opc_sync_enter 260 -#define opc_sync_exit 261 -#define opc_fld4 262 -#define opc_fld 263 -#define opc_fst 264 -#define opc_dld8 265 -#define opc_dld 266 -#define opc_dst 267 - -#define opc_strict_enter 268 -#define opc_strict_exit 269 - -#define opc_fppc_save 270 -#define opc_fppc_restore 271 -#define opc_fppc_single 272 -#define opc_fppc_double 273 -#define opc_fppc_extended 274 - -#define opc_strict_fprep 275 -#define opc_strict_fscdown 276 -#define opc_strict_fscup 277 -#define opc_strict_fsettle 278 -#define opc_strict_dprep 279 // 0x117 -#define opc_strict_dscdown 280 -#define opc_strict_dscup 281 -#define opc_strict_dsettle 282 - -#define opc_throw_illegalaccess 283 -#define opc_throw_noclassdef 284 - -#define opc_fill_cache 285 // 0x11d -#define opc_flush_cache 286 -#define opc_array_check 287 - -#define opc_invokeignored_static 288 // 0x120 -#define opc_invokeignored_static_quick 289 - -#define opc_getstatic2 290 -#define opc_putstatic2 291 -#define opc_getfield2 292 -#define opc_putfield2 293 - -#define opc_iastore1 294 -#define opc_lastore1 295 - -#define opc_stateto0 296 -#define opc_stateto1 297 -#define opc_stateto2 298 -#define opc_stateto3 299 -#define opc_stateto4 300 - -#define opc_goto_st0 301 // 0x12d -#define opc_goto_st1 302 -#define opc_goto_st2 303 -#define opc_goto_st3 304 -#define opc_goto_st4 305 - -#define opc_sqrt 306 -#define opc_sin 307 -#define opc_cos 308 -#define opc_tan 309 -#define opc_atan2 310 -#define opc_atan 311 -#define opc_exp 312 -#define opc_log 313 -#define opc_floor 314 -#define opc_ceil 315 -// for OPTIMIZE_INTERNAL_CODE -#define opc_fload_fld 316 // 0x13c -#define opc_dload_dld 317 -#define opc_faload_fld 318 -#define opc_daload_dld 319 - -#define opc_istld 320 -#define opc_lstld 321 - -#define opc_direct_invoke 322 // 0x142 +#define opc_methodhead 230 // 0xe6 +#define opc_epilogue 231 +#define opc_exc_handler 232 +#define opc_methodtail 233 +#define opc_sync_enter 234 +#define opc_sync_exit 235 + +#define opc_inv_head 236 // 0xec +#define opc_inv_core 237 +#define opc_inv_metavm 238 + +#define opc_inv_vir_obj 239 // 0xef +#define opc_inv_vir_varspace 240 +#define opc_invokevirtual_obj 241 + +#define opc_inv_spe_obj 242 +#define opc_inv_spe_varspace 243 + +#define opc_inv_stq_obj 244 +#define opc_inv_stq_varspace 245 + +#define opc_direct_invoke 246 // 0xf6 + +#define opc_invokeignored_static 247 // 0xf7 +#define opc_invokeignored_static_quick 248 + +#define opc_throw_illegalaccess 249 // 0xf9 +#define opc_throw_noclassdef 250 + +#define opc_fill_cache 251 +#define opc_flush_cache 252 +#define opc_array_check 253 + + +#define opc_strict_enter 256 // 0x100 +#define opc_strict_exit 257 + +#define opc_fld4 258 // 0x102 +#define opc_fld 259 +#define opc_fst 260 +#define opc_dld8 261 +#define opc_dld 262 +#define opc_dst 263 + +#define opc_fppc_save 264 // 0x108 +#define opc_fppc_restore 265 +#define opc_fppc_single 266 +#define opc_fppc_double 267 +#define opc_fppc_extended 268 + +#define opc_strict_fprep 269 // 0x10d +#define opc_strict_fscdown 270 +#define opc_strict_fscup 271 +#define opc_strict_fsettle 272 +#define opc_strict_dprep 273 +#define opc_strict_dscdown 274 +#define opc_strict_dscup 275 +#define opc_strict_dsettle 276 + +#define opc_getstatic2 277 // 0x115 +#define opc_putstatic2 278 +#define opc_getfield2 279 +#define opc_putfield2 280 + +#define opc_iastore1 281 // 0x119 +#define opc_lastore1 282 + +#define opc_stateto0 283 // 0x11b +#define opc_stateto1 284 +#define opc_stateto2 285 +#define opc_stateto3 286 +#define opc_stateto4 287 + +#define opc_goto_st0 288 // 0x120 +#define opc_goto_st1 289 +#define opc_goto_st2 290 +#define opc_goto_st3 291 +#define opc_goto_st4 292 + +#define opc_sqrt 293 // 0x125 +#define opc_sin 294 +#define opc_cos 295 +#define opc_tan 296 +#define opc_atan2 297 +#define opc_atan 298 // 0x12a +#define opc_exp 299 +#define opc_log 300 +#define opc_floor 301 +#define opc_ceil 302 -#define opc_inv_head 323 // 0x143 -#define opc_inv_core 324 -#define opc_inv_metavm 325 - -#define opc_inv_vir_obj 326 -#define opc_inv_vir_varspace 327 -#define opc_invokevirtual_obj 328 - -#define opc_inv_spe_obj 329 -#define opc_inv_spe_varspace 330 +// for OPTIMIZE_INTERNAL_CODE +#define opc_fload_fld 303 // 0x12f +#define opc_dload_dld 304 +#define opc_faload_fld 305 +#define opc_daload_dld 306 + +#define opc_fst_fstore 307 +#define opc_dst_dstore 308 +#define opc_fst_fastore 309 +#define opc_dst_dastore 310 -#define opc_inv_stq_obj 331 -#define opc_inv_stq_varspace 332 +#define opc_istld 311 // 0x137 +#define opc_lstld 312 -#define NOPCODES 333 +#define NOPCODES 313 diff -aruN shujit-0.6.3/optimize.c shujit/optimize.c --- shujit-0.6.3/optimize.c Mon Aug 28 11:48:07 2000 +++ shujit/optimize.c Sun Sep 3 14:54:15 2000 @@ -46,7 +46,7 @@ #endif for (i = 0; i < pctableLen(cc); i++) { - pcentry *entry1, *entry2, *entry3; + pcentry *entry1, *entry2, *entry3, *entry4; #define GET_1_ENTRY \ if (!(entry1 = pctableNext(cc, entry))) break;\ if (pcentryBlockTop(entry1)) break @@ -57,7 +57,11 @@ #define GET_3_ENTRIES \ GET_2_ENTRIES; \ if (!(entry3 = pctableNext(cc, entry2))) break;\ - if (pcentryBlockTop(entry1)) break + if (pcentryBlockTop(entry3)) break +#define GET_4_ENTRIES \ + GET_3_ENTRIES; \ + if (!(entry4 = pctableNext(cc, entry3))) break;\ + if (pcentryBlockTop(entry4)) break entry = cc->pctable + i; @@ -77,27 +81,89 @@ *entry = *entry1; // copy opc_flush_cache pctableNDelete(cc, i + 1, 2); } + else if ((pcentryState(entry) == 0) && + (entry1->opcode == opc_fill_cache) && (entry2->opcode == opc_lstore)) { +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" boff:0x%x(%d)\n", entry->byteoff, entry->byteoff); + printf(" dst,fill_cache,dstore %d found.\n", entry2->operand); + fflush(stdout); + } +#endif + entry->opcode = opc_dst_dstore; + entry->operand = entry2->operand; + pctableNDelete(cc, i + 1, 2); + } +#ifndef METAVM + else if ((pcentryState(entry) == 0) && + (entry1->opcode == opc_fill_cache) && + (entry2->opcode == opc_lastore)) { +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" boff:0x%x(%d)\n", entry->byteoff, entry->byteoff); + printf(" dst,fill_cache,dastore found.\n"); + fflush(stdout); + } +#endif + entry->opcode = opc_dst_dastore; + pctableNDelete(cc, i + 1, 2); + } +#endif // !METAVM break; -#if 0 // single-precision operations need store-reload - // for the precise floating-point semantics case opc_fst: - // combine FPU store and load instructions - GET_2_ENTRIES; - if ((pcentryState(entry) == 0) && - (entry1->opcode == opc_flush_cache) && (entry2->opcode == opc_fld)) { + GET_1_ENTRY; + if ((pcentryState(entry) == 0) && (entry1->opcode == opc_istore)) { #ifdef COMPILE_DEBUG if (compile_debug) { printf(" boff:0x%x(%d)\n", entry->byteoff, entry->byteoff); - printf(" fst,flush_cache,fld found.\n"); + printf(" fst,fstore %d found.\n", entry1->operand); fflush(stdout); } #endif - *entry = *entry1; // copy opc_flush_cache - pctableNDelete(cc, i + 1, 2); + entry->opcode = opc_fst_fstore; + entry->operand = entry1->operand; + pctableDelete(cc, i + 1); + } + else { +#if 0 // single-precision operations need store-reload + // for the precise floating-point semantics + + GET_2_ENTRIES; + // combine FPU store and load instructions + if ((pcentryState(entry) == 0) && + (entry1->opcode == opc_flush_cache) && + (entry2->opcode == opc_fld)) { +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" boff:0x%x(%d)\n", entry->byteoff, entry->byteoff); + printf(" fst,flush_cache,fld found.\n"); + fflush(stdout); + } +#endif + *entry = *entry1; // copy opc_flush_cache + pctableNDelete(cc, i + 1, 2); + } + else { +#endif // if 0 + GET_4_ENTRIES; + if ((pcentryState(entry) == 0) && (entry1->opcode == opc_iastore1)) { +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" boff:0x%x(%d)\n", entry->byteoff, entry->byteoff); + printf(" fst,...,iastore found.\n"); + fflush(stdout); + } +#endif + entry->opcode = opc_fst_fastore; + entry->operand = entry4->operand; + pctableNDelete(cc, i + 1, 3); + } +#if 0 + } +#endif // 0 } break; -#endif case opc_iload: // load a float value to a FPU register directly @@ -110,8 +176,8 @@ fflush(stdout); } #endif - *entry1 = *entry; entry1->opcode = opc_fload_fld; + entry1->operand = entry->operand; entry->opcode = opc_flush_cache; @@ -130,8 +196,8 @@ fflush(stdout); } #endif - *entry1 = *entry; entry1->opcode = opc_dload_dld; + entry1->operand = entry->operand; entry->opcode = opc_flush_cache; @@ -172,6 +238,38 @@ #endif entry->opcode = opc_lstld; pctableDelete(cc, i + 1); + } + break; + + case opc_iaload: + GET_2_ENTRIES; + if ((entry1->opcode == opc_flush_cache) && (entry2->opcode == opc_fld)) { +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" boff:0x%x(%d)\n", entry->byteoff, entry->byteoff); + printf(" faload,flush_cache,fld found.\n", + entry->operand, entry1->operand); + fflush(stdout); + } +#endif + entry->opcode = opc_faload_fld; + pctableNDelete(cc, i + 1, 2); + } + break; + + case opc_laload: + GET_2_ENTRIES; + if ((entry1->opcode == opc_flush_cache) && (entry2->opcode == opc_dld)) { +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" boff:0x%x(%d)\n", entry->byteoff, entry->byteoff); + printf(" daload,flush_cache,dld found.\n", + entry->operand, entry1->operand); + fflush(stdout); + } +#endif + entry->opcode = opc_daload_dld; + pctableNDelete(cc, i + 1, 2); } break; } diff -aruN shujit-0.6.3/signal.c shujit/signal.c --- shujit-0.6.3/signal.c Sun Aug 20 19:45:00 2000 +++ shujit/signal.c Sun Sep 3 15:51:25 2000 @@ -165,6 +165,7 @@ # ifdef SEARCH_SIGCONTEXT uint32_t *ebp; # endif // SEARCH_SIGCONTEXT + ExecEnv *ee = EE(); SIGCONTEXT *sc = NULL; struct methodblock *mb; CodeInfo *codeinfo; @@ -228,7 +229,7 @@ #if defined(EXC_BY_SIGNAL) || defined(GET_SIGCONTEXT) if ((sig != SIGSEGV) && (sig != SIGFPE)) return FALSE; - mb = EE()->current_frame->current_method; + mb = ee->current_frame->current_method; if (!mb) return FALSE; #if defined(RUNTIME_DEBUG) || defined(COMPILE_DEBUG) printf("method(0x%x)", (int)mb); fflush(stdout); @@ -297,9 +298,11 @@ #ifdef NULLEXC_BY_SIGNAL if (sig == SIGSEGV) { - // NullPointerException occurred - SignalError(NULL, JAVAPKG "NullPointerException", 0); + if (!exceptionOccurred(ee)) { + // NullPointerException occurred + SignalError(NULL, JAVAPKG "NullPointerException", 0); // set ee->exception.exc, exception object + } } #endif #if defined(NULLEXC_BY_SIGNAL) && defined(ARITHEXC_BY_SIGNAL) diff -aruN shujit-0.6.3/txt/benchmark-PJ2X3 shujit/txt/benchmark-PJ2X3 --- shujit-0.6.3/txt/benchmark-PJ2X3 Tue Aug 29 20:47:26 2000 +++ shujit/txt/benchmark-PJ2X3 Sun Sep 3 19:13:27 2000 @@ -3,21 +3,26 @@ [TYA 付属のもの] - interp. TYA17 Inp1213 000423 000429 000822 -Sieve 120 589 1100 622 634 627 + interp. TYA17v2 Inp1215 000423 000429 0.6.4 +Sieve 125 586 1096 622 634 629 [Linpack Benchmark -- Java Version] -interpreter 2.297 0.3 +interpreter 2.393 0.29 shuJIT-000423 7.007 0.1 shuJIT-000429 7.803 0.09 shuJIT-000706 7.893 0.09 shuJIT-000816 9.035 0.08 shuJIT-000822 9.035 0.08 +shuJIT-000901 11.257 0.06 +shuJIT-0.6.4 13.205 0.05 TYA-1.7 11.444 0.06 OpenJIT-1.1.10 12.956 0.05 -Inprise-1.2.13 9.81 0.07 +OpenJIT-1.1.13 13.464 0.05 +OpenJIT-1.1.14 10.899 0.06 +Inprise-1.2.15 11.257 0.06 +Inprise-1.2.15 11.638 0.06 JAVA_COMPILER_THRESHOLD = 0 sunwjit 2.229 0.31 ??? @@ -50,17 +55,17 @@ Dialog 84 82 83 96 85 150 119 CM3 980 952 981 984 960 1048 979 - 000816 000822 000827 0.6.3 -Sieve 2007 1996 1997 1994 -Loop 3348 3346 3348 3337 -Logic 4401 4912 4818 5935 -String 1844 1867 1879 1855 -Float 2024 1920 1822 1829 -Method 1508 1672 1737 1752 -Graphics 346 343 392 323 -Image 513 518 506 526 -Dialog 126 121 127 114 -CM3 1157 1173 1191 1183 + 000816 000822 000827 0.6.3 000829 000901 0.6.4 +Sieve 2007 1996 1997 1994 1990 1999 1992 +Loop 3348 3346 3348 3337 3350 3351 3347 +Logic 4401 4912↑ 4818 5935↑ 5950 6879(?) 5950(?) +String 1844 1867 1879 1855 1943↑ 2487(?) 2450(?) +Float 2024 1920 1822 1829 1831 2079↑ 2448↑ +Method 1508 1672↑ 1737 1752 1732 1736 1827↑ +Graphics 346 343 392 323 324 312 319 +Image 513 518 506 526 517 524 529 +Dialog 126 121 127 114 120 129 127 +CM3 1157 1173 1191 1183 1193 1272 1281 TYA 1.7v2 OpenJIT 1.1.13 Sieve 1911 3231 diff -aruN shujit-0.6.3/txt/memo shujit/txt/memo --- shujit-0.6.3/txt/memo Tue Aug 29 17:47:08 2000 +++ shujit/txt/memo Sun Sep 3 17:37:19 2000 @@ -27,6 +27,12 @@ - invokeignored_quick への書き換え規則。 最適化 + - スタック上の要素の性質 (例: 配列のサイズ) を trace し、 + 省ける各種チェック (例: 添字の範囲) を省く。仮想スタックライブラリを用意。 + - 内部命令 direct_invoke 相当の処理を、 + compileAndInvokeMethod() (invoker.c) で行う。 + - 内部命令 exc_handler のコードを methodtail の前からどこかへ移し、 + メソッド末尾の return ではジャンプを不要にする。 - メソッド呼び出しから戻った後の、例外の有無チェックを省く。 - インライン展開。 コンパイル中に、そのメソッドが呼ぶメソッドを途中までコンパイル、 @@ -40,8 +46,6 @@ fadd -> ロード, 加算, ストア (前後のストア, ロードを相殺できる) - 浮動小数点数を FPU のレジスタに載せたままにしておく。 JVM のレジスタに載せない。 - - スタック上の要素の性質 (例: 配列のサイズ) を trace し、 - 省ける各種チェック (例: 添字の範囲) を省く。仮想スタックライブラリを用意。 - stack 上の倍精度浮動小数点数を 8バイト境界に align する。 - VolanoMark を試す。 - CM3 に対する compiled code を見る。 @@ -52,14 +56,11 @@ JavaFrame のメンバ ostack と optop が同じ領域にあることを 仮定したコードがある。 JavaFrame の存在を仮定したコードが多い。 - - Object# の呼び出しを削除する。 - invokeignored_quick への recode 条件を調べる。 - invoke(Synchronized)JavaMethod() の代替を用意、処理を軽減する。 排他制御が必要。-> thread library を使ってしまう。 - native 命令列の書き換え。 invoke -> invokevirtual*object* 相当など。 obj_array_methodtable() ではなく obj_methodtable() が使える。 - - JavaFrame の作成を省く。 - vars[0..] をレジスタにのせてキャッシュする。 - lookupswitch 命令の検索アルゴリズムを改良する。 - Address Generation Interlock(AGI) (MMX 本 pp.95,99) を避ける。 @@ -71,6 +72,7 @@ Done - JMP 命令の、E9 (引数 4 バイト) から EB (引数 1 バイト) への書き換え + - JavaFrame の作成を省く。 - メソッド呼び出しの overhead 削減。 スタック積み直しを削減。 native method を呼ぶ際に restack を減らせる? @@ -78,6 +80,8 @@ - invokevirtual を invokespecial に変換。 - exception_handler の処理をメソッドごとにコピーしないようにする。 - ループの先頭を 16バイト境界に align。 + - Object# の呼び出しを削除する。 + invokeignored_quick への recode 条件を調べる。 - java.lang.Math#exp を inlining しないように戻す。 x86 FPU と JDK 1.2 のインタプリタで結果が微妙に異なるので。 - クラスが存在しなかった場合に、JIT コンパイルが失敗するのではなく、