diff -aruN shujit-0.6.1/ChangeLog shujit/ChangeLog --- shujit-0.6.1/ChangeLog Mon Aug 21 18:49:40 2000 +++ shujit/ChangeLog Sat Aug 26 21:31:32 2000 @@ -1,5 +1,32 @@ $Id$ +[20000826] + +resolveExcRetSwitch() (compile.c) でも、 +jmp (0xe9) XX XX XX XX を jmp (0xeb) XX に書き換えるようにした。 +(see [20000822]) +(compile.c) + +0.6.2 リリース。 + +[20000825] + +invoke* 命令を、いくつかの内部命令に分割。 +(opcodes_internal.h, code.c, compile.c) + +invokevirtual 命令に対して、これまで常に +マクロ obj_array_methodtable() (interpreter.h) 相当の +コードを生成してきたところ、java.lang.Object 以外に対する呼び出しに対しては +マクロ obj_methodtable() 相当のコードを生成するようにした。 +(code.c, compile.c) + +[20000822] + +resolveJumpInstructions() (compile.c) にて、 +jmp (0xe9) XX XX XX XX を jmp (0xeb) XX に書き換えるようにした。 +CaffeineMark 3.0 の Logic のスコアが大きく向上: 4400 -> 4900。 +(compile.c) + [20000821] monitorenter, monitorexit 命令で monitorEnter2(), monitorExit2() を呼び出す際、 diff -aruN shujit-0.6.1/code.c shujit/code.c --- shujit-0.6.1/code.c Mon Aug 21 11:46:36 2000 +++ shujit/code.c Sat Aug 26 16:03:59 2000 @@ -585,17 +585,40 @@ asm("movl $" #N ",%ecx"); }\ CODE(opc_iconst_##S, iconst_##S, ST2, ST4, OPC_NONE){\ asm("pushl %edx\n\t"\ - "movl $" #N ",%edx");\ - }\ + "movl $" #N ",%edx"); }\ CODE(opc_iconst_##S, iconst_##S, ST3, ST4, OPC_NONE) {\ asm("movl $" #N ",%edx"); }\ CODE(opc_iconst_##S, iconst_##S, ST4, ST2, OPC_NONE) {\ asm("pushl %ecx\n\t"\ - "movl $" #N ",%ecx");\ - } + "movl $" #N ",%ecx"); } +#if 1 CODE_ICONST_N(m1, -1); CODE_ICONST_N(1, 1); +#else +# define CODE_ICONST_1(S, INSN) \ + CODE(opc_iconst_##S, iconst_##S, ST0, ST1, OPC_NONE) {\ + asm("xorl %edx,%edx\n\t"\ + #INSN " %edx"); }\ + CODE(opc_iconst_##S, iconst_##S, ST1, ST2, OPC_NONE) {\ + asm("xorl %ecx,%ecx\n\t"\ + #INSN " %ecx"); }\ + CODE(opc_iconst_##S, iconst_##S, ST2, ST4, OPC_NONE){\ + asm("pushl %edx");\ + asm("xorl %edx,%edx\n\t"\ + #INSN " %edx"); }\ + CODE(opc_iconst_##S, iconst_##S, ST3, ST4, OPC_NONE) {\ + asm("xorl %edx,%edx\n\t"\ + #INSN " %edx"); }\ + CODE(opc_iconst_##S, iconst_##S, ST4, ST2, OPC_NONE) {\ + asm("pushl %ecx");\ + asm("xorl %ecx,%ecx\n\t"\ + #INSN " %ecx"); } + + CODE_ICONST_1(1, incl); + CODE_ICONST_1(m1, decl); +#endif + CODE_ICONST_N(2, 2); CODE_ICONST_N(3, 3); CODE_ICONST_N(4, 4); @@ -3559,7 +3582,7 @@ asm(".byte 0xe8\n\t.long 0\n\t"\ "popl %edi");\ asm("subl $" GETSTATIC_REWRITE_OFFSET ",%edi\n\t"\ - "movw $" GETSTATIC_REWRITE_DATA "eb,(%edi)"); /* jmp XX XX */\ + "movw $" GETSTATIC_REWRITE_DATA "eb,(%edi)"); /* jmp XX */\ \ asm(LABEL "_initclass_done:") #endif // INITCLASS_IN_COMPILING || NO_REWRITE @@ -3735,136 +3758,48 @@ // const: args_size, method, local_var_space, retsize // invokeinterface // const: args_size, guessptr, imethod, retsize -#ifdef RUNTIME_DEBUG -# define INVOKE_CORE_DEBUG1 \ - if (runtime_debug) {\ - DEBUG_IN;\ - asm("pushl %eax");\ - PUSH_CONSTSTR(" invocationHelper() returns: %d\n");\ - asm("call " SYMBOL(printf) "@PLT\n\t"\ - "addl $8,%esp");\ - FFLUSH;\ - DEBUG_OUT;\ - } -#else -# define INVOKE_CORE_DEBUG1 -#endif -#ifdef RUNTIME_DEBUG -#define INVOKE_CORE_PUSH_DEBUG_FLAG \ - asm("pushl %0" : : "m" (runtime_debug)) -#define INVOKE_CORE_ARG_SIZE "28" -#else -#define INVOKE_CORE_PUSH_DEBUG_FLAG -#define INVOKE_CORE_ARG_SIZE "24" -#endif // RUNTIME_DEBUG +// stuff to rewrite code for opc_invoke* +# define INVOKE_REWRITE_OFFSET "0x28" +# define INVOKE_REWRITE_DATA "0x2f" -#ifdef METAVM -# define METAVM_INVOKE(LABEL) \ - JUMP_IF_NOT_PROXY(%edx /* is obj */, LABEL "_inv_local");\ - JUMP_IF_NOT_REMOTE(LABEL "_inv_local");\ - /* these break edi */\ - \ - /* call Proxy#* at local */\ - asm("pushl %ecx\n\tpushl %eax\n\t" /* save */\ - "leal 8(%esp),%ecx"); /* save original esp to ecx */\ - \ - asm("movl " METHOD_CLAZZ(%eax) ",%eax");\ - CB_METHODTABLE(%eax,%eax); /* break edi */\ - /* eax = cbMethodTable(mb->fb.clazz) */\ - METHODTABLE_OF_PROXY(%edi);\ - /* edi = cbMethodTable(Proxy clazz) */\ - asm("cmpl %eax,%edi");\ - asm("jnz " LABEL "_inv_remote\n\t"\ - "popl %eax\n\tpopl %ecx\n\t" /* restore */\ - "jmp " LABEL "_inv_local");\ - \ - asm(LABEL "_inv_remote:\n\t"\ - "popl %eax"); /* restore */\ - \ - asm("pushl %ecx\n\t" /* stack pointer */\ - "pushl " METHOD_SIGNATURE(%eax) "\n\t" /* signature */\ - "pushl " METHOD_FB_U_OFFSET(%eax) "\n\t" /* index in methodtable */\ - "pushl %eax\n\t" /* methodblock */\ - "pushl %edx"); /* obj (Proxy) */\ - asm("pushl %0" : : "m" (ee)); /* ee */\ - asm("call " SYMBOL(proxy_invoke) "@PLT\n\t"\ - "addl $24,%esp");\ - \ - asm("popl %ecx"); /* restore */\ - asm("jmp " LABEL "_restack");\ - \ - asm(LABEL "_inv_local:") +#if defined(INITCLASS_IN_COMPILING) || defined(NO_REWRITE) +# define INITCLASS_INVOKE(LABEL) #else -# define METAVM_INVOKE(LABEL) -#endif // METAVM - -#define INVOKE_CORE(VOP, LABEL) \ - bytepcoff = BYTEPCOFF;\ - asm("movl $" STR(CONST) ",%ecx"); /* ecx = args_size */\ - \ - TGTOBJ_##VOP(LABEL); /* edx = obj */\ - /* needs ecx:args_size */\ - /* TGTOBJ_* performs null check, too */\ - \ - METHODBLOCK_##VOP(LABEL); /* eax = method */\ - /* needs edx:obj */\ - /* breaks edi */\ - \ - METAVM_INVOKE_##VOP(LABEL);\ - /* needs edx:obj eax:method */\ - /* breaks edi */\ - \ - VARSPACE_##VOP(LABEL); /* edi = local var. space */\ - /* needs eax:method, ecx:args_size */\ - \ - asm("subl %edi,%esp\n\t"\ - "pushl %edi\n\t" /* save */\ - "leal 4(%esp,%edi),%edi"); /* edi = original esp */\ - \ - asm("leal -4(%edi,%ecx,4),%edi"); /* base of native stack */\ - /* edi = original esp + 4 * (args_size - 1) */\ - \ - /* save registers */\ - asm("pushl %esi");\ - \ - /* push args of invocationHelper() */\ - INVOKE_CORE_PUSH_DEBUG_FLAG; /* push runtime_debug */\ - asm("pushl $" STR(CONST)); /* push retsize */\ - 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("movl " EE_CURRENTFRAME(%edi) ",%edi");\ - /* edi = ee->current_frame */\ - \ - INVOKE_CORE_DIRECT_JIT(LABEL);\ - \ - asm(LABEL "_invoke_normal:");\ - asm("call " SYMBOL(invocationHelper) "@PLT");\ - asm(LABEL "_invoke_done:");\ - \ - asm("addl $" INVOKE_CORE_ARG_SIZE ",%esp");\ - /* restore registers */\ - asm("popl %esi");\ +# define INITCLASS_INVOKE(LABEL) \ + /* edx is clazz */\ + asm(".short 0x9090");\ \ - INVOKE_CORE_DEBUG1;\ + asm("pushl %eax\n\tpushl %ecx"); /* save */\ + asm("pushl %edx");\ + asm("pushl %0" : : "m" (ee)); /* ee */\ + asm("call " SYMBOL(once_InitClass) "@PLT\n\t"\ + "addl $4,%esp");\ + asm("popl %edx\n\tpopl %ecx"); /* restore */\ \ - asm("popl %edi"); /* restore */\ - asm("addl %edi,%esp"); /* free local var space */\ + /* exc. check */\ + asm("testl %eax,%eax\n\t"\ + "popl %eax\n\t" /* restore */\ + "jz " LABEL "_initclass_success");\ + SIGNAL_ERROR_JUMP();\ \ - asm(LABEL "_restack:");\ + asm(LABEL "_initclass_success:");\ \ - /* adjust optop */\ - asm("movl $" STR(CONST) ",%edi\n\t" /* edi = args_size */\ - "leal (%esp,%edi,4),%esp"); /* esp += (args_size * 4) */\ + /* rewrite */\ + asm(".byte 0xe8\n\t.long 0\n\t"\ + "popl %edi");\ + asm("subl $" INVOKE_REWRITE_OFFSET ",%edi\n\t"\ + "movw $" INVOKE_REWRITE_DATA "eb,(%edi)"); /* jmp XX */\ \ - /* if (eax == 0) goto exc_handler */\ - asm("testl %eax,%eax\n\t"\ - "jnz " STR(ADDR_EXC)) + asm(LABEL "_initclass_done:") +#endif // INITCLASS_IN_COMPILING || NO_REWRITE + + + // const: args_size + CODE(opc_inv_head, inv_head, STANY, STSTA, OPC_NONE) { + bytepcoff = BYTEPCOFF; + asm("movl $" STR(CONST) ",%ecx"); // ecx = args_size + } #ifdef DIRECT_INVOCATION @@ -3907,170 +3842,216 @@ #endif // DIRECT_INVOCATION -#define CODE_INVOKE(vop, VOP, OPC_FLAG) \ - CODE(opc_invoke##vop, invoke##vop, ST0, ST0, OPC_FLAG) {\ - INVOKE_CORE(VOP, #vop "_st0");\ - }\ - CODE(opc_invoke##vop, invoke##vop, ST1, ST0, OPC_FLAG) {\ - asm("pushl %edx"); /* now state 0 */\ - INVOKE_CORE(VOP, #vop "_st1");\ - }\ - CODE(opc_invoke##vop, invoke##vop, ST2, ST0, OPC_FLAG) {\ - asm("pushl %edx\n\t"\ - "pushl %ecx"); /* now state 0 */\ - INVOKE_CORE(VOP, #vop "_st2");\ - }\ - CODE(opc_invoke##vop, invoke##vop, ST3, ST0, OPC_FLAG) {\ - asm("pushl %ecx"); /* now state 0 */\ - INVOKE_CORE(VOP, #vop "_st3");\ - }\ - CODE(opc_invoke##vop, invoke##vop, ST4, ST0, OPC_FLAG) {\ - asm("pushl %ecx\n\t"\ - "pushl %edx"); /* now state 0 */\ - INVOKE_CORE(VOP, #vop "_st4");\ +#ifdef RUNTIME_DEBUG +# define INVOKE_CORE_DEBUG1 \ + if (runtime_debug) {\ + DEBUG_IN;\ + asm("pushl %eax");\ + PUSH_CONSTSTR(" invocationHelper() returns: %d\n");\ + asm("call " SYMBOL(printf) "@PLT\n\t"\ + "addl $8,%esp");\ + FFLUSH;\ + DEBUG_OUT;\ } +#else +# define INVOKE_CORE_DEBUG1 +#endif -// stuff to rewrite code for opc_invoke* -# define INVOKE_REWRITE_OFFSET "0x2a" -# define INVOKE_REWRITE_DATA "0x31" - -#if defined(INITCLASS_IN_COMPILING) || defined(NO_REWRITE) -# define INITCLASS_INVOKE(MB, LABEL) +#ifdef RUNTIME_DEBUG +#define INVOKE_CORE_PUSH_DEBUG_FLAG \ + asm("pushl %0" : : "m" (runtime_debug)) +#define INVOKE_CORE_ARG_SIZE "28" #else -# define INITCLASS_INVOKE(MB, LABEL) \ - asm(".short 0x9090");\ - \ - asm("pushl %eax\n\tpushl %edx\n\tpushl %ecx"); /* save */\ - asm("pushl " METHOD_CLAZZ(MB));\ - asm("pushl %0" : : "m" (ee)); /* ee */\ - asm("call " SYMBOL(once_InitClass) "@PLT\n\t"\ - "addl $8,%esp");\ - asm("popl %ecx\n\tpopl %edx"); /* restore */\ - \ - /* exc. check */\ - asm("testl %eax,%eax\n\t"\ - "popl %eax\n\t" /* restore */\ - "jz " LABEL "_initclass_success");\ - SIGNAL_ERROR_JUMP();\ - \ - asm(LABEL "_initclass_success:");\ - \ - /* rewrite */\ - asm(".byte 0xe8\n\t.long 0\n\t"\ - "popl %edi");\ - asm("subl $" INVOKE_REWRITE_OFFSET ",%edi\n\t"\ - "movw $" INVOKE_REWRITE_DATA "eb,(%edi)"); /* jmp XX XX */\ - \ - asm(LABEL "_initclass_done:") -#endif // INITCLASS_IN_COMPILING || NO_REWRITE +#define INVOKE_CORE_PUSH_DEBUG_FLAG +#define INVOKE_CORE_ARG_SIZE "24" +#endif // RUNTIME_DEBUG -#define TGTOBJ_VIRTUAL(LABEL) \ - asm("movl -4(%esp,%ecx,4),%edx"); /* ecx must be args_size */\ - NULL_TEST(%edx, LABEL) + // const: retsize, args_size + CODE(opc_inv_core, inv_core, STANY, ST0, OPC_NONE) { + asm("subl %edi,%esp\n\t" + "pushl %edi\n\t" // save + "leal 4(%esp,%edi),%edi"); // edi = original esp + + asm("leal -4(%edi,%ecx,4),%edi"); // base of native stack + // edi = original esp + 4 * (args_size - 1) + + // save registers + asm("pushl %esi"); + + // push args of invocationHelper() + INVOKE_CORE_PUSH_DEBUG_FLAG; // push runtime_debug + asm("pushl $" STR(CONST)); // push retsize + 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("movl " EE_CURRENTFRAME(%edi) ",%edi"); + // edi = ee->current_frame + + INVOKE_CORE_DIRECT_JIT("inv_core"); + + asm("inv_core_invoke_normal:"); + asm("call " SYMBOL(invocationHelper) "@PLT"); + asm("inv_core_invoke_done:"); + + asm("addl $" INVOKE_CORE_ARG_SIZE ",%esp"); + // restore registers + asm("popl %esi"); + + INVOKE_CORE_DEBUG1; + + asm("popl %edi"); // restore + asm("addl %edi,%esp"); // free local var space + + asm("inv_core_restack:"); + + // adjust optop + asm("movl $" STR(CONST) ",%edi\n\t" // edi = args_size + "leal (%esp,%edi,4),%esp"); // esp += (args_size * 4) + + // if (eax == 0) goto exc_handler + asm("testl %eax,%eax\n\t" + "jnz " STR(ADDR_EXC)); + } + + CODE(opc_inv_vir_obj, inv_vir_obj, STANY, STSTA, OPC_NONE) { + asm("movl -4(%esp,%ecx,4),%edx"); // ecx must be args_size + NULL_TEST(%edx, "inv_vir_obj"); + } #ifdef METAVM -# define METHODBLOCK_VIRTUAL(LABEL) \ - OBJ_ARRAY_METHODTABLE_TO_EAX(%edx, LABEL); /* eax = obj_array_..(obj) */\ - \ - JUMP_IF_NOT_REMOTE(LABEL "_not_proxy"); /* break edi */\ +# define METAVM_INVOKEVIRTUAL \ + JUMP_IF_NOT_REMOTE("invokevir_not_proxy"); /* break edi */\ \ METHODTABLE_OF_PROXY(%edi);\ asm("cmpl %eax,%edi\n\t"\ - "jnz " LABEL "_not_proxy");\ + "jnz invokevir_not_proxy");\ PROXY_CLAZZ(%edx, %eax); /* eax = Proxy.clazz */\ CB_METHODTABLE(%eax, %eax); /* eax = methodtable of Proxy.clazz */\ \ - asm(LABEL "_not_proxy:");\ - asm("movl $" STR(CONST) ",%edi"); /* edi = methodIndex */\ - MT_SLOT(%eax, %edi, %eax) /* eax = method */ -#else -# define METHODBLOCK_VIRTUAL(LABEL) \ - /* get methodblock */\ - OBJ_ARRAY_METHODTABLE_TO_EAX(%edx, LABEL); /* eax = obj_array_..(obj) */\ - /* may cause SIGSEGV */\ - asm("movl $" STR(CONST) ",%edi"); /* edi = methodIndex */\ - MT_SLOT(%eax, %edi, %eax) /* eax = method */ -#endif // METAVM + asm("invokevir_not_proxy:") +#else +# define METAVM_INVOKEVIRTUAL +#endif -#define VARSPACE_VIRTUAL(LABEL) \ - /* allocate local var space */\ - METHOD_NLOCALS(%eax, %edi); /* edi = method->nlocals */\ - asm("testl %edi,%edi\n\t"\ - "jz " LABEL "_nlocal_done\n\t" /* edi = 0, if true */\ - /* method->nlocals of native method is 0 */\ - "subl %ecx,%edi\n\t" /* edi -= args_size */\ - "shll $2,%edi\n\t" /* edi *= 4 */\ - LABEL "_nlocal_done:") - -#define METAVM_INVOKE_VIRTUAL(LABEL) METAVM_INVOKE(LABEL) - -#define TGTOBJ_SPECIAL(LABEL) \ - TGTOBJ_VIRTUAL(LABEL);\ - asm("movl (%edx),%eax") /* to cause SIGSEGV */ -#define METHODBLOCK_SPECIAL(LABEL) asm("movl $" STR(CONST) ",%eax") -#define VARSPACE_SPECIAL(LABEL) asm("movl $" STR(CONST) ",%edi") -#define METAVM_INVOKE_SPECIAL(LABEL) METAVM_INVOKE(LABEL) - -#define TGTOBJ_STATIC_QUICK(LABEL) - /* null instead of 0 clear (asm("xorl %edx,%edx")) */ -#define METHODBLOCK_STATIC_QUICK(LABEL) \ - asm("movl $" STR(CONST) ",%eax\n\t"\ - "movl " METHOD_CLAZZ(%eax) ",%edx");\ - // edx = cbHandle(method->fb.clazz) -#define VARSPACE_STATIC_QUICK(LABEL) asm("movl $" STR(CONST) ",%edi") -#define METAVM_INVOKE_STATIC_QUICK(LABEL) // nothing - -#define TGTOBJ_STATIC(LABEL) TGTOBJ_STATIC_QUICK(LABEL) -#define METHODBLOCK_STATIC(LABEL) \ - METHODBLOCK_STATIC_QUICK(LABEL);\ - /* call InitClass(cb) */\ - INITCLASS_INVOKE(%eax, LABEL) -#define VARSPACE_STATIC(LABEL) VARSPACE_STATIC_QUICK(LABEL) -#define METAVM_INVOKE_STATIC(LABEL) METAVM_INVOKE_STATIC_QUICK(LABEL) - -#define TGTOBJ_INTERFACE(LABEL) \ - TGTOBJ_VIRTUAL(LABEL);\ - asm("movl (%edx),%eax") + // const: methodIndex + CODE(opc_invokevirtual, invokevirtual, STANY, STSTA, OPC_SIGNAL) { + OBJ_ARRAY_METHODTABLE_TO_EAX(%edx, "invokevir"); + // may cause SIGSEGV + METAVM_INVOKEVIRTUAL; + asm("movl $" STR(CONST) ",%edi"); // edi = slot + MT_SLOT(%eax, %edi, %eax); // eax = method + } + // const: methodIndex + CODE(opc_invokevirtual_obj, invokevirtual_obj, STANY, STSTA, OPC_SIGNAL) { + OBJ_METHODTABLE(%edx, %eax); // may cause SIGSEGV + METAVM_INVOKEVIRTUAL; + asm("movl $" STR(CONST) ",%edi"); // edi = slot + MT_SLOT(%eax, %edi, %eax); // eax = method + } -#define INVINTF_REWRITE_OFFSET "0x17" -#define INVINTF_REWRITE_DATA "0x1e" + CODE(opc_inv_vir_varspace, inv_vir_varspace, STANY, STSTA, OPC_NONE) { + // allocate local var space + METHOD_NLOCALS(%eax, %edi); // edi = method->nlocals + asm("testl %edi,%edi\n\t" + "jz inv_vir_varspace_nlocal_done\n\t" // edi = 0, if true + // method->nlocals of native method is 0 + "subl %ecx,%edi\n\t" // edi -= args_size + "shll $2,%edi\n\t" // edi *= 4 + "inv_vir_varspace_nlocal_done:"); + } -#define INVINTF_REWRITE1(LABEL) \ - asm(".short 0x9090") +#ifdef METAVM + CODE(opc_inv_metavm, inv_metavm, STANY, STSTA, OPC_NONE) { + JUMP_IF_NOT_PROXY(%edx /* is obj */, "inv_metavm_inv_local"); + JUMP_IF_NOT_REMOTE("inv_metavm_inv_local"); + // these break edi -#define INVINTF_REWRITE2(LABEL) \ - asm(".byte 0xe8\n\t.long 0\n\t"\ - "popl %edi"); /* here, can break edi */\ - asm("subl $" INVINTF_REWRITE_OFFSET ",%edi\n\t"\ - "movw $" INVINTF_REWRITE_DATA "eb,(%edi)") /* jmp XX XX */ + // call Proxy#* at local + asm("pushl %ecx\n\tpushl %eax\n\t" // save + "leal 8(%esp),%ecx"); // save original esp to ecx -#define METHODBLOCK_INTERFACE(LABEL) \ - /* get methodblock: call getInterfaceMethod() */\ - asm("pushl %ecx\n\tpushl %edx"); /* save */\ - /*FUNCCALL_IN(0);*/\ - asm("pushl %0" : : "m" (bytepcoff));/* bytepcoff */\ - asm("pushl $" STR(CONST) "\n\t" /* guessptr */\ - "pushl $" STR(CONST) "\n\t" /* imethod */\ - "pushl %edx"); /* obj */\ - asm("pushl %0" : : "m" (ee)); /* ee */\ - CALL_GETINTFMETHOD;\ - /*FUNCCALL_OUT(0);*/\ - asm("popl %edx\n\tpopl %ecx"); /* restore */\ - \ - INVINTF_REWRITE1(LABEL);\ - asm("testl %eax,%eax\n\t"\ - "jnz " LABEL "_getintf_success");\ - SIGNAL_ERROR_JUMP();\ - \ - asm(LABEL "_getintf_success:");\ - \ - INVINTF_REWRITE2(LABEL);\ - \ - asm(LABEL "_getintf_done:") + asm("movl " METHOD_CLAZZ(%eax) ",%eax"); + CB_METHODTABLE(%eax,%eax); // break edi + // eax = cbMethodTable(mb->fb.clazz) + METHODTABLE_OF_PROXY(%edi); + // edi = cbMethodTable(Proxy clazz) + asm("cmpl %eax,%edi"); + asm("jnz inv_metavm_inv_remote\n\t" + "popl %eax\n\tpopl %ecx\n\t" // restore + "jmp inv_metavm_inv_local"); + + asm("inv_metavm_inv_remote:\n\t" + "popl %eax"); // restore -#define VARSPACE_INTERFACE(LABEL) VARSPACE_VIRTUAL(LABEL) -#define METAVM_INVOKE_INTERFACE(LABEL) METAVM_INVOKE(LABEL) + asm("pushl %ecx\n\t" // stack pointer + "pushl " METHOD_SIGNATURE(%eax) "\n\t" // signature + "pushl " METHOD_FB_U_OFFSET(%eax) "\n\t" // index in methodtable + "pushl %eax\n\t" // methodblock + "pushl %edx"); // obj (Proxy) + asm("pushl %0" : : "m" (ee)); // ee + asm("call " SYMBOL(proxy_invoke) "@PLT\n\t" + "addl $24,%esp"); + + asm("popl %ecx"); // restore + asm("jmp inv_metavm_restack"); + + asm("inv_metavm_inv_local:"); + } +#endif METAVM + + + CODE(opc_inv_spe_obj, inv_spe_obj, STANY, STSTA, OPC_SIGNAL) { + asm("movl -4(%esp,%ecx,4),%edx"); // ecx must be args_size + NULL_TEST(%edx, "inv_spe_obj"); + asm("movl (%edx),%eax"); // to cause SIGSEGV + } + + // const: method + CODE(opc_invokespecial, invokespecial, STANY, STSTA, OPC_NONE) { + asm("movl $" STR(CONST) ",%eax"); + } + + // const: local_var_space + CODE(opc_inv_spe_varspace, inv_spe_varspace, STANY, STSTA, OPC_NONE) { + asm("movl $" STR(CONST) ",%edi"); + } + + CODE(opc_inv_stq_obj, inv_stq_obj, STANY, STSTA, OPC_NONE) { + // null instead of 0 clear (asm("xorl %edx,%edx")) + } + + // const: method + CODE(opc_invokestatic_quick, invokestatic_quick, STANY, STSTA, OPC_NONE) { + // edx = cbHandle(method->fb.clazz) + asm("movl $" STR(CONST) ",%eax\n\t" + "movl " METHOD_CLAZZ(%eax) ",%edx"); + } + + // const: local_var_space + CODE(opc_inv_stq_varspace, inv_stq_varspace, STANY, STSTA, OPC_NONE) { + asm("movl $" STR(CONST) ",%edi"); + } + + // inv_sta_obj is same as inv_stq_obj + + // const: method + CODE(opc_invokestatic, invokestatic, STANY, STSTA, OPC_NONE) { + // edx = cbHandle(method->fb.clazz) + asm("movl $" STR(CONST) ",%eax\n\t" + "movl " METHOD_CLAZZ(%eax) ",%edx"); + + INITCLASS_INVOKE("invokesta"); + } + + // inv_sta_varspace is same as inv_stq_varspace + + + // inv_int_obj is same as inv_spe_obj #ifdef RUNTIME_DEBUG # define CALL_GETINTFMETHOD \ @@ -4083,12 +4064,49 @@ "addl $20,%esp") #endif +#define INVINTF_REWRITE_OFFSET "0x17" +#define INVINTF_REWRITE_DATA "0x1e" + +#define INVINTF_REWRITE1() \ + asm(".short 0x9090") + +#define INVINTF_REWRITE2() \ + asm(".byte 0xe8\n\t.long 0\n\t"\ + "popl %edi"); /* here, can break edi */\ + asm("subl $" INVINTF_REWRITE_OFFSET ",%edi\n\t"\ + "movw $" INVINTF_REWRITE_DATA "eb,(%edi)") /* jmp XX */ + + // const: guessptr, imethod + CODE(opc_invokeinterface, invokeinterface, STANY, STSTA, OPC_NONE) { + // get methodblock: call getInterfaceMethod() + + asm("pushl %ecx\n\tpushl %edx"); // save + + //FUNCCALL_IN(0); + asm("pushl %0" : : "m" (bytepcoff));// bytepcoff + asm("pushl $" STR(CONST) "\n\t" // guessptr + "pushl $" STR(CONST) "\n\t" // imethod + "pushl %edx"); // obj + asm("pushl %0" : : "m" (ee)); // ee + CALL_GETINTFMETHOD; + //FUNCCALL_OUT(0); + + asm("popl %edx\n\tpopl %ecx"); // restore + + INVINTF_REWRITE1(); + asm("testl %eax,%eax\n\t" + "jnz invokeint_getintf_success"); + SIGNAL_ERROR_JUMP(); + + asm("invokeint_getintf_success:"); + + INVINTF_REWRITE2(); + + asm("invokeint_getintf_done:"); + } + + // inv_int_varspace is same as inv_vir_varspace - CODE_INVOKE(virtual, VIRTUAL, OPC_SIGNAL); - CODE_INVOKE(special, SPECIAL, OPC_SIGNAL); - CODE_INVOKE(static_quick, STATIC_QUICK, OPC_NONE); - CODE_INVOKE(static, STATIC, OPC_THROW); - CODE_INVOKE(interface, INTERFACE, OPC_SIGNAL); #if 0 // how to get methodblock # if 0 @@ -4100,16 +4118,6 @@ #endif - // invokevirtual_quick - // const: args_size, methodIndex, retsize - CODE_INVOKE(virtual_quick, VIRTUAL, OPC_SIGNAL); - - - // invokevirtualobject_quick - // const: args_size, methodIndex, retsize - CODE_INVOKE(virtualobject_quick, VIRTUAL, OPC_SIGNAL); - - // xxxunusedxxx CODE(opc_xxxunusedxxx, xxxunusesxxx, STANY, STSTA, OPC_NONE) {} @@ -4222,7 +4230,7 @@ asm(".byte 0xe8\n\t.long 0\n\t"\ "popl %edi");\ asm("subl $" NEW_REWRITE_OFFSET ",%edi\n\t"\ - "movw $" NEW_REWRITE_DATA "eb,(%edi)"); /* jmp XX XX */\ + "movw $" NEW_REWRITE_DATA "eb,(%edi)"); /* jmp XX */\ \ asm(LABEL "_once_done:") #else diff -aruN shujit-0.6.1/code.h shujit/code.h --- shujit-0.6.1/code.h Mon Aug 21 03:30:25 2000 +++ shujit/code.h Thu Aug 24 22:20:28 2000 @@ -394,7 +394,7 @@ #define METHODTABLE_OF_PROXY(DST) \ asm("movl " SYMBOL(proxy_methodtable) "@GOT(%ebx)," #DST "\n\t"\ - "movl (" #DST ")," #DST); + "movl (" #DST ")," #DST) // break no registers #define JUMP_IF_NOT_PROXY(HANDLE_REG /* must not be %edi */, LABEL) \ diff -aruN shujit-0.6.1/compile.c shujit/compile.c --- shujit-0.6.1/compile.c Mon Aug 21 05:44:31 2000 +++ shujit/compile.c Sat Aug 26 13:07:53 2000 @@ -412,6 +412,10 @@ int endoff = mb->code_length; int32_t byteoff = 0; int byteinc; + int operand; + cp_item_type *constant_pool = cbConstantPool(fieldclass(&mb->fb)); + unsigned char *type_table = + constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type; CodeInfo *info = (CodeInfo *)(mb->CompiledCodeInfo); #if 0 @@ -619,6 +623,300 @@ byteoff++; break; + case opc_invokevirtual: case opc_invokevirtual_quick_w: + case opc_invokespecial: + case opc_invokenonvirtual_quick: case opc_invokesuper_quick: + case opc_invokestatic: case opc_invokestatic_quick: + case opc_invokeinterface: case opc_invokeinterface_quick: + switch (opcode) { + case opc_invokevirtual: case opc_invokevirtual_quick_w: + opcode = opc_invokevirtual; + break; + case opc_invokespecial: + case opc_invokenonvirtual_quick: case opc_invokesuper_quick: + opcode = opc_invokespecial; + break; + case opc_invokestatic: case opc_invokestatic_quick: + opcode = opc_invokestatic; + break; + case opc_invokeinterface: case opc_invokeinterface_quick: + opcode = opc_invokeinterface; + } + + operand = GET_UINT16(methodcode + byteoff + 1); + byteinc = opcode_length[opcode]; + + // throwing NoClassDefFoundError if the callee method cannot be resolved + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { + 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; + } + } + + // throwing IllegalAccessError if invoke* final method + { + struct methodblock *src_mb; + struct fieldblock *method_fb; + ClassClass *src_clazz, *method_clazz; + + if (!(src_mb = cc->mb)) { +#ifdef COMPILE_DEBUG + printf("Illegal method invocation: methodblock is null.\n"); + fflush(stdout); +#endif + processAnOpcode(cc, opc_throw_illegalaccess, byteoff); + goto makepc_invoke_done; + } + method_fb = &constant_pool[operand].mb->fb; + + src_clazz = fieldclass(&src_mb->fb); + method_clazz = fieldclass(method_fb); + + // check private and protected from other packages + if (!src_mb || + (!VerifyFieldAccess( + src_clazz, method_clazz, + method_fb->access, FALSE))) { + char *src_clazz_name, *method_clazz_name; + char *src_p, *method_p; + int len = 0; + + src_clazz_name = cbName(src_clazz); + method_clazz_name = cbName(method_clazz); + +#ifdef COMPILE_DEBUG + printf("Illegal method invocation:\n"); fflush(stdout); + printf("\tfrom: %s#%s\n", + src_clazz_name, src_mb->fb.name); + printf("\tto : %s#%s\n", + method_clazz_name, method_fb->name); +#endif + + // but, allow access to/from inner class + src_p = strchr(src_clazz_name, '$'); + method_p = strchr(method_clazz_name, '$'); + if (src_p) { + if (!method_p) len = src_p - src_clazz_name; + } + else { + if (method_p) len = method_p - method_clazz_name; + } + if (len && +#if JDK_VER >= 12 + (cbProtectionDomain(src_clazz) == cbProtectionDomain(method_clazz)) && + (cbLoader(src_clazz) == cbLoader(method_clazz)) +#else + TRUE +#endif // JDK_VER >= 12 + ) { + if (!strncmp(src_clazz_name, method_clazz_name, len)) { +#ifdef COMPILE_DEBUG + printf(" VerifyFieldAccess returned FALSE, " + "but the access is to/from inner class.\n"); + fflush(stdout); +#endif + goto check_illacc_done; + } + } + +#ifdef COMPILE_DEBUG + printf(" A private or protected method invoked.\n"); + fflush(stdout); +#endif + processAnOpcode(cc, opc_throw_illegalaccess, byteoff); + goto makepc_invoke_done; + } + check_illacc_done: + } + + switch (opcode) { + case opc_invokevirtual: + { + struct methodblock *method = constant_pool[operand].mb; + char *clz_name = cbName(fieldclass(&method->fb)); + + if (method->fb.access & (ACC_PRIVATE | ACC_FINAL)) { +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" adjust invokevirtual private method to" + "invokespecial.\n"); + fflush(stdout); + } +#endif + opcode = opc_invokespecial; + goto makepc_invokespecial; + } + + processAnOpcode(cc, opc_stateto0, byteoff); + processAnOpcode(cc, opc_inv_head, byteoff); + processAnOpcode(cc, opc_inv_vir_obj, byteoff); + if (!strcmp(clz_name, "java/lang/Object")) + processAnOpcode(cc, opc_invokevirtual, byteoff); + else + processAnOpcode(cc, opc_invokevirtual_obj, byteoff); +#ifdef METAVM + processAnOpcode(cc, opc_inv_metavm, byteoff); +#endif + processAnOpcode(cc, opc_inv_vir_varspace, byteoff); + processAnOpcode(cc, opc_inv_core, byteoff); + } + break; + + case opc_invokespecial: + case opc_invokestatic: + makepc_invokespecial: + // translate invokevirtual Object# to invokeignored_quick + { + struct methodblock *method = constant_pool[operand].mb; + + 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, "")); + // condition: !static && !constructor + // omit null checks for constructors +#ifdef NO_CHECK + bytepc[0] = opcode = opc_invokeignored_static_quick; + processAnOpcode(cc, opcode, 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); + } + else { + bytepc[0] = opcode = + ((CB_INITIALIZED(fieldclass(&method->fb))) ? + opc_invokeignored_static_quick : opc_invokeignored_static); + processAnOpcode(cc, opcode, byteoff); + } +# if JDK_VER >= 12 + CODE_UNLOCK(EE2SysThread(cc->ee)); +# else + BINCLASS_UNLOCK(); +# endif // JDK_VER +#endif // NO_CHECK + + goto makepc_invoke_done; + } + } + + switch (opcode) { + case opc_invokespecial: + processAnOpcode(cc, opc_stateto0, byteoff); + processAnOpcode(cc, opc_inv_head, byteoff); + processAnOpcode(cc, opc_inv_spe_obj, byteoff); + processAnOpcode(cc, opc_invokespecial, byteoff); +#ifdef METAVM + processAnOpcode(cc, opc_inv_metavm, byteoff); +#endif + processAnOpcode(cc, opc_inv_spe_varspace, byteoff); + processAnOpcode(cc, opc_inv_core, byteoff); + break; + + case opc_invokestatic: + { +#ifdef SPECIAL_INLINING + // special inlining + bool_t inlined = FALSE; + struct methodblock *method = constant_pool[operand].mb; + + if (!strcmp(cbName(fieldclass(&method->fb)), "java/lang/Math")) { + char *mname = method->fb.name; +# ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" invocation of a method of java.lang.Math#%s.\n", + mname); + } +# endif + if (!strcmp(mname, "sqrt")) { + inlined = TRUE; processAnOpcode(cc, opc_sqrt, byteoff); + } + else if (!strcmp(mname, "sin")) { + inlined = TRUE; processAnOpcode(cc, opc_sin, byteoff); + } + else if (!strcmp(mname, "cos")) { + inlined = TRUE; processAnOpcode(cc, opc_cos, byteoff); + } + else if (!strcmp(mname, "tan")) { + inlined = TRUE; processAnOpcode(cc, opc_tan, byteoff); + } + else if (!strcmp(mname, "atan2")) { + inlined = TRUE; processAnOpcode(cc, opc_atan2, byteoff); + } + else if (!strcmp(mname, "atan")) { + inlined = TRUE; processAnOpcode(cc, opc_atan, byteoff); + } +#if 0 + // behavior of pre-assembled code differs from an interpreter. + else if (!strcmp(mname, "exp")) { + inlined = TRUE; processAnOpcode(cc, opc_exp, byteoff); + } +#endif + else if (!strcmp(mname, "log")) { + inlined = TRUE; processAnOpcode(cc, opc_log, byteoff); + } + else if (!strcmp(mname, "floor")) { + inlined = TRUE; processAnOpcode(cc, opc_floor, byteoff); + } + else if (!strcmp(mname, "ceil")) { + inlined = TRUE; processAnOpcode(cc, opc_ceil, byteoff); + } + } // if "java/lang/Math" + if (!inlined) +#endif // SPECIAL_INLINING + { + processAnOpcode(cc, opc_stateto0, byteoff); + processAnOpcode(cc, opc_inv_head, byteoff); + processAnOpcode(cc, opc_inv_stq_obj, byteoff); + if (OPT_SETQ(OPT_CODEDB) || + !CB_INITIALIZED(fieldclass(&(constant_pool[operand].mb->fb)))) + processAnOpcode(cc, opc_invokestatic, byteoff); + else + processAnOpcode(cc, opc_invokestatic_quick, byteoff); + processAnOpcode(cc, opc_inv_stq_varspace, byteoff); + processAnOpcode(cc, opc_inv_core, byteoff); + } + } + } + break; + + case opc_invokeinterface: + processAnOpcode(cc, opc_stateto0, byteoff); + processAnOpcode(cc, opc_inv_head, byteoff); + processAnOpcode(cc, opc_inv_spe_obj, byteoff); + processAnOpcode(cc, opc_invokeinterface, byteoff); +#ifdef METAVM + processAnOpcode(cc, opc_inv_metavm, byteoff); +#endif + processAnOpcode(cc, opc_inv_vir_varspace, byteoff); + processAnOpcode(cc, opc_inv_core, byteoff); + break; + } // switch (opcode) + + makepc_invoke_done: + byteoff += byteinc; + break; + + case opc_invokevirtualobject_quick: + case opc_invokevirtual_quick: + fprintf(stderr, "FATAL: lossy quick opcodes found: %d(0x%x)\n", + opcode, opcode); + JVM_Exit(1); + break; + case opc_monitorenter: case opc_monitorexit: if (OPT_SETQ(OPT_IGNLOCK)) break; // go through @@ -915,8 +1213,8 @@ if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) {\ if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), operand,\ cc->ee, 1 << CONSTANT_Fieldref, FALSE)) {\ - code_opcode = opc_throw_noclassdef;\ exceptionClear(cc->ee);\ + code_opcode = opc_throw_noclassdef;\ }\ }\ \ @@ -955,8 +1253,8 @@ if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) {\ if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), operand,\ cc->ee, 1 << CONSTANT_Fieldref, FALSE)) {\ - code_opcode = opc_throw_noclassdef;\ exceptionClear(cc->ee);\ + code_opcode = opc_throw_noclassdef;\ }\ }\ \ @@ -1010,44 +1308,18 @@ operand = GET_UINT16(bytepc + 1); break; + case opc_inv_head: + case opc_inv_core: case opc_invokevirtual: - case opc_invokevirtual_quick_w: - code_opcode = opc_invokevirtual; - operand = GET_UINT16(bytepc + 1); - break; + case opc_invokevirtual_obj: case opc_invokespecial: - case opc_invokenonvirtual_quick: - case opc_invokesuper_quick: - code_opcode = opc_invokespecial; - operand = GET_UINT16(bytepc + 1); - break; - case opc_invokestatic: + case opc_inv_spe_varspace: case opc_invokestatic_quick: - operand = GET_UINT16(bytepc + 1); - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { - if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), operand, - cc->ee, 1 << CONSTANT_Methodref, FALSE)) { - code_opcode = opc_throw_noclassdef; - exceptionClear(cc->ee); - } - } - if (code_opcode != opc_throw_noclassdef) { - if (OPT_SETQ(OPT_CODEDB) || - !CB_INITIALIZED(fieldclass(&(constant_pool[operand].mb->fb)))) { - code_opcode = opc_invokestatic; - } - else { - code_opcode = opc_invokestatic_quick; - } - // if a class which has the callee method is already initialized, - // generate the quick instruction. - // but in case of the code DB function is enabled, - // initialization of the target class cannot be omitted. - } - break; + case opc_inv_stq_varspace: + case opc_invokestatic: case opc_invokeinterface: - case opc_invokeinterface_quick: - code_opcode = opc_invokeinterface; + case opc_invokeignored_static: + case opc_invokeignored_static_quick: operand = GET_UINT16(bytepc + 1); break; @@ -1059,8 +1331,8 @@ if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), operand, cc->ee, 1 << CONSTANT_Class, FALSE)) { - code_opcode = opc_throw_noclassdef; exceptionClear(cc->ee); + code_opcode = opc_throw_noclassdef; } } } @@ -1175,262 +1447,6 @@ check_access_done: } - // throwing IllegalAccessError if invoke* final method - if ((code_opcode == opc_invokevirtual) || - (code_opcode == opc_invokespecial) || - (code_opcode == opc_invokestatic) || - (code_opcode == opc_invokestatic_quick)) { - struct methodblock *src_mb; - struct fieldblock *method_fb; - ClassClass *src_clazz, *method_clazz; - - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { - if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), operand, - cc->ee, 1 << CONSTANT_Methodref, FALSE)) { - code_opcode = opc_throw_noclassdef; - exceptionClear(cc->ee); - - goto check_invoke_done; - } - } - - if (!(src_mb = cc->mb)) { -#ifdef COMPILE_DEBUG - printf("Illegal method invocation: methodblock is null.\n"); - fflush(stdout); -#endif - code_opcode = opc_throw_illegalaccess; - goto check_invoke_done; - } - method_fb = &constant_pool[operand].mb->fb; - - src_clazz = fieldclass(&src_mb->fb); - method_clazz = fieldclass(method_fb); - - // check private and protected from other packages - if (!src_mb || - (!VerifyFieldAccess( - src_clazz, method_clazz, - method_fb->access, FALSE))) { - char *src_clazz_name, *method_clazz_name; - char *src_p, *method_p; - int len = 0; - - src_clazz_name = cbName(src_clazz); - method_clazz_name = cbName(method_clazz); - -#ifdef COMPILE_DEBUG - printf("Illegal method invocation:\n"); fflush(stdout); - printf("\tfrom: %s#%s\n", - src_clazz_name, src_mb->fb.name); - printf("\tto : %s#%s\n", - method_clazz_name, method_fb->name); -#endif - - // but, allow access to/from inner class - src_p = strchr(src_clazz_name, '$'); - method_p = strchr(method_clazz_name, '$'); - if (src_p) { - if (!method_p) len = src_p - src_clazz_name; - } - else { - if (method_p) len = method_p - method_clazz_name; - } - if (len && -#if JDK_VER >= 12 - (cbProtectionDomain(src_clazz) == cbProtectionDomain(method_clazz)) && - (cbLoader(src_clazz) == cbLoader(method_clazz)) -#else - TRUE -#endif // JDK_VER >= 12 - ) { - if (!strncmp(src_clazz_name, method_clazz_name, len)) { -#ifdef COMPILE_DEBUG - printf(" VerifyFieldAccess returned FALSE, " - "but the access is to/from inner class.\n"); - fflush(stdout); -#endif - goto check_invoke_done; - } - } - -#ifdef COMPILE_DEBUG - printf(" A private or protected method invoked.\n"); - fflush(stdout); -#endif - code_opcode = opc_throw_illegalaccess; - goto check_invoke_done; - } - check_invoke_done: - } - -#ifdef SPECIAL_INLINING - // special inlining - if ((code_opcode == opc_invokestatic) || - (code_opcode == opc_invokestatic_quick)) { - struct methodblock *method; - - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { - if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), operand, - cc->ee, 1 << CONSTANT_Methodref, FALSE)) { - code_opcode = opc_throw_noclassdef; - exceptionClear(cc->ee); - } - } - - if (code_opcode != opc_throw_noclassdef) { - method = constant_pool[operand].mb; - - if (!strcmp(cbName(fieldclass(&method->fb)), "java/lang/Math")) { - char *mname = method->fb.name; -# ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" invocation of a method of java.lang.Math#%s.\n", mname); - } -# endif - if (!strcmp(mname, "sqrt")) code_opcode = opc_sqrt; - else if (!strcmp(mname, "sin")) code_opcode = opc_sin; - else if (!strcmp(mname, "cos")) code_opcode = opc_cos; - else if (!strcmp(mname, "tan")) code_opcode = opc_tan; - else if (!strcmp(mname, "atan2")) code_opcode = opc_atan2; - else if (!strcmp(mname, "atan")) code_opcode = opc_atan; -#if 0 - // behavior of pre-assembled code differs from an interpreter. - else if (!strcmp(mname, "exp")) code_opcode = opc_exp; -#endif - else if (!strcmp(mname, "log")) code_opcode = opc_log; - else if (!strcmp(mname, "floor")) code_opcode = opc_floor; - else if (!strcmp(mname, "ceil")) code_opcode = opc_ceil; - } - } // if (code_opcode != opc_throw_noclassdef) - } -#endif // SPECIAL_INLINING - - -#if 1 - // translate invokevirtual to invokespecial - if (opcode == opc_invokevirtual) { - struct methodblock *method; - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { - int res_result; -#if COMPILE_DEBUG - if (compile_debug) { - printf(" resolving cp[%d] type: %d.\n", operand, - CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, operand)); - fflush(stdout); - } -#endif - res_result = ResolveClassConstantFromClass2(fieldclass(&mb->fb), - operand, cc->ee, 1 << CONSTANT_Methodref, FALSE); -#if COMPILE_DEBUG - if (compile_debug) { - printf(" resolving cp[%d] done.\n", operand); - if (exceptionOccurred(cc->ee)) { - JHandle *exc = cc->ee->exception.exc; - printf("exception occurred: %s\n", - cbName(exc->methods->classdescriptor)); - showExcStackTrace(exc); - } - fflush(stdout); - } -#endif - if (!res_result) { - code_opcode = opc_throw_noclassdef; - exceptionClear(cc->ee); - } - } - - if (code_opcode != opc_throw_noclassdef) { - method = constant_pool[operand].mb; - - if (method->fb.access & (ACC_PRIVATE | ACC_FINAL)) { -#ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" adjust invokevirtual private method to invokespecial.\n"); - } -#endif - code_opcode = opc_invokespecial; - } - } // if (code_opcode != opc_throw_noclassdef) - } -#endif // #if 0 or 1 - - -#if 1 - // translate invokevirtual Object# to invokeignored_quick - if ((code_opcode == opc_invokespecial) || - (code_opcode == opc_invokestatic) || - (code_opcode == opc_invokestatic_quick)) { - struct methodblock *method; - - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { - int res_result; -#if COMPILE_DEBUG - if (compile_debug) { - printf(" resolving cp[%d] type: %d.\n", operand, - CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, operand)); - fflush(stdout); - } -#endif - res_result = ResolveClassConstantFromClass2(fieldclass(&mb->fb), - operand, cc->ee, 1 << CONSTANT_Methodref, FALSE); -#if COMPILE_DEBUG - if (compile_debug) { - printf(" resolving cp[%d] done.\n", operand); - if (exceptionOccurred(cc->ee)) { - JHandle *exc = cc->ee->exception.exc; - printf("exception occurred: %s\n", - cbName(exc->methods->classdescriptor)); - showExcStackTrace(exc); - } - fflush(stdout); - } -#endif - if (!res_result) { - code_opcode = opc_throw_noclassdef; - exceptionClear(cc->ee); - } - } - - if (code_opcode != opc_throw_noclassdef) { - method = constant_pool[operand].mb; - - if (!(method->fb.access & (ACC_NATIVE | ACC_ABSTRACT)) && - (method->code[0] == opc_return)) { - int toNullCheck = (((method->fb.access & ACC_STATIC) == 0) && - strcmp(method->fb.name, "")); - // condition: !static && !constructor - // omit null checks for constructors -#ifdef NO_CHECK - bytepc[0] = code_opcode = opc_invokeignored_static_quick; -#else -# if JDK_VER >= 12 - CODE_LOCK(EE2SysThread(cc->ee)); -# else - BINCLASS_LOCK(); -# endif // JDK_VER - if (toNullCheck) { - bytepc[0] = code_opcode = opc_invokeignored_quick; - bytepc[1] = method->args_size; - bytepc[2] = (unsigned char)toNullCheck; - // indicates whether to be checked or not - } - else { - bytepc[0] = code_opcode = - ((CB_INITIALIZED(fieldclass(&method->fb))) ? - opc_invokeignored_static_quick : opc_invokeignored_static); - } -# if JDK_VER >= 12 - CODE_UNLOCK(EE2SysThread(cc->ee)); -# else - BINCLASS_UNLOCK(); -# endif // JDK_VER -#endif // NO_CHECK - } - } // if (code_opcode != opc_throw_noclassdef) - } -#endif // #if 0 or 1 - #ifdef COMPILE_DEBUG if (compile_debug) { @@ -1667,7 +1683,7 @@ if (codep->last_state != STSTA) { switch (opcode) { - // jump instructions + // jump instructions case opc_goto: case opc_jsr: case opc_ret: @@ -1675,12 +1691,9 @@ case opc_lookupswitch: state = STATE_AFTER_JUMP; break; - // invocation instructions - case opc_invokevirtual: - case opc_invokespecial: - case opc_invokestatic_quick: - case opc_invokestatic: - case opc_invokeinterface: + + // invocation instructions + case opc_inv_core: case opc_invokevirtual_quick: case opc_invokevirtualobject_quick: { @@ -1692,17 +1705,6 @@ struct methodblock *method; CodeInfo *info; - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { - if (!ResolveClassConstantFromClass2( - fieldclass(&cc->mb->fb), operand, cc->ee, - 1 << ((opcode == opc_invokeinterface) ? - CONSTANT_InterfaceMethodref : CONSTANT_Methodref), - FALSE)) { - pctable->opcode = opc_throw_noclassdef; - break; - } - } - method = constant_pool[operand].mb; #ifdef COMPILE_DEBUG if (compile_debug) { @@ -1731,6 +1733,7 @@ state = 4; } break; + default: state = codep->last_state; break; @@ -2351,118 +2354,79 @@ CONST_GETMEMBER(getfield); CONST_GETMEMBER(putfield); + case opc_inv_head: + { + struct methodblock *method = constant_pool[operand].mb; + int32_t args_size = method->args_size; + #ifdef COMPILE_DEBUG -# define WC_CONST_INVOKE_DEBUG1() \ - if (compile_debug) {\ - printf(" not resolved yet.\n"); fflush(stdout);\ - } -# define WC_CONST_INVOKE_DEBUG2() \ - if (compile_debug) {\ - method = constant_pool[operand].mb;\ - printf(" clz initialized: %s\n",\ - (CB_INITIALIZED(fieldclass(&method->fb)) ? "true" : "false"));\ - if (!(method->CompiledCodeInfo)) {\ - printf(" WARNING: CompiledCodeInfo is NULL. (writeCode())\n");\ - fflush(stdout);\ - }\ + if (compile_debug) { + printf(" %s#%s %s\n", cbName(fieldclass(&method->fb)), + method->fb.name, method->fb.signature); + fflush(stdout); } -# define WC_CONST_INVOKE_DEBUG3(VIRTUALP) \ - if (compile_debug) {\ - printf(" %s#%s %s\n", cbName(fieldclass(&method->fb)),\ - method->fb.name, method->fb.signature);\ - fflush(stdout);\ - printf(" args_size, ret_size, localvar_space: %d, %d, %d\n",\ - args_size, ret_size, localvar_space);\ - fflush(stdout);\ - if (VIRTUALP)\ - printf(" offset in table: %d\n", method->fb.u.offset);\ - fflush(stdout);\ +#endif + + memcpy(bufp + constant_table[opcode][state][0], &args_size, 4); + } + break; + + case opc_inv_core: + { + struct methodblock *method = constant_pool[operand].mb; + char *sig; + int32_t args_size, ret_size; + + sig = method->fb.signature; + while (*(sig++) != ')'); + if (*sig == 'V') ret_size = 0; + else if ((*sig == 'D') || (*sig == 'J')) ret_size = 2; + else ret_size = 1; + + args_size = method->args_size; + +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" args_size, ret_size: %d, %d\n", args_size, ret_size); + fflush(stdout); } -#else -# define WC_CONST_INVOKE_DEBUG1() -# define WC_CONST_INVOKE_DEBUG2() -# define WC_CONST_INVOKE_DEBUG3(VIRTUALP) #endif -#define WC_CONST_INVOKE(vop, VIRTUALP, INTERFACEP) \ - {\ - struct methodblock *method;\ - char *sig;\ - int32_t args_size, localvar_space, ret_size;\ - sysAssert(operand != -1);\ - \ - if (*bytepc == opc_invoke##vop) {\ - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) {\ - WC_CONST_INVOKE_DEBUG1();\ - if (!ResolveClassConstantFromClass2(\ - fieldclass(&mb->fb), operand, cc->ee,\ - 1 << (INTERFACEP ?\ - CONSTANT_InterfaceMethodref : CONSTANT_Methodref),\ - FALSE))\ - return 1;\ - }\ - WC_CONST_INVOKE_DEBUG2();\ - }\ - method = constant_pool[operand].mb;\ - args_size = method->args_size;\ - \ - localvar_space = method->nlocals - args_size;\ - if (localvar_space > 0) localvar_space *= 4;\ - else localvar_space = 0;\ - /* nlocals is 0 in the case of native method */\ - \ - sig = method->fb.signature;\ - while (*(sig++) != ')');\ - if (*sig == 'V') ret_size = 0;\ - else if ((*sig == 'D') || (*sig == 'J')) ret_size = 2;\ - else ret_size = 1;\ - \ - WC_CONST_INVOKE_DEBUG3(VIRTUALP);\ - \ - memcpy(bufp + constant_table[opcode][state][0], &args_size, 4);\ - if (VIRTUALP) { /* invokevirtual */\ - uint32_t slot = method->fb.u.offset;\ - memcpy(bufp + constant_table[opcode][state][1], &slot, 4);\ - memcpy(bufp + constant_table[opcode][state][2], &ret_size, 4);\ - memcpy(bufp + constant_table[opcode][state][3], &args_size, 4);\ - }\ - else if (INTERFACEP) { /* invokeinterface */\ - memcpy(bufp + constant_table[opcode][state][3], &ret_size, 4);\ - memcpy(bufp + constant_table[opcode][state][4], &args_size, 4);\ - }\ - else { /* invokespecial, invokestatic */\ - memcpy(bufp + constant_table[opcode][state][2], &localvar_space, 4);\ - memcpy(bufp + constant_table[opcode][state][3], &ret_size, 4);\ - memcpy(bufp + constant_table[opcode][state][4], &args_size, 4);\ - }\ - }\ - break + memcpy(bufp + constant_table[opcode][state][0], &ret_size, 4); + memcpy(bufp + constant_table[opcode][state][1], &args_size, 4); + } + break; case opc_invokevirtual: - WC_CONST_INVOKE(virtual, 1, 0); - - case opc_invokespecial: - WC_CONST_INVOKE(special, 0, 0); + case opc_invokevirtual_obj: + { + struct methodblock *method = constant_pool[operand].mb; + uint32_t slot = method->fb.u.offset; - case opc_invokestatic: - case opc_invokestatic_quick: - WC_CONST_INVOKE(static, 0, 0); +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" offset in table: %d\n", method->fb.u.offset); + fflush(stdout); + } +#endif - case opc_invokeinterface: - WC_CONST_INVOKE(interface, 0, 1); + memcpy(bufp + constant_table[opcode][state][0], &slot, 4); + } + break; - case opc_invokevirtualobject_quick: - case opc_invokevirtual_quick: + case opc_inv_spe_varspace: + case opc_inv_stq_varspace: { - uint32_t slot = bytepc[1]; - int32_t localvar_space = 0; // can't get this information !!! - int32_t args_size = bytepc[2]; - int32_t ret_size = 0; // can't get this information !!! + struct methodblock *method = constant_pool[operand].mb; + int32_t localvar_space; - memcpy(bufp + constant_table[opcode][state][0], &args_size, 4); - memcpy(bufp + constant_table[opcode][state][1], &localvar_space, 4); - memcpy(bufp + constant_table[opcode][state][2], &slot, 4); - memcpy(bufp + constant_table[opcode][state][3], &ret_size, 4); + localvar_space = method->nlocals - method->args_size; + if (localvar_space > 0) + localvar_space *= 4; + else + localvar_space = 0; // nlocals is 0 in the case of native method + + memcpy(bufp + constant_table[opcode][state][0], &localvar_space, 4); } break; @@ -2501,16 +2465,16 @@ case opc_invokeignored_static: case opc_invokeignored_static_quick: { - int32_t index = GET_UINT16(bytepc + 1); struct methodblock *method; int32_t args_size; - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) + sysAssert(operand != -1); + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) if (!ResolveClassConstantFromClass2( - fieldclass(&mb->fb), index, cc->ee, + fieldclass(&mb->fb), operand, cc->ee, (1 << CONSTANT_Methodref) | (1 << CONSTANT_InterfaceMethodref), FALSE)) return 1; - method = constant_pool[index].mb; + method = constant_pool[operand].mb; args_size = method->args_size; #ifdef COMPILE_DEBUG if (compile_debug) { @@ -2787,67 +2751,56 @@ } break; -#if defined(INITCLASS_IN_COMPILING) || defined(NO_REWRITE) -# define CALL_INITCLASS_INVOKE \ - {\ - ClassClass *cb = fieldclass(&method->fb);\ - if (!CB_INITIALIZED(cb)) InitClass(cb);\ + case opc_invokevirtual: + case opc_invokevirtual_obj: + case opc_invokespecial: + case opc_invokestatic_quick: + case opc_invokestatic: + case opc_invokeinterface: + { + struct methodblock *method; + + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { + if (!ResolveClassConstantFromClass2( + fieldclass(&mb->fb), operand, cc->ee, + (1 << CONSTANT_InterfaceMethodref) | (1 << CONSTANT_Methodref), + FALSE)) + return 1; } -#else -# define CALL_INITCLASS_INVOKE -#endif + + method = constant_pool[operand].mb; #ifdef COMPILE_DEBUG -# define RC_CONST_INVOKE_DEBUG1 \ - if (compile_debug) {\ - printf(" %s#%s %s\n", cbName(fieldclass(&method->fb)),\ - method->fb.name, method->fb.signature);\ - fflush(stdout);\ + if (compile_debug) { + printf(" %s#%s %s\n", cbName(fieldclass(&method->fb)), + method->fb.name, method->fb.signature); + fflush(stdout); } -#else -# define RC_CONST_INVOKE_DEBUG1 #endif -#define RC_CONST_INVOKE(vop, VIRTUALP, INTERFACEP) \ - {\ - struct methodblock *method;\ - \ - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) {\ - if (!ResolveClassConstantFromClass2(\ - fieldclass(&mb->fb), operand, cc->ee,\ - 1 << (INTERFACEP ?\ - CONSTANT_InterfaceMethodref : CONSTANT_Methodref),\ - FALSE))\ - return 1;\ - }\ - method = constant_pool[operand].mb;\ - \ - RC_CONST_INVOKE_DEBUG1;\ - \ - CALL_INITCLASS_INVOKE;\ - \ - if (VIRTUALP) { /* invokevirtual */\ - }\ - else if (INTERFACEP) { /* invokeinterface */\ - unsigned char *guessptr = bytepc + 4;\ - memcpy(bufp + constant_table[opcode][state][1], &guessptr, 4);\ - memcpy(bufp + constant_table[opcode][state][2], &method, 4);\ - }\ - else { /* invokespecial, invokestatic */\ - memcpy(bufp + constant_table[opcode][state][1], &method, 4);\ - }\ - }\ - break - - case opc_invokespecial: - RC_CONST_INVOKE(special, 0, 0); - - case opc_invokestatic: - case opc_invokestatic_quick: - RC_CONST_INVOKE(static, 0, 0); +#if defined(INITCLASS_IN_COMPILING) || defined(NO_REWRITE) + { + ClassClass *cb = fieldclass(&method->fb); + if (!CB_INITIALIZED(cb)) InitClass(cb); + } +#endif - case opc_invokeinterface: - RC_CONST_INVOKE(interface, 0, 1); + switch (opcode) { + case opc_invokespecial: + case opc_invokestatic_quick: + case opc_invokestatic: + memcpy(bufp + constant_table[opcode][state][0], &method, 4); + break; + case opc_invokeinterface: + { + unsigned char *guessptr = bytepc + 4; + memcpy(bufp + constant_table[opcode][state][0], &guessptr, 4); + memcpy(bufp + constant_table[opcode][state][1], &method, 4); + } + break; + } + } + break; #ifdef COMPILE_DEBUG # define CONST_NEW_DEBUG1 \ @@ -2973,8 +2926,8 @@ case opc_invokeignored_static: // invokeignored_static_quick doesn't need this process { - int32_t index = GET_UINT16(bytepc + 1); ClassClass *cb; + sysAssert(operand != -1); if (OPT_SETQ(OPT_CODEDB) && !CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { @@ -2983,7 +2936,7 @@ return 1; } - cb = fieldclass(&(constant_pool[index].mb->fb)); + cb = fieldclass(&(constant_pool[operand].mb->fb)); memcpy(bufp + constant_table[opcode][state][0], &cb, 4); } @@ -3016,6 +2969,8 @@ pcentry *tgttable = pctableGet(cc, jptable->tgtoff); unsigned int tgtoff = tgttable->nativeoff; int32_t arg = tgtoff - (argoff + 4); + + unsigned char *p = nativeCode + argoff; #ifdef COMPILE_DEBUG if (compile_debug) { printf("resolveJpInst(): arg. offset: 0x%x(%d)\n", argoff, argoff); @@ -3024,7 +2979,36 @@ fflush(stdout); } #endif - memcpy(nativeCode + argoff, &arg, 4); + memcpy(p, &arg, 4); + + // rewrite `0xe9 XX XX XX XX' to `0xeb XX' +#if 0 + if ((arg >= -132) && (arg <= 124)) // preliminary check +#endif + { + char carg; + if (*(--p) == 0xe9) { + arg += 3; + carg = (char)arg; + + if (arg == ((int32_t)carg)) { // -128 <= (arg + 3) <= 127 + p[0] = 0xeb; p[1] = carg; // 0xeb: jmp XX + p[4] = p[3] = p[2] = 0x90; // 0x90: nop + } + } +#if 0 + else { + arg += 4; + carg = (char)arg; + + if (arg == ((int32_t)carg)) { // -128 <= (arg + 3) <= 127 + p--; + p[0] = p[1] - 0x10; p[1] = carg; // jXX XX + *((int32_t *)(p + 2)) = 0x909002eb; // 0x90: nop + } + } +#endif + } jptable++; } @@ -3089,9 +3073,13 @@ unsigned int exc_off = info->exc_handler_nativeoff; unsigned int arg_off; int32_t relative_off; + + unsigned char *p; + while (jumpexc_table[opcode][state][i] > 0) { arg_off = entry->nativeoff + jumpexc_table[opcode][state][i]; relative_off = exc_off - (arg_off + 4); + p = nativeCode + arg_off; #ifdef COMPILE_DEBUG if (compile_debug) { printf(" res. jump to exc.handler at 0x%x(%d) + %d: 0x%x(%d)\n", @@ -3100,7 +3088,21 @@ fflush(stdout); } #endif - memcpy(nativeCode + arg_off, &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; + + 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++; } } @@ -3111,9 +3113,13 @@ 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; #ifdef COMPILE_DEBUG if (compile_debug) { printf(" res. jump to fin.of method at 0x%x(%d) + %d: 0x%x(%d)\n", @@ -3122,7 +3128,21 @@ fflush(stdout); } #endif - memcpy(nativeCode + arg_off, &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; + + 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.1/gentable.rb shujit/gentable.rb --- shujit-0.6.1/gentable.rb Tue Aug 15 18:20:14 2000 +++ shujit/gentable.rb Fri Aug 25 20:40:49 2000 @@ -4,7 +4,7 @@ CONST_C_FNAME = 'constants.c' CONST_H_FNAME = 'constants.h' -NOPCODES = 323 +NOPCODES = 333 NSTATES = 5 STANY = 5 STSTA = 5 diff -aruN shujit-0.6.1/invoker.c shujit/invoker.c --- shujit-0.6.1/invoker.c Mon Aug 21 04:12:22 2000 +++ shujit/invoker.c Sat Aug 26 13:14:58 2000 @@ -588,11 +588,8 @@ if ((!strcmp(cbName(fieldclass(&mb->fb)), "sun/tools/java/Constants")) && (!strcmp(mb->fb.name, ""))) runtime_debug = 1; - else if ((!strcmp(cbName(fieldclass(&mb->fb)), "javax/media/Manager")) - && (!strcmp(mb->fb.name, "createPlayerForContent"))) - runtime_debug = 1; - else if ((!strcmp(cbName(fieldclass(&mb->fb)), "javax/media/Manager")) - && (!strcmp(mb->fb.name, "createPlayer"))) + else if ((!strcmp(cbName(fieldclass(&mb->fb)), "java/lang/System")) + && (!strcmp(mb->fb.name, "getProperty"))) runtime_debug = 1; else if ((!strcmp(cbName(fieldclass(&mb->fb)), "com/sun/media/protocol/file/DataSource")) && (!strcmp(mb->fb.name, "connect"))) @@ -600,15 +597,15 @@ else if ((!strcmp(cbName(fieldclass(&mb->fb)), "java/lang/Thread")) && (!strcmp(mb->fb.name, "init"))) runtime_debug = 1; - else if ((!strcmp(cbName(fieldclass(&mb->fb)), "java/lang/System")) - && (!strcmp(mb->fb.name, "getSecurityManager"))) - runtime_debug = 1; else if ((!strcmp(cbName(fieldclass(&mb->fb)), "java/lang/ThreadGroup")) && (!strcmp(mb->fb.name, "uncaughtException"))) runtime_debug = 1; + else if ((!strcmp(cbName(fieldclass(&mb->fb)), "java/security/Security")) + && (!strcmp(mb->fb.name, "initialize"))) + runtime_debug = 1; else if (!strcmp(mb->fb.name, "dtoa")) runtime_debug = 1; -#if 1 +#if 0 else if (!strcmp(mb->fb.name, "main")) runtime_debug = 1; else if (!strcmp(mb->fb.name, "start")) diff -aruN shujit-0.6.1/opcodes_internal.h shujit/opcodes_internal.h --- shujit-0.6.1/opcodes_internal.h Thu Aug 17 02:41:19 2000 +++ shujit/opcodes_internal.h Sat Aug 26 14:24:32 2000 @@ -100,7 +100,7 @@ #define opc_ceil 315 // for OPTIMIZE_INTERNAL_CODE -#define opc_fload_fld 316 +#define opc_fload_fld 316 // 0x13c #define opc_dload_dld 317 #define opc_faload_fld 318 #define opc_daload_dld 319 @@ -108,6 +108,20 @@ #define opc_istld 320 #define opc_lstld 321 -#define opc_direct_invoke 322 +#define opc_direct_invoke 322 // 0x142 -#define NOPCODES 323 +#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 + +#define opc_inv_stq_obj 331 +#define opc_inv_stq_varspace 332 + +#define NOPCODES 333 diff -aruN shujit-0.6.1/txt/benchmark-PJ2X3 shujit/txt/benchmark-PJ2X3 --- shujit-0.6.1/txt/benchmark-PJ2X3 Wed Aug 16 22:50:43 2000 +++ shujit/txt/benchmark-PJ2X3 Tue Aug 22 04:24:04 2000 @@ -3,8 +3,8 @@ [TYA 付属のもの] - interp. TYA17 Inp1213 000423 000429 -Sieve 120 589 1100 622 634 + interp. TYA17 Inp1213 000423 000429 000822 +Sieve 120 589 1100 622 634 627 [Linpack Benchmark -- Java Version] @@ -14,6 +14,7 @@ shuJIT-000429 7.803 0.09 shuJIT-000706 7.893 0.09 shuJIT-000816 9.035 0.08 +shuJIT-000822 9.035 0.08 TYA-1.7 11.444 0.06 OpenJIT-1.1.10 12.956 0.05 Inprise-1.2.13 9.81 0.07 @@ -48,14 +49,14 @@ Dialog 84 82 83 96 85 150 119 CM3 980 952 981 984 960 1048 979 - 000816 -Sieve 2007 -Loop 3348 -Logic 4401 -String 1844 -Float 2024 -Method 1508 -Graphics 346 -Image 513 -Dialog 126 -CM3 1157 + 000816 000822 +Sieve 2007 1996 +Loop 3348 3346 +Logic 4401 4912 +String 1844 1867 +Float 2024 1920 +Method 1508 1672 +Graphics 346 343 +Image 513 518 +Dialog 126 121 +CM3 1157 1173 diff -aruN shujit-0.6.1/txt/memo shujit/txt/memo --- shujit-0.6.1/txt/memo Sun Aug 13 17:40:29 2000 +++ shujit/txt/memo Tue Aug 22 14:25:31 2000 @@ -1,15 +1,12 @@ Todo + - private メンバへのアクセス時に NoClassDefFoundError を発生させてしまうのを + きちんと IllegalAccessError にする。 - 特定メソッドの inlining。 profiling (javac, Linpack 等) に基づいて。 System#arraycopy, Object#getClass, Object#hashCode Math#sin,cos,..., StringBuffer#append % (fmod) - FreeBSD 2.2.8R (cucumber) でコンパイル。 - - invokevirtual を invokespecial に変換。 - - メソッド呼び出しの overhead 削減。 - スタック積み直しを削減。 - native method を呼ぶ際に restack を減らせる? - JIT の frame にする。 - JVM Debugger Interface, JVMProfiler Interface の各種イベントを発生させる。 #ifdef HPROF if (jvmpi_event_flags & JVMPI_EVENT_METHOD_ENTRY_ON) { @@ -18,11 +15,9 @@ #endif /* HPROF */ - コンパイル中のメソッドが呼ばれた場合の対策。 インタプリタで実行され、_quick への変換が起こり、pctable と食い違う。 - - SIGNAL_ERROR* に渡す STATE がおそらく適切ではない。直す。 - sysMalloc(), sysRealloc() の例外処理。 - SunOS 5, Win32 に移植。 - SignalError() の第 3引数として文字列を渡しているものをチェック。 - - JMP 命令の、E9 (引数 4 バイト) から EB (引数 1 バイト) への書き換え - UseLosslessQuickOpcodes = FALSE でよいようにする。 invokevirtual{,object}_quick で無理がある。 インタプリタに実行させた場合に、optop が返り値の分増やされない @@ -71,6 +66,12 @@ javac の、フックをかけられる箇所を探す。-> Jikes を改造? Done + - JMP 命令の、E9 (引数 4 バイト) から EB (引数 1 バイト) への書き換え + - メソッド呼び出しの overhead 削減。 + スタック積み直しを削減。 + native method を呼ぶ際に restack を減らせる? + JIT の frame にする。 + - invokevirtual を invokespecial に変換。 - exception_handler の処理をメソッドごとにコピーしないようにする。 - ループの先頭を 16バイト境界に align。 - java.lang.Math#exp を inlining しないように戻す。