diff -aruN shujit-0.6.6/ChangeLog shujit/ChangeLog --- shujit-0.6.6/ChangeLog Wed Sep 13 19:35:22 2000 +++ shujit/ChangeLog Tue Sep 19 21:31:01 2000 @@ -1,5 +1,53 @@ $Id$ +[20000919] + +compiled code が compiled code を呼ぶ際も +きちんと StackOverflowError が発生するようにした。 +マクロ CAUSE_STACKOVERFLOW (compiler.h) で +このチェックを行うか否かを制御できる。 +(code.c, signal.c, compiler.h) + +クラスの初期化時に、final クラスのメソッドに final 属性を付けるようにした。 +(compiler.c) + +末尾再帰のジャンプへの変換の適用範囲を広げた。 +static bind 可能なメソッド呼び出しの直後が *return 命令ではなくて +*return 命令への goto である場合にも適用できるようにした。 +(see [20000913]) +(compile.c) + +try 節中にある再帰呼び出しは、return 後に catch 節が実行され得るから +末尾再帰足り得ないのに、末尾再帰として扱ってしまっていた。修整。 +このために、例外が発生していない状態 (ee->exception.exc == NULL) で +searchCatchFrame() を呼んだ場合、例外の種類に関係なく PC だけ見て +結果を返すようにした。 +[Thanks 前田さん ] +(compile.c, runtime.c) + +0.6.7 リリース。 + +[20000918] + +これまで、resolve (ResolveClassConstantFromClass2()) の失敗は +すべて NoClassDefFoundError を throw するコードに変換していたところ、 +本当に NoClassDefFoundError が throw された際にだけ、そうするようにした。 +Kaffe 1.0.5 の regression テストのひとつ、CLTestConc にて問題が発覚。 +resolve 中に Thread#stop() で止められた際にも停止せずに、 +NoClassDefFoundError を throw してしまっていた。 +(compile.c, compiler.c, compiler.h) + +配列の境界チェックの方法を変更。これまで + %edi = length, check index < 0, check index >= length +と処理してきたところ、 +index - length 後のキャリーフラグを見て一度で判断するようにした。 +Linpack benchmark: 13.733 -> 14.306 と向上 (Pentium II / 333 MHz)。 +[Thanks 石崎さん ] +(code.c) + +配列 jumpret_table を排した。 +(compile.c, gentable.rb) + [20000913] 末尾再帰を、メソッド先頭へのジャンプに変換する最適化を実装。 @@ -415,12 +463,12 @@ ResolveClass() が InitializeForCompiler() (JDK 内関数) を呼ぶ前に methodblock->info が要求されて SIGSEGV が発生していた。 JPython 1.1 で発覚。 -[Thanks 高橋秀明さん for a bug report] +[Thanks 高橋秀明さん for a bug report] (runtime.c, compiler.c, compiler.h) lookupswitch 命令で npairs が 0 の場合を想定していなかったのを修整。 JPython 1.1 で発覚。 -[Thanks 高橋秀明さん for a bug report] +[Thanks 高橋秀明さん for a bug report] (code.c) 浮動小数点数のストア、ロードを除去する最適化を、 @@ -528,7 +576,7 @@ processAnOpcode() (in compile.c) での wide 命令群の扱いに問題があった。 wide prefix が付いた命令を内部命令に変換していなかった。修整。 -[Thanks to 志村さん ] +[Thanks 志村さん ] (compile.c) [20000415] @@ -537,7 +585,7 @@ これまでは関数名の文字列を constants.c 中の表 (配列) に保持していたところ、 はじめから表には関数のアドレスを入れておくようにした。 これに伴い、initFunctionSymbols() (in compile.c) が不要になった。 -[Thanks to 丸山さん ] +[Thanks 丸山さん ] (gentable.rb, compile.c, compiler.c) [20000330] @@ -590,7 +638,7 @@ examineSigcontextNestCount() を JIT のシグナルハンドラに設定し、 int $0x3 で割り込みを発生させ、その関数内で到達法を求める。 native threads と green threads で探し方が異なる。 -[Thanks to OpenJIT team ] +[Thanks OpenJIT team ] (signal.c, compiler.h) スタック上で目的の sigcontext を探す際、これまでは @@ -642,7 +690,7 @@ sigcontext の探し方を変更。単にスタックをなめていたところ、 ベースポインタをたぐって探すようにした。 ebp + 3 が sigcontext_t * 型かどうかで判定する。 -[Thanks to OpenJIT team ] +[Thanks OpenJIT team ] glibc 2.1.2 の LinuxThreads は sigcontext を 2つスタックに置いてしまい、 ひとつめに見付かった sigcontext を変更しても、 シグナルハンドラから戻った際に反映されない。 @@ -653,7 +701,7 @@ 単にジャンプしていたところ、 Linux では %ebp を設定して return するように、 FreeBSD では sigreturn(sigcontext_t *) を使うようにした。 -[Thanks to OpenJIT team ] +[Thanks OpenJIT team ] FreeBSD で行っていたシグナルの unmask (sigprocmask(SIG_UNBLOCK, ...)) は 不要になった。 (compiler.c) @@ -1899,7 +1947,7 @@ for subdir in ; do ... と in の後が空だと syntax error になる問題に対処。 bash 1.14.7 では error にならなかった。 -[Thanks 高橋秀明さん for a bug report] +[Thanks 高橋秀明さん for a bug report] (GNUmakefile) [19990109] @@ -1909,7 +1957,7 @@ これまでは 0x0f, 0x0f で区切ってきたのだが、 これが AMD 3D Now! 命令の prefix として使われ、 3D Now! 命令に対応した GNU binutils が出てきたため。 -[Thanks 高橋秀明さん for a bug report] +[Thanks 高橋秀明さん for a bug report] (code.h, gentable.rb) [19990107] @@ -1993,8 +2041,8 @@ egcs 1.0.3 の生成するコードでは問題がなかった。 gcc 2.7.X で code.o を生成する際は、code.s を ruby スクリプト (postcmpl.rb) で修整するようにした。 -[Thanks 高橋秀明さん - and Justin Wells さん for bug reports] +[Thanks 高橋秀明さん + and Justin Wells さん for bug reports] (postcmpl.rb, GNUmakefile) [19981228] diff -aruN shujit-0.6.6/code.c shujit/code.c --- shujit-0.6.6/code.c Wed Sep 13 21:19:10 2000 +++ shujit/code.c Tue Sep 19 19:58:31 2000 @@ -1129,14 +1129,9 @@ OBJ_LENGTH(HANDLE, %edi); /* edi = obj_length(handle) */\ ARRAY_CHECK_DEBUG2(%edi);\ \ - /* check if index < 0 */\ - asm("testl " #INDEX "," #INDEX "\n\t"\ - "jl " LABEL "_arychk_exc");\ - /* check if index >= length */\ + /* check if (index < 0 || index >= length) */\ asm("cmpl %edi," #INDEX "\n\t"\ - "jl " LABEL "_arychk_done");\ - \ - asm(LABEL "_arychk_exc:");\ + "jc " LABEL "_arychk_done");\ SIGNAL_ERROR0(EXCID_ArrayIndexOutOfBoundsException);\ asm(LABEL "_arychk_done:") /* label */ #else @@ -3529,7 +3524,7 @@ CODE(opc_return, return, STANY, STATE_AFTER_RETURN, OPC_NONE) { VALUE_DEBUG(%edx); VALUE_DEBUG(%ecx); - asm("jmp " STR(ADDR_FIN)); + asm(".byte 0xe9\n\t.long " STR(CONST)); // jmp } @@ -4011,9 +4006,17 @@ #define INVOKE_CORE_ARG_SIZE "20" #endif // RUNTIME_DEBUG +#ifdef CAUSE_STACKOVERFLOW +# define CHECK_STACK_MARGIN \ + asm("movl -" STR(STACKOVERFLOW_MARGIN) "(%ebp),%ecx") +#else +# define CHECK_STACK_MARGIN +#endif // CAUSE_STACKOVERFLOW + // const: retsize, args_size #define INVOKE_CORE(VOP, CORE_TYPE) \ - CODE(opc_##VOP, VOP, STANY, ST0, OPC_NONE) {\ + CODE(opc_##VOP, VOP, STANY, ST0, OPC_SIGNAL) {\ + /* CAUSE_STACKOVERFLOW needs OPC_SIGNAL */\ asm(".globl " #VOP "\n\t.type " #VOP ",@function");\ asm(#VOP ":");\ \ @@ -4029,12 +4032,12 @@ asm("pushl %edi"); /* push var. base */\ asm("movl %0,%%edi" : : "m" (ee)); /* edi = ee */\ asm("pushl %edi"); /* push ee */\ - asm("pushl %ecx\n\t" /* push args_size */\ - "pushl %eax\n\t" /* push method */\ - "pushl %edx"); /* push obj */\ - \ + asm("pushl %ecx"); /* push args_size */\ + CHECK_STACK_MARGIN;\ asm("movl " EE_CURRENTFRAME(%edi) ",%edi");\ - /* edi = ee->current_frame */\ + /* edi = ee->current_frame */\ + asm("pushl %eax\n\t" /* push method */\ + "pushl %edx"); /* push obj */\ \ INVCORE_##CORE_TYPE;\ \ @@ -4056,7 +4059,7 @@ asm("movl %0,%%edi" : : "m" (ee)); /* edi = ee */\ EE_EXCEPTIONKIND_EAX(%edi);\ asm("testl %eax,%eax\n\t"\ - "jnz " STR(ADDR_EXC));\ + ".short 0x850f\n\t.long " STR(ADDR_EXC)); /* jnz */\ } INVOKE_CORE(invoke_core, INVOKE); @@ -4279,14 +4282,14 @@ ".short 0xa5f3\n\t" // "rep movsl (%esi),(%edi)\n\t" "leal (%esp,%eax,4),%esp\n\t" // esp += 4 * args_size "movl %edx,%esi"); // restore esi - asm(".byte 0xe9\n\t.long " STR(CONST)); + asm(".byte 0xe9\n\t.long " STR(CONST)); // jmp } CODE(opc_invoke_recursive_1, invoke_recursive_1, ST0, ST0, OPC_NONE) { asm("movl (%esp),%eax\n\t" "addl $4,%esp\n\t" "movl %eax,(%esi)\n\t" - ".byte 0xe9\n\t.long " STR(CONST)); + ".byte 0xe9\n\t.long " STR(CONST)); // jmp } CODE(opc_invoke_recursive_2, invoke_recursive_2, ST0, ST0, OPC_NONE) { @@ -4295,7 +4298,7 @@ "addl $8,%esp\n\t" "movl %eax,-4(%esi)\n\t" "movl %edi,(%esi)\n\t" - ".byte 0xe9\n\t.long " STR(CONST)); + ".byte 0xe9\n\t.long " STR(CONST)); // jmp } CODE(opc_invoke_recursive_3, invoke_recursive_3, ST0, ST0, OPC_NONE) { @@ -4306,7 +4309,7 @@ "movl %eax,-8(%esi)\n\t" "movl %edi,-4(%esi)\n\t" "movl %ecx,(%esi)\n\t" - ".byte 0xe9\n\t.long " STR(CONST)); + ".byte 0xe9\n\t.long " STR(CONST)); // jmp } #endif // ELIMINATE_TAIL_RECURSION @@ -4716,7 +4719,8 @@ }\ \ bytepcoff = BYTEPCOFF;\ - asm("jmp " STR(ADDR_EXC)) + asm(".byte 0xe9\n\t.long " STR(ADDR_EXC)) + // jmp CODE(opc_athrow, athrow, ST0, ST1, OPC_SIGNAL) { asm("popl %edx"); // now state 1 diff -aruN shujit-0.6.6/code.h shujit/code.h --- shujit-0.6.6/code.h Tue Sep 12 14:13:28 2000 +++ shujit/code.h Mon Sep 18 18:38:46 2000 @@ -165,7 +165,7 @@ #define SIGNAL_ERROR_JUMP() \ bytepcoff = BYTEPCOFF;\ - asm("jmp " STR(ADDR_EXC)) + asm(".byte 0xe9\n\t.long " STR(ADDR_EXC)) #define SIGNAL_ERROR_CORE(EXCID) \ asm("movb $" #EXCID ",%al");\ diff -aruN shujit-0.6.6/compile.c shujit/compile.c --- shujit-0.6.6/compile.c Wed Sep 13 20:43:06 2000 +++ shujit/compile.c Tue Sep 19 18:49:11 2000 @@ -358,8 +358,6 @@ fflush(stdout); #endif - exceptionClear(cc->ee); - #ifdef DIRECT_INVOCATION mb->fb.access &= ~ACC_MACHINE_COMPILED; #endif @@ -642,9 +640,21 @@ if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), operand, cc->ee, (1 << CONSTANT_Methodref) | (1 << CONSTANT_InterfaceMethodref), FALSE)) { - exceptionClear(cc->ee); - processAnOpcode(cc, opc_throw_noclassdef, byteoff); - goto makepc_invoke_done; + JHandle *exc; +#ifdef COMPILE_DEBUG + printf("resolution failed (cp index: %d).\n", operand); + fflush(stdout); +#endif + sysAssert(exceptionOccurred(cc->ee)); + exc = cc->ee->exception.exc; + sysAssert(exc != NULL); + if (obj_classblock(exc) == classJavaLangNoClassDefFoundError) { + exceptionClear(cc->ee); + processAnOpcode(cc, opc_throw_noclassdef, byteoff); + goto makepc_invoke_done; + } + + return 1; } } @@ -809,34 +819,60 @@ struct methodblock *method = constant_pool[operand].mb; if (mb == method) { // recursive call - int next_opcode = *(methodcode + byteoff + byteinc); + int next_bytepc = byteoff + byteinc; + int next_opcode = *(methodcode + next_bytepc); + while ((next_opcode == opc_goto) || (next_opcode == opc_goto_w)) { + if (next_opcode == opc_goto) { + next_bytepc += GET_INT16(methodcode + next_bytepc + 1); + } + else { + next_bytepc += GET_INT32(methodcode + next_bytepc + 1); + } + next_opcode = *(methodcode + next_bytepc); + } + if ((opc_ireturn <= next_opcode) && (next_opcode <= opc_return)) { // next insn. is return - // tail recursion - int reccall_opcode; + if (searchCatchFrame(cc->ee, mb, byteoff +# ifdef RUNTIME_DEBUG + , COMPILE_DEBUG +# endif + ) == NULL) { + // tail recursion + int reccall_opcode; # ifdef COMPILE_DEBUG - if (compile_debug) { - printf("tail recursion.\n"); - printf(" args_size: %d\n", method->args_size); - fflush(stdout); - } + if (compile_debug) { + printf("tail recursion.\n"); + printf(" args_size: %d\n", method->args_size); + fflush(stdout); + } # endif - switch (method->args_size) { - case 1: - reccall_opcode = opc_invoke_recursive_1; break; - case 2: - reccall_opcode = opc_invoke_recursive_2; break; - case 3: - reccall_opcode = opc_invoke_recursive_3; break; - default: - reccall_opcode = opc_invoke_recursive; break; - } + switch (method->args_size) { + case 1: + reccall_opcode = opc_invoke_recursive_1; break; + case 2: + reccall_opcode = opc_invoke_recursive_2; break; + case 3: + reccall_opcode = opc_invoke_recursive_3; break; + default: + reccall_opcode = opc_invoke_recursive; break; + } - processAnOpcode(cc, opc_stateto0, byteoff); - processAnOpcode(cc, reccall_opcode, byteoff); + processAnOpcode(cc, opc_stateto0, byteoff); + processAnOpcode(cc, reccall_opcode, byteoff); - goto makepc_invoke_done; - } + goto makepc_invoke_done; + } // if (searchCatchFrame(...)) +# ifdef COMPILE_DEBUG + else { + if (compile_debug) { + printf("not tail recursion:\n" + " calling insn is in a catch frame.\n"); + fflush(stdout); + } + } +# endif + } // if (opc_ireturn <= next_opcode <= opc_return) } } #endif // ELIMINATE_TAIL_RECURSION @@ -1006,7 +1042,9 @@ // go through default: - byteoff += processAnOpcode(cc, opcode, byteoff); + byteinc = processAnOpcode(cc, opcode, byteoff); + if (byteinc < 0) return 1; + byteoff += byteinc; break; } @@ -1070,7 +1108,8 @@ /* - * returns: increment count for bytecode PC. + * returns: increment count for bytecode PC, + * minus value if an exception occurred. */ static int processAnOpcode(CompilerContext *cc, int opcode, int byteoff) { struct methodblock *mb = cc->mb; @@ -1297,25 +1336,31 @@ if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) {\ if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), operand,\ cc->ee, 1 << CONSTANT_Fieldref, FALSE)) {\ - exceptionClear(cc->ee);\ - code_opcode = opc_throw_noclassdef;\ + JHandle *exc;\ + sysAssert(exceptionOccurred(cc->ee));\ + exc = cc->ee->exception.exc;\ + sysAssert(exc != NULL);\ + if (obj_classblock(exc) == classJavaLangNoClassDefFoundError) {\ + exceptionClear(cc->ee);\ + code_opcode = opc_throw_noclassdef;\ + break;\ + }\ + return -1;\ }\ }\ \ - if (code_opcode != opc_throw_noclassdef) {\ - fb = constant_pool[operand].fb;\ - sig = fieldsig(fb);\ - if ((OPT_SETQ(OPT_CODEDB)) ||\ + fb = constant_pool[operand].fb;\ + sig = fieldsig(fb);\ + if ((OPT_SETQ(OPT_CODEDB)) ||\ !CB_INITIALIZED(fieldclass(fb))) {/* not quick instructions */\ - code_opcode =\ - ((sig[0] == SIGNATURE_LONG) || (sig[0] == SIGNATURE_DOUBLE)) ?\ - opc_##vop##2 : opc_##vop;\ - }\ - else { /* quick instructions */\ - code_opcode =\ - ((sig[0] == SIGNATURE_LONG) || (sig[0] == SIGNATURE_DOUBLE)) ?\ - opc_##vop##2_quick : opc_##vop##_quick;\ - }\ + code_opcode =\ + ((sig[0] == SIGNATURE_LONG) || (sig[0] == SIGNATURE_DOUBLE)) ?\ + opc_##vop##2 : opc_##vop;\ + }\ + else { /* quick instructions */\ + code_opcode =\ + ((sig[0] == SIGNATURE_LONG) || (sig[0] == SIGNATURE_DOUBLE)) ?\ + opc_##vop##2_quick : opc_##vop##_quick;\ }\ } @@ -1337,18 +1382,24 @@ if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) {\ if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), operand,\ cc->ee, 1 << CONSTANT_Fieldref, FALSE)) {\ - exceptionClear(cc->ee);\ - code_opcode = opc_throw_noclassdef;\ + JHandle *exc;\ + sysAssert(exceptionOccurred(cc->ee));\ + exc = cc->ee->exception.exc;\ + sysAssert(exc != NULL);\ + if (obj_classblock(exc) == classJavaLangNoClassDefFoundError) {\ + exceptionClear(cc->ee);\ + code_opcode = opc_throw_noclassdef;\ + break;\ + }\ + return -1;\ }\ }\ \ - if (code_opcode != opc_throw_noclassdef) {\ - fb = constant_pool[operand].fb;\ - sig = fieldsig(fb);\ - code_opcode =\ - ((sig[0] == SIGNATURE_LONG) || (sig[0] == SIGNATURE_DOUBLE)) ?\ + fb = constant_pool[operand].fb;\ + sig = fieldsig(fb);\ + code_opcode =\ + ((sig[0] == SIGNATURE_LONG) || (sig[0] == SIGNATURE_DOUBLE)) ?\ opc_##vop##2 : opc_##vop;\ - }\ } case opc_getfield: @@ -1421,8 +1472,23 @@ if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), operand, cc->ee, 1 << CONSTANT_Class, FALSE)) { - exceptionClear(cc->ee); - code_opcode = opc_throw_noclassdef; + JHandle *exc; + sysAssert(exceptionOccurred(cc->ee)); + exc = cc->ee->exception.exc; + sysAssert(exc != NULL); +#ifdef COMPILE_DEBUG + fprintf(stderr, "%s\n", cbName(exc->methods->classdescriptor)); +# if JDK_VER >= 12 + printStackTrace(cc->ee, 100, NULL); +# endif + fflush(stderr); +#endif // COMPILE_DEBUG + if (obj_classblock(exc) == classJavaLangNoClassDefFoundError) { + exceptionClear(cc->ee); + code_opcode = opc_throw_noclassdef; + break; + } + return -1; } } @@ -1955,7 +2021,7 @@ #ifdef ALIGN_JUMP_TARGET // align a jump target to 16-byte boundary #define ALIGN_BOUND 16 -#define ALIGN_THRESHOLD 4 +#define JUMP_THRESHOLD 4 // have to >= 2 if (pcentryLoopTop(pctable)) { int pad = @@ -1970,7 +2036,7 @@ #endif sysAssert((0 <= pad) && (pad < ALIGN_BOUND)); - if (pad >= ALIGN_THRESHOLD) { + if (pad >= JUMP_THRESHOLD) { char code_pad[2]; pad -= 2; @@ -1982,9 +2048,17 @@ } { - static unsigned char nops[] = - {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90}; + static unsigned char nops[] = { +#if ALIGN_BOUND > 8 + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +#if ALIGN_BOUND > 16 + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +#if ALIGN_BOUND > 24 + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +#endif +#endif +#endif + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90}; writeToBuffer(cc, nops, pad); nativeoff += pad; } @@ -3315,42 +3389,37 @@ } // resolve jump to finishing of method - i = 0; - if (jumpret_table[opcode][state][i] > 0) { + if (opcode == opc_return) { unsigned int fin_off = info->finish_return_nativeoff; unsigned int arg_off; int32_t relative_off; unsigned char *p; - while (jumpret_table[opcode][state][i] > 0) { - arg_off = entry->nativeoff + jumpret_table[opcode][state][i]; - relative_off = fin_off - (arg_off + 4); - p = nativeCode + arg_off; + arg_off = entry->nativeoff + constant_table[opc_return][state][0]; + relative_off = fin_off - (arg_off + 4); + p = nativeCode + arg_off; #ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" res. jump to fin.of method at 0x%x(%d) + %d: 0x%x(%d)\n", + if (compile_debug) { + printf(" res. jump to fin.of method at 0x%x(%d) + %d: 0x%x(%d)\n", entry->nativeoff, entry->nativeoff, - jumpret_table[opcode][state][i], fin_off, fin_off); - fflush(stdout); - } + constant_table[opc_return][state][0], fin_off, fin_off); + fflush(stdout); + } #endif - memcpy(p, &relative_off, 4); + memcpy(p, &relative_off, 4); - // rewrite `0xe9 XX XX XX XX' to `0xeb XX' - { - char carg; - if (*(--p) == 0xe9) { - relative_off += 3; carg = (char)relative_off; + // rewrite `0xe9 XX XX XX XX' to `0xeb XX' + { + char carg; + if (*(--p) == 0xe9) { + relative_off += 3; carg = (char)relative_off; - if (relative_off == ((int32_t)carg)) { // -128 - 127 - p[0] = 0xeb; p[1] = carg; // 0xeb: jmp XX - p[4] = p[3] = p[2] = 0x90; // 0x90: nop - } + if (relative_off == ((int32_t)carg)) { // -128 - 127 + p[0] = 0xeb; p[1] = carg; // 0xeb: jmp XX + p[4] = p[3] = p[2] = 0x90; // 0x90: nop } } - - i++; } } diff -aruN shujit-0.6.6/compiler.c shujit/compiler.c --- shujit-0.6.6/compiler.c Wed Sep 13 19:46:47 2000 +++ shujit/compiler.c Tue Sep 19 02:46:21 2000 @@ -68,6 +68,8 @@ int db_page = -1; #endif // CODE_DB +ClassClass *classJavaLangNoClassDefFoundError; + struct bool_opt_entry { char *name; int num; }; struct bool_opt_entry bool_opt_entry[] = { {"quiet", OPT_QUIET}, @@ -283,10 +285,10 @@ // resolve some symbols #define RESOLVE_A_INVOKER(NAME) \ - if (!(sym_##NAME = (void *)symbolInSystemClassLoader(#NAME))) {\ - printf("FATAL: cannot resolve a symbol: %s\n", #NAME);\ - JVM_Exit(1);\ - } + if (!(sym_##NAME = (void *)symbolInSystemClassLoader(#NAME))) {\ + printf("FATAL: cannot resolve a symbol: " #NAME "\n");\ + JVM_Exit(1);\ + } RESOLVE_A_INVOKER(compileAndInvokeMethod); RESOLVE_A_INVOKER(invokeJITCompiledMethod); @@ -317,6 +319,17 @@ #endif + // find classes +#define FIND_A_CLASS(NAME) \ + if ((classJavaLang##NAME =\ + FindClass(ee, JAVAPKG #NAME, TRUE)) == NULL) {\ + printf("FATAL: cannot find a class: " #NAME "\n");\ + JVM_Exit(1);\ + } + + FIND_A_CLASS(NoClassDefFoundError); + + // initialize all classes already loaded if (!OPT_SETQ(OPT_DONTCMPLVMCLZ)) { ClassClass **clazzptr; @@ -570,6 +583,10 @@ // initialize mb->CompiledCodeInfo if (!(mb->CompiledCodeInfo)) if (!prepareCompiledCodeInfo(EE(), mb)) continue; + + // if the class is final, make the method final + if (cbAccess(cb) & ACC_FINAL) + mb->fb.access |= ACC_FINAL; if (access & ACC_NATIVE) continue; diff -aruN shujit-0.6.6/compiler.h shujit/compiler.h --- shujit-0.6.6/compiler.h Wed Sep 13 18:03:09 2000 +++ shujit/compiler.h Tue Sep 19 20:57:53 2000 @@ -83,6 +83,7 @@ #define DIRECT_INVOCATION #define EAGER_COMPILATION #define ELIMINATE_TAIL_RECURSION +#define CAUSE_STACKOVERFLOW #define GET_SIGCONTEXT #define NULLEXC_BY_SIGNAL #define ARITHEXC_BY_SIGNAL @@ -96,6 +97,14 @@ #undef IGNORE_DISABLE #undef NO_CHECK +#ifdef CAUSE_STACKOVERFLOW +# if JDK_VER >= 12 +# define STACKOVERFLOW_MARGIN 2100 +# else +# define STACKOVERFLOW_MARGIN 1452 +# endif +#endif + #if defined(NULLEXC_BY_SIGNAL) || defined(ARITHEXC_BY_SIGNAL) # define EXC_BY_SIGNAL #endif @@ -104,12 +113,8 @@ # undef EAGER_COMPILATION #endif -#if 0 -# ifdef RUNTIME_DEBUG -# undef NULLEXC_BY_SIGNAL -# undef ARITHEXC_BY_SIGNAL -# undef EXC_BY_SIGNAL -# endif +#ifndef NULLEXC_BY_SIGNAL +# undef CAUSE_STACKOVERFLOW #endif @@ -431,6 +436,8 @@ extern bool_t is_fpupc_double; // Is the FPU rounding precision double? + +extern ClassClass *classJavaLangNoClassDefFoundError; // in signal.c #if (defined(EXC_BY_SIGNAL) || defined(GET_SIGCONTEXT)) && defined(SEARCH_SIGCONTEXT) diff -aruN shujit-0.6.6/gentable.rb shujit/gentable.rb --- shujit-0.6.6/gentable.rb Wed Sep 13 20:42:09 2000 +++ shujit/gentable.rb Mon Sep 18 19:04:42 2000 @@ -294,28 +294,28 @@ # else # jump_table[opcode][init_state] = array # end - elsif /74 74/ # return instruction - i = 1 - i += 1 while elems[i] != '74' - off = elems[0].chop().hex() + i - 2 - code_addr -#print "return instruction: #{off}\n" - if init_state == STANY - array = jumpret_table[opcode][0]; - else - array = jumpret_table[opcode][init_state]; - end - if (array) - array << off - else - array = [off] - end - arysize = array.length() - jumpret_arysize = arysize if arysize > jumpret_arysize - if init_state == STANY - (0..(NSTATES - 1)).each {|i| jumpret_table[opcode][i] = array } - else - jumpret_table[opcode][init_state] = array - end +# elsif /74 74/ # return instruction +# i = 1 +# i += 1 while elems[i] != '74' +# off = elems[0].chop().hex() + i - 2 - code_addr +# #print "return instruction: #{off}\n" +# if init_state == STANY +# array = jumpret_table[opcode][0]; +# else +# array = jumpret_table[opcode][init_state]; +# end +# if (array) +# array << off +# else +# array = [off] +# end +# arysize = array.length() +# jumpret_arysize = arysize if arysize > jumpret_arysize +# if init_state == STANY +# (0..(NSTATES - 1)).each {|i| jumpret_table[opcode][i] = array } +# else +# jumpret_table[opcode][init_state] = array +# end end end @@ -383,8 +383,8 @@ outTableToC(f, 'jumpexc_table', jumpexc_table, jumpexc_arysize, max_jumpexc_off) # # jump_table[][NSTATE][] # outTableToC(f, 'jump_table', jump_table, jump_arysize, 255) - # jumpret_table[][NSTATE][] - outTableToC(f, 'jumpret_table', jumpret_table, jumpret_arysize, 255) +# # jumpret_table[][NSTATE][] +# outTableToC(f, 'jumpret_table', jumpret_table, jumpret_arysize, 255) end @@ -444,5 +444,5 @@ outTableToH(f, 'bytepc_table', bytepc_arysize, max_bytepc_off) outTableToH(f, 'jumpexc_table', jumpexc_arysize, max_jumpexc_off) # outTableToH(f, 'jump_table', jump_arysize, 255) - outTableToH(f, 'jumpret_table', jumpret_arysize, 255) +# outTableToH(f, 'jumpret_table', jumpret_arysize, 255) end diff -aruN shujit-0.6.6/invoker.c shujit/invoker.c --- shujit-0.6.6/invoker.c Wed Sep 13 22:03:28 2000 +++ shujit/invoker.c Tue Sep 19 18:27:40 2000 @@ -606,9 +606,15 @@ else if ((!strcmp(cbName(fieldclass(&mb->fb)), "java/lang/ClassLoader")) && (!strcmp(mb->fb.name, "getSystemClassLoader"))) runtime_debug = 1; + else if ((!strcmp(cbName(fieldclass(&mb->fb)), "Overflow")) + && (!strcmp(mb->fb.name, "recurse"))) + runtime_debug = 1; + else if ((!strcmp(cbName(fieldclass(&mb->fb)), "Test")) + && (!strcmp(mb->fb.name, "loop"))) + runtime_debug = 1; else if (!strcmp(mb->fb.name, "dtoa")) runtime_debug = 1; -#if 0 +#if 1 else if (!strcmp(mb->fb.name, "main")) runtime_debug = 1; else if (!strcmp(mb->fb.name, "start")) diff -aruN shujit-0.6.6/opcodes_internal.h shujit/opcodes_internal.h --- shujit-0.6.6/opcodes_internal.h Wed Sep 13 19:07:30 2000 +++ shujit/opcodes_internal.h Mon Sep 18 16:36:19 2000 @@ -60,7 +60,7 @@ #define opc_invoke_recursive_3 253 -#define opc_fill_cache 256 +#define opc_fill_cache 256 // 0x100 #define opc_flush_cache 257 #define opc_array_check 258 diff -aruN shujit-0.6.6/runtime.c shujit/runtime.c --- shujit-0.6.6/runtime.c Sun Sep 10 23:38:17 2000 +++ shujit/runtime.c Tue Sep 19 18:47:36 2000 @@ -1111,6 +1111,10 @@ ClassClass *catchClazz = NULL; ClassClass *excClazz; + if (ee->exception.exc == NULL) { + found = 1; goto search_finish; + } + if (typeindex == 0) { // This catch frame accpets any type of exceptions. found = 1; goto search_finish; @@ -1176,7 +1180,7 @@ if (excClazz == catchClazz) { found = 1; goto search_finish; } - } + } // for (excClazz = ...) } // if (start_pc <= pc < end_pc) cf++; diff -aruN shujit-0.6.6/signal.c shujit/signal.c --- shujit-0.6.6/signal.c Tue Sep 5 16:02:13 2000 +++ shujit/signal.c Tue Sep 19 04:07:55 2000 @@ -304,12 +304,20 @@ #ifdef NULLEXC_BY_SIGNAL if (sig == SIGSEGV) { if (!exceptionOccurred(ee)) { - // NullPointerException occurred - SignalError(NULL, JAVAPKG "NullPointerException", 0); - // set ee->exception.exc, exception object +# ifdef CAUSE_STACKOVERFLOW + unsigned char *pc = (unsigned char *)sc->SC_EIP; + if ((pc[0] == 0x8b) && (pc[1] == 0x8d)) { + // movl -STACKOVERFLOW_MARGIN(%ebp),%ecx + SignalError(NULL, JAVAPKG "StackOverflowError", 0); + } + else +# endif // CAUSE_STACKOVERFLOW + { + SignalError(NULL, JAVAPKG "NullPointerException", 0); + } } } -#endif +#endif //NULLEXC_BY_SIGNAL #if defined(NULLEXC_BY_SIGNAL) && defined(ARITHEXC_BY_SIGNAL) else #endif diff -aruN shujit-0.6.6/txt/SPECjvm98 shujit/txt/SPECjvm98 --- shujit-0.6.6/txt/SPECjvm98 Wed Sep 13 21:56:03 2000 +++ shujit/txt/SPECjvm98 Tue Sep 19 20:53:08 2000 @@ -10,23 +10,23 @@ * TYA 1.7v2 * interpreter - 0.6.6 0.6.5 0.6.4 0.6.3 -_201_compress 140.161 143.152 146.926 147.786 -_202_jess 56.649 57.459 57.876 58.563 -_209_db 125.032 129.824 137.821 129.598 -_213_javac 121.552 124.729 126.728 126.206 -_222_mpegaudio 107.761 110.923 116.418 125.457 -_227_mtrt 84.81 85.534 87.007 89.999 -_228_jack 66.717 69.653 68.524 72.625 + 0.6.7 000918 0.6.6 0.6.5 0.6.4 0.6.3 +_201_compress 134.974 139.301 140.161 143.152 146.926 147.786 +_202_jess 55.433 52.86 56.649 57.459 57.876 58.563 +_209_db 127.106 126.31 125.032 129.824 137.821 129.598 +_213_javac 123.595 122.246 121.552 124.729 126.728 126.206 +_222_mpegaudio 101.514 104.951 107.761 110.923 116.418 125.457 +_227_mtrt 87.968 85.485 84.81 85.534 87.007 89.999 +_228_jack 67.15 67.393 66.717 69.653 68.524 72.625 -_227_mtrt 5.42 5.38 5.29 5.11 -_202_jess 6.71 6.61 6.57 6.49 -_201_compress 8.38 8.21 8.00 7.95 -_209_db 4.04 3.89 3.66 3.90 -_222_mpegaudio 10.2 9.92 9.45 8.77 -_228_jack 6.82 6.53 6.64 6.27 -_213_javac 3.50 3.41 3.35 3.37 -Geometric Mean 6.06 5.91 5.77 5.68 +_227_mtrt 5.23 5.37 5.42 5.38 5.29 5.11 +_202_jess 6.86 7.19 6.71 6.61 6.57 6.49 +_201_compress 8.71 8.43 8.38 8.21 8.00 7.95 +_209_db 3.97 4.00 4.04 3.89 3.66 3.90 +_222_mpegaudio 10.8 10.5 10.2 9.92 9.45 8.77 +_228_jack 6.78 6.75 6.82 6.53 6.64 6.27 +_213_javac 3.44 3.48 3.50 3.41 3.35 3.37 +Geometric Mean 6.10 6.12 6.06 5.91 5.77 5.68 TYA JBui OpenJIT int:FCS int:RC4 _201_compress 153.195 112.659 114.529 596.893 615.064 diff -aruN shujit-0.6.6/txt/benchmark-PJ2X3 shujit/txt/benchmark-PJ2X3 --- shujit-0.6.6/txt/benchmark-PJ2X3 Wed Sep 13 19:53:08 2000 +++ shujit/txt/benchmark-PJ2X3 Tue Sep 19 21:12:21 2000 @@ -3,13 +3,12 @@ [TYA 付属のもの] - interp. TYA17v2 Inp1215 000423 000429 0.6.4 0.6.5 0.6.6 -Sieve 125 586 1096 622 634 629 618 632 + interp. TYA17v2 Inp1215 000429 0.6.4 0.6.5 0.6.6 0.6.7 +Sieve 125 586 1096 634 629 618 632 632 [Linpack Benchmark -- Java Version] -interpreter 2.393 0.29 shuJIT-000423 7.007 0.1 shuJIT-000429 7.803 0.09 shuJIT-000706 7.893 0.09 @@ -19,6 +18,7 @@ shuJIT-0.6.4 13.205 0.05 shuJIT-000909 13.464 0.05 shuJIT-0.6.6 13.733 0.05 +shuJIT-0.6.7 14.306 0.05 TYA-1.7 11.444 0.06 OpenJIT-1.1.10 12.956 0.05 OpenJIT-1.1.13 13.464 0.05 @@ -26,6 +26,7 @@ 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 ??? +interpreter 2.393 0.29 [CaffeineMark 3.0] @@ -56,6 +57,18 @@ Image 513 518 506 526 517 524 529 526 518 Dialog 126 121 127 114 120 129 127 107 118 CM3 1157 1173 1191 1183 1193 1272 1281 1291 1291 + + 0.6.7 +Sieve 1961 +Loop 3443↑ +Logic 6841 +String 2447 +Float 2542↑ +Method 1812 +Graphics 308 +Image 507 +Dialog 118 +CM3 1285 TYA 1.7v2 OpenJIT 1.1.13 OpenJIT 1.1.14 Sieve 1911 3231 3224 diff -aruN shujit-0.6.6/txt/codesize shujit/txt/codesize --- shujit-0.6.6/txt/codesize Wed Sep 6 22:25:55 2000 +++ shujit/txt/codesize Tue Sep 19 21:19:59 2000 @@ -30,6 +30,14 @@ native code size / num of inst: 24.43330154 native code size / byte code size: 11.20846603 +[2000年 9月 19日 (0.6.7 + 1.1.8v1)] +num of compiled method: 598 +num of byte code inst: 29132 +byte code size (byte): 63522 +native code size (byte): 666932 +native code size / num of inst: 22.8934505 +native code size / byte code size: 10.49922861 + % java DoNothing @@ -47,6 +55,14 @@ native code size (byte): 7143 native code size / num of inst: 21.7112462 native code size / byte code size: 12.10677966 + +[2000年 9月 19日 (0.6.7 + 1.1.8v1)] +num of compiled method: 14 +num of byte code inst: 329 +byte code size (byte): 590 +native code size (byte): 6870 +native code size / num of inst: 20.88145897 +native code size / byte code size: 11.6440678 2. E2 暗号化 diff -aruN shujit-0.6.6/txt/memo shujit/txt/memo --- shujit-0.6.6/txt/memo Wed Sep 13 21:37:24 2000 +++ shujit/txt/memo Tue Sep 19 03:41:29 2000 @@ -1,7 +1,4 @@ Todo - - きちんと StackOverflowError を起こす。 - - private メンバへのアクセス時に NoClassDefFoundError を発生させてしまうのを - きちんと IllegalAccessError にする。 - 特定メソッドの inlining。 profiling (javac, Linpack 等) に基づいて。 System#arraycopy, Object#getClass, Object#hashCode @@ -73,6 +70,7 @@ javac の、フックをかけられる箇所を探す。-> Jikes を改造? Done + - きちんと StackOverflowError を起こす。 - 末尾再帰をメソッド先頭へのジャンプに変換。 - JMP 命令の、E9 (引数 4 バイト) から EB (引数 1 バイト) への書き換え - JavaFrame の作成を省く。