diff -aruN shujit-0.3.2/ChangeLog shujit/ChangeLog --- shujit-0.3.2/ChangeLog Sat Jul 31 23:04:12 1999 +++ shujit/ChangeLog Fri Aug 6 18:35:58 1999 @@ -1,5 +1,32 @@ $Id$ +[19990806] + +tableswitch 命令のジャンプ先表を作成した後、 +コード生成バッファへのポインタを誤って設定していた。修整。 +(compile.c) + +0.3.3 リリース。 + +[19990804] + +compiled method からのメソッド呼び出し (invocationHelper()) で、 +mb->invoker が compileAndInvokerMethod() だった際にも +restack (native -> interpreter) するようにした。 +compileAndInvokerMethod() で JIT コンパイルが起きた場合に +restack が 2度起きて悲しいが、コンパイルしない場合のために。 +(runtime.c) + +[19990803] + +オプション (環境変数 JAVA_COMPILER_OPT) の parse 方法を変更。 +(compiler.c, compiler.h) + +オプション cmplthreshold を用意。 +cmplthreshold=<整数> と設定すると、メソッドはその回数呼ばれた時点で +コンパイルされる。 +(compiler.c, compiler.h, invoker.c) + [19990731] 浮動少数点数を整数に変換する [fd]2[il] 命令の pre-assembled code を変更した。 diff -aruN shujit-0.3.2/code.c shujit/code.c --- shujit-0.3.2/code.c Sat Jul 31 17:59:33 1999 +++ shujit/code.c Fri Aug 6 18:00:34 1999 @@ -3160,7 +3160,7 @@ if (runtime_debug) {\ DEBUG_IN;\ asm("pushl %eax\n\tpushl %edi\n\tpushl " #INDEX);\ - PUSH_CONSTSTR(" index: %d (%d - %d)\n");\ + PUSH_CONSTSTR(" index: %d [%d:%d]\n");\ asm("call " SYMBOL(printf) "@PLT\n\t"\ "addl $16,%esp");\ DEBUG_OUT;\ diff -aruN shujit-0.3.2/compile.c shujit/compile.c --- shujit-0.3.2/compile.c Sat Jul 31 19:19:03 1999 +++ shujit/compile.c Fri Aug 6 17:58:14 1999 @@ -104,10 +104,10 @@ #endif #ifdef CODE_DB - if (opt_codedb) { + if (OPT_SETQ(OPT_CODEDB)) { if (readCompiledCode(db, db_page, cc)) goto static_part_done; - } /* if (opt_codedb) */ + } /* if (OPT_CODEDB) */ #endif /* CODE_DB */ /* compile */ @@ -137,7 +137,7 @@ } #ifdef CODE_DB - if (opt_codedb) + if (OPT_SETQ(OPT_CODEDB)) writeCompiledCode(db, db_page, cc); #endif /* CODE_DB */ @@ -159,13 +159,13 @@ /* write code size */ - if (opt_codesize) { + if (OPT_SETQ(OPT_CODESIZE)) { static FILE *sizefp = NULL; if (!sizefp) { if (!(sizefp = fopen(CODESIZE_FNAME, "w"))) { perror("fopen"); - opt_codesize = 0; + OPT_RESET(OPT_CODESIZE); goto codesize_open_failed; } @@ -195,7 +195,7 @@ /* write generated code to the file code_.c */ - if (opt_outcode) { + if (OPT_SETQ(OPT_OUTCODE)) { FILE *codefp; char funcname[256]; char fname[256]; @@ -303,7 +303,9 @@ int32_t byteoff = 0; CodeInfo *info = (CodeInfo *)(mb->CompiledCodeInfo); - int32_t called_count = info->called_count; +#if 0 + int32_t invocation_count = info->invocation_count; +#endif int remaked = 0; /* makePCTable() is retried once at least */ int opcode; @@ -357,7 +359,8 @@ break; } - if (!remaked && (info->called_count > called_count)) { +#if 0 /* This condition will never happen */ + if (!remaked && (info->invocation_count > invocation_count)) { /* The method being compiled is called. */ /* It's possible that bytecode of the method is changed ! */ #ifdef COMPILE_DEBUG @@ -373,6 +376,7 @@ remaked = 1; goto makepctable_start; } +#endif } dummy_byteoff = ~(1 << 31); @@ -405,7 +409,7 @@ CodeTable *codep; #ifdef COMPILE_DEBUG - printf("procAnOpc(): %s(0x%02x,%d), st: %d\n", + printf("procAnOpc(): %s(0x%02x,%d) st:%d\n", ((opcode > opc_nonnull_quick) ? "(null)" : opcode_symbol[opcode]), opcode, opcode, state); printf(" b off: 0x%x(%d)\n", *byteoffp, *byteoffp); @@ -690,7 +694,7 @@ pctableAdd(cc, code_opcode, state, *byteoffp, -1); codep = &code_table[code_opcode][state]; #ifdef COMPILE_DEBUG - printf(" next st: %d\n", codep->after_state); fflush(stdout); + printf(" next st:%d\n", codep->after_state); fflush(stdout); #endif @@ -809,7 +813,7 @@ bytepc = mb->code + pctable->byteoff; #ifdef COMPILE_DEBUG - printf("writeCode(): %s(0x%02x,%d), st: %d\n", + printf("writeCode(): %s(0x%02x,%d) st:%d\n", ((opcode > opc_nonnull_quick) ? "(null)" : opcode_symbol[opcode]), opcode, opcode, state); printf(" off: b 0x%x(%d) n 0x%x(%d)\n", @@ -1489,7 +1493,7 @@ nativeoff = pctable->nativeoff; #ifdef COMPILE_DEBUG - printf("resolveDynConst(): %s(0x%02x,%d), st: %d\n", + printf("resolveDynConst(): %s(0x%02x,%d) st:%d\n", ((opcode > opc_nonnull_quick) ? "(null)" : opcode_symbol[opcode]), opcode, opcode, state); printf(" off: b 0x%x(%d) n 0x%x(%d)\n", @@ -1879,8 +1883,8 @@ int byteoff = pctable->byteoff; int nativeoff = pctable->nativeoff; - printf("resERS(): %s(0x%02x,%d), st: %d\n", - ((opcode > opc_nonnull_quick) ? "(null)" : opcode_symbol[opcode]), + printf("resERS(): %s(0x%02x,%d) st:%d\n", + ((opcode > opc_nonnull_quick)?"(null)":opcode_symbol[opcode]), opcode, opcode, state); printf(" off: b 0x%x(%d) n 0x%x(%d)\n", byteoff, byteoff, nativeoff, nativeoff); @@ -1888,7 +1892,6 @@ } #endif - /* resolve PC in bytecode */ i = 0; if (bytepc_table[opcode][state][i] > 0) { @@ -2014,7 +2017,7 @@ tblp += 2; } - cc->bufp = (unsigned char *)(tblp + (h - l + 1) * 2); + cc->bufp = (unsigned char *)tblp; } break; case opc_lookupswitch: diff -aruN shujit-0.3.2/compiler.c shujit/compiler.c --- shujit-0.3.2/compiler.c Sat Jul 31 22:39:28 1999 +++ shujit/compiler.c Thu Aug 5 03:06:09 1999 @@ -21,7 +21,7 @@ $Id$ */ -#include /* for getenv() */ +#include /* for getenv(),atoi() */ #include /* for gdbm_open(), stat() */ #include /* for stat() */ @@ -77,16 +77,21 @@ int db_page = -1; #endif /* CODE_DB */ -int opt_quiet = 0; -int opt_outcode = 0; -int opt_codesize = 0; -int opt_dontcmplvmcls = 0; -int opt_igndisable = 0; -int opt_cmplclinit = 0; +struct bool_opt_entry { char *name; int num; }; +struct bool_opt_entry bool_opt_entry[] = { + {"quiet", OPT_QUIET}, + {"outcode", OPT_OUTCODE}, + {"codesize", OPT_CODESIZE}, + {"dontcmplvmclz", OPT_DONTCMPLVMCLZ}, + {"igndisable", OPT_IGNDISABLE}, #ifdef CODE_DB -int opt_codedb = 0; + {"codedb", OPT_CODEDB}, #endif /* CODE_DB */ -int opt_cmplatload = 0; + {"cmplatload", OPT_CMPLATLOAD}, + {NULL, -1} +}; +int options = 0; +int opt_cmplthreshold = 0; void *sym_compileAndInvokeMethod, *sym_invokeJITCompiledMethod; void *sym_invokeJavaMethod, *sym_invokeSynchronizedJavaMethod; @@ -136,7 +141,7 @@ static HObject *compilerCommand(HObject *); #define INITIALIZE_METHOD(MB) \ - if (opt_cmplclinit || strcmp((MB)->fb.name, "")) {\ + if (OPT_SETQ(OPT_CMPLCLINIT) || strcmp((MB)->fb.name, "")) {\ (MB)->invoker = sym_compileAndInvokeMethod;\ (MB)->CompiledCode = NULL;\ } @@ -215,38 +220,19 @@ opt = strtok(opts, ", "); while (opt) { - if (!strncmp(opt, "quiet", 6)) { - opt_quiet = 1; - } - else if (!strncmp(opt, "outcode", 8)) { - opt_outcode = 1; - if (!opt_quiet) printf(" option: outcode\n"); - } - else if (!strncmp(opt, "codesize", 9)) { - opt_codesize = 1; - if (!opt_quiet) printf(" option: codesize\n"); - } - else if (!strncmp(opt, "dontcmplvmcls", 14)) { - opt_dontcmplvmcls = 1; - if (!opt_quiet) printf(" option: dontcmplvmcls\n"); - } - else if (!strncmp(opt, "igndisable", 11)) { - opt_igndisable = 1; - if (!opt_quiet) printf(" option: igndisable\n"); - } - else if (!strncmp(opt, "cmplclinit", 11)) { - opt_cmplclinit = 1; - if (!opt_quiet) printf(" option: cmplclinit\n"); - } -#ifdef CODE_DB - else if (!strncmp(opt, "codedb", 7)) { - opt_codedb = 1; - if (!opt_quiet) printf(" option: codedb\n"); + int i = 0; + char *opt_name; + while (opt_name = bool_opt_entry[i].name, opt_name) { + if (!strcmp(opt, opt_name)) { + OPT_SET(bool_opt_entry[i].num); + if (!OPT_SETQ(OPT_QUIET)) printf(" option: %s\n", opt_name); + } + i++; } -#endif /* CODE_DB */ - else if (!strncmp(opt, "cmplatload", 11)) { - opt_cmplatload = 1; - if (!opt_quiet) printf(" option: cmplatload\n"); + if (!strncmp(opt, "cmplthreshold=", 14)) { + opt_cmplthreshold = atoi(opt+14); + if (!OPT_SETQ(OPT_QUIET)) + printf(" option: cmplthreshold = %d\n", opt_cmplthreshold); } opt = strtok(NULL, ", "); } @@ -255,7 +241,7 @@ /* show credit */ - if (!opt_quiet) { + if (!OPT_SETQ(OPT_QUIET)) { fprintf(stderr, CREDIT); fflush(stderr); } @@ -432,7 +418,7 @@ /* initialize the classes which is already loaded */ - if (!opt_dontcmplvmcls) { + if (!OPT_SETQ(OPT_DONTCMPLVMCLZ)) { ClassClass **clazzptr; int i; @@ -473,7 +459,7 @@ *(char **)vector[5] = (char *)compileClass; *(char **)vector[6] = (char *)compileClasses; #ifndef IGNORE_DISABLE - if (!opt_igndisable) { + if (!OPT_SETQ(OPT_IGNDISABLE)) { *(char **)vector[7] = (char *)compilerEnable; *(char **)vector[8] = (char *)compilerDisable; } @@ -504,7 +490,7 @@ *ji6->p_CompilerCompileClass = compileClass; *ji6->p_CompilerCompileClasses = compileClasses; #ifndef IGNORE_DISABLE - if (!opt_igndisable) { + if (!OPT_SETQ(OPT_IGNDISABLE)) { *ji6->p_CompilerEnable = compilerEnable; *ji6->p_CompilerDisable = compilerDisable; } @@ -519,7 +505,7 @@ #ifdef CODE_DB /* open DB and page file */ - if (opt_codedb) { + if (OPT_SETQ(OPT_CODEDB)) { void *dl_dbm; if (!(dl_dbm = dlopen(LIBDBM, RTLD_LAZY))) { fputs(dlerror(), stderr); fputc('\n', stderr); @@ -568,7 +554,7 @@ goto codedb_init_done; codedb_init_fail: - fprintf(stderr, "disable codedb.\n"); opt_codedb = 0; + fprintf(stderr, "disable codedb.\n"); OPT_RESET(OPT_CODEDB); if (db_page >= 0) close(db_page); JVM_Exit(1); codedb_init_done: @@ -625,7 +611,7 @@ } #endif - if (opt_cmplatload) { + if (OPT_SETQ(OPT_CMPLATLOAD)) { compileClass(cb); return; } @@ -676,7 +662,7 @@ uint32_t jump_target = 0; #endif /* EXC_BY_SIGNAL */ -#ifdef RUNTIME_DEBUG +#if defined(RUNTIME_DEBUG) || defined(COMPILE_DEBUG) printf("Signal handler: %d (sys_thread_t: %x)\n", sig, (int)sysThreadSelf()); showStackFrames(EE()); #endif diff -aruN shujit-0.3.2/compiler.h shujit/compiler.h --- shujit-0.3.2/compiler.h Sat Jul 31 19:32:47 1999 +++ shujit/compiler.h Wed Aug 4 02:43:55 1999 @@ -307,7 +307,7 @@ #endif /* EXC_BY_SIGNAL */ typedef struct compiled_code_info { - int32_t called_count; + int32_t invocation_count; int32_t code_size; int32_t ret_size; @@ -396,25 +396,32 @@ extern int db_page; #endif /* CODE_DB */ -extern int opt_quiet; +#define OPT_SET(N) (options |= (1 << (N))) +#define OPT_RESET(N) (options & ~(1 << (N))) +#define OPT_SETQ(N) (options & (1 << (N))) +enum opt_bit { + OPT_QUIET = 0, /* suppress initial message and some outputs */ -extern int opt_outcode; + OPT_OUTCODE, /* write generated code to code__.s */ -extern int opt_codesize; + OPT_CODESIZE, /* write code size of each methods to the file jit_codesize */ -extern int opt_dontcmplvmcls; + OPT_DONTCMPLVMCLZ, /* suppress compilation classes which is already loaded when JIT is initialized */ -extern int opt_igndisable; + OPT_IGNDISABLE, /* make java.lang.Compiler#disable() void */ -extern int opt_cmplclinit; + OPT_CMPLCLINIT, /* compile class initializer */ #ifdef CODE_DB -extern int opt_codedb; + OPT_CODEDB, /* save and re-use generated native code */ #endif /* CODE_DB */ -extern int opt_cmplatload; + OPT_CMPLATLOAD /* compile the whole class when the class is loaded */ +}; +extern int options; +extern int opt_cmplthreshold; extern void *sym_compileAndInvokeMethod; extern void *sym_invokeJITCompiledMethod; diff -aruN shujit-0.3.2/invoker.c shujit/invoker.c --- shujit-0.3.2/invoker.c Sat Jul 31 22:35:41 1999 +++ shujit/invoker.c Fri Aug 6 18:10:13 1999 @@ -44,8 +44,8 @@ JHandle *o, struct methodblock *mb, int args_size, ExecEnv *ee) { int access; int compilation_result; - MONITOR_T key; + int invocation_count; key = obj_monitor(fieldclass(&mb->fb)); @@ -64,29 +64,21 @@ #endif #endif - /* add a counter */ - ((CodeInfo *)mb->CompiledCodeInfo)->called_count++; - - /* call original invoker - if compiler is disabled or the method is being compiled now */ access = mb->fb.access; -#ifndef IGNORE_DISABLE - if (!compiler_enabled) { -#ifdef COMPILE_DEBUG - printf("now call original invoker: %s\n %s#%s %s\n", - nameOfInvoker(access2invoker(access)), - cbName(mb->fb.clazz), mb->fb.name, mb->fb.signature); - fflush(stdout); -#endif - goto candi_call_normal_method; - } -#endif /* IGNORE_DISABLE */ /* compile the called method */ monitorEnter2(ee, key); { bool_t (*invoker)(JHandle*,struct methodblock *,int,ExecEnv*); + /* add a counter */ + invocation_count = ((CodeInfo *)mb->CompiledCodeInfo)->invocation_count; + invocation_count++; + ((CodeInfo *)mb->CompiledCodeInfo)->invocation_count = invocation_count; +#ifdef COMPILE_DEBUG + printf(" invocation count: %d\n", invocation_count); fflush(stdout); +#endif + invoker = mb->invoker; if (invoker == sym_invokeJITCompiledMethod) { #ifdef COMPILE_DEBUG @@ -95,14 +87,18 @@ monitorExit2(ee, key); goto compilation_done; } - else if (invoker != sym_compileAndInvokeMethod) { -#ifdef COMPILE_DEBUG - printf(" being compiled.\n"); fflush(stdout); -#endif + else if ((invoker != sym_compileAndInvokeMethod) /* being compiled */ + || (invocation_count < opt_cmplthreshold) +#ifndef IGNORE_DISABLE + || (!compiler_enabled) /* compiler is disabled */ +#endif /* IGNORE_DISABLE */ + ) { monitorExit2(ee, key); goto candi_call_normal_method; } } + + /* compile */ #ifdef REENTER_DEBUG mb->invoker = redirectInvoker; #else @@ -148,6 +144,11 @@ bool_t invoker_ret; norm_invoker = access2invoker(access); +#ifdef COMPILE_DEBUG + printf("call original invoker: %s\n", + nameOfInvoker(norm_invoker)); + fflush(stdout); +#endif invoker_ret = norm_invoker(o, mb, args_size, ee); if (!invoker_ret) return FALSE; @@ -298,7 +299,7 @@ #endif /* RUNTIME_DEBUG */ /* add a counter */ - ((CodeInfo *)mb->CompiledCodeInfo)->called_count++; + ((CodeInfo *)mb->CompiledCodeInfo)->invocation_count++; old_frame = ee->current_frame; access = mb->fb.access; @@ -375,8 +376,9 @@ prev_method = old_frame->current_method; if (prev_method) { unsigned char *prev_returnpc = old_frame->returnpc; - if ((prev_returnpc > prev_method->code) && - ((prev_method->code + prev_method->code_length) <= prev_returnpc)) { + if (prev_returnpc && + ((prev_returnpc < prev_method->code) || + ((prev_method->code + prev_method->code_length) <= prev_returnpc))) { /* called by compiled method */ frame->vars = (stack_item *)prev_returnpc; goto restack2native_done; @@ -572,17 +574,7 @@ && (!strcmp(mb->fb.name, "exit"))) runtime_debug = 1; - else if ((!strcmp(cbName(mb->fb.clazz), "Matrix3D"))) - runtime_debug = 1; - else if ((!strcmp(cbName(mb->fb.clazz), "ThreeD"))) - runtime_debug = 1; #endif - else if ((!strcmp(cbName(mb->fb.clazz), "Model3D")) - && (!strcmp(mb->fb.name, "transform"))) - runtime_debug = 1; - else if ((!strcmp(cbName(mb->fb.clazz), "sun/java2d/SunGraphics2D")) - && (!strcmp(mb->fb.name, "setComposite"))) - runtime_debug = 1; else if (!strcmp(mb->fb.name, "main")) runtime_debug = 1; diff -aruN shujit-0.3.2/rate_codesize.rb shujit/rate_codesize.rb --- shujit-0.3.2/rate_codesize.rb Sun Jan 24 12:20:05 1999 +++ shujit/rate_codesize.rb Wed Aug 4 23:16:29 1999 @@ -10,6 +10,7 @@ filename = 'jit_codesize' +nmethod = 0 ninst = 0 byte_size = 0 native_size = 0 @@ -29,6 +30,7 @@ next if /^#/ chomp!() elems = split() + nmethod += 1 ninst += elems[0].to_i() byte_size += elems[1].to_i() native_size += elems[2].to_i() @@ -38,6 +40,7 @@ f.close end +print "num of compiled method: #{nmethod}\n" print "num of byte code inst: #{ninst}\n" print "byte code size (byte): #{byte_size}\n" print "native code size (byte): #{native_size}\n" diff -aruN shujit-0.3.2/runtime.c shujit/runtime.c --- shujit-0.3.2/runtime.c Sat Jul 31 19:19:54 1999 +++ shujit/runtime.c Thu Aug 5 18:54:06 1999 @@ -208,20 +208,15 @@ /* obj is required for enter/exit a monitor of the object. */ #endif - if ((invoker == sym_invokeJITCompiledMethod) || - ((invoker == sym_compileAndInvokeMethod) -#ifndef IGNORE_DISABLE - && compiler_enabled -#endif - )) { - /* the method will be compiled, if invoker is compileAnd...() */ - /* compiled method */ - cur_frame->returnpc = (unsigned char *)var_base; + cur_frame->returnpc = (unsigned char *)var_base; + if (invoker == sym_invokeJITCompiledMethod) { + /* Surely the compiled method is called */ CALL_INVOKER; } else { - /* normal Java or native method */ + /* normal Java or native method + or call compileAndInvokeMethod() */ /* restack from native stack to JVM stack */ stack_item *sp = var_base; stack_item *optop = cur_frame->optop; @@ -287,7 +282,7 @@ } #endif } /* normal Java method */ - } /* normal Java or native method */ + } /* normal Java or native method or compileAndInvokeMethod() */ #ifdef RUNTIME_DEBUG if (runtime_debug) {