diff -aruN shujit-0.4.2/ChangeLog shujit/ChangeLog --- shujit-0.4.2/ChangeLog Mon Feb 21 20:05:58 2000 +++ shujit/ChangeLog Tue Apr 25 19:30:35 2000 @@ -1,5 +1,126 @@ $Id$ +[20000425] + +0.5.0 リリース。 + +[20000424] + +basic block を認識するようにした。 +makeBlockStruct() (in compile.c) を用意。 +peephole 最適化の際に基本ブロックをまたいでの最適化を抑制するため。 +(compile.c, compiler.h, optimize.c) + +[20000423] + +内部命令が保持するバイトコード上のプログラムカウンタを、 +バイトコード命令としては存在しない命令についても +きちんとした値が入るようにした。 +processAnOpcode() (in compile.c) のインタフェースを変更。 +ジャンプ先がきちんとあるバイトコード命令の先頭を指すように。 +(compile.c, compiler.h) + +内部命令表のエントリを削除する pctableDelete(), pctableNDelete() (computil.c) +のバグを修整。 +(computil.c) + +倍精度数の四則演算命令 (dadd, dsub, dmul, ddiv) や +frem などの pre-assembled code を変更。 +最適化しやすいように単精度数と同じ方式にした。 +このために、内部命令 dld8 を追加。 +この変更により、プログラムによっては遅くなった。 +(code.c, compiler.h, compile.c) + +optimize.c に、内部命令を peephole 最適化する関数 +optimizeInternalCode() を用意。 +マクロ OPTIMIZE_INTERNAL_CODE (in compiler.h) で +最適化を行うか否かを制御する。 +(optimize.c, compiler.h) + +FPU のレジスタからメモリへのストア、ロードを combine する最適化を実装。 +Linpack benchmark の結果が 1.11 倍になった。 +(optimize.c) + +[20000422] + +x86 の cdq 命令を movl %eax,%edx, sarl $31,%edx と 2命令に分割。 +しかし整数の除算、剰余命令 (idiv, irem) では +演算にかかる時間が支配的なので性能向上は見えず。 +(code.c) + +compiler.h でマクロ FORCE_DOUBLE_PRECISION が定義された場合、 +JIT 初期化時に丸め精度を倍精度に設定するようにした。 +倍精度に設定することで、デフォルトで拡張精度になっている +JDK 1.1.X for Linux のような環境でも確実に +JLS の規定通りのセマンティクスを達成できる。 +(compiler.h, compiler.c, compile.c, code.c) + +浮動少数点数の四則演算命令 ([fd]{add,sub,mul,div}) を +複数の内部命令に分解した。 +例: 通常は dmul -> dld, dmul, dst +strictfp の場合は dmul -> strict_dprep, dld, +strict_dscdown, dmul, strict_dscup, dst, strict_dsettle +(compiler.h, code.c, compile.c) + +内部命令 fill_cache と逆に、レジスタ %ecx, %edx の内容を +スタックに書き戻す flush_cache 命令を用意。 +(code.c) + +[20000421] + +内部命令を保持する構造体 pcentry に、メンバ operand を追加。 +コンパイルの初期段階で命令のオペランドをここに格納しておく。 +後続パスにて、バイトコードの領域を参照する必要がほとんどなくなった。 +peephole 最適化への布石。 +(compiler.h, compile.c) + +バイトコード命令 [ifa]load_[0123] に対応する内部命令を iload に、 +[ld]store_[0123] に対応する内部命令を lload に変更。 +これまではバイトコード命令 == 内部命令だった。 +(code.c, compile.c) + +sysAssert() を使い始めた。 +(compile.c) + +[20000420] + +内部命令がクラスファイル中の命令と異なる類の命令に +wide prefix が付いていた場合に、内部命令への変換をし損ねていた。 +(see [20000419]) +(compile.c) + +バイトコード命令のカウント方法を修整。(see [19990815]) +構造体 CompilerContext のメンバ ninsn の扱いを変えた。 +(compile.c, computil.c) + +[20000419] + +FreeBSD でも libc, libm を JVM_LoadLibrary() するのを止めた。 +constants.c 中の表 (配列) func_table[][][] 中に直接関数名を書き、 +アドレスはダイナミックリンカに解決してもらうことにしたことに伴う変更。 +(see [19990223]) +(compiler.c) + +processAnOpcode() (in compile.c) での wide 命令群の扱いに問題があった。 +wide prefix が付いた命令を内部命令に変換していなかった。修整。 +[Thanks to 志村さん ] +(compile.c) + +[20000415] + +シンボルの解決方法を変更した。 +これまでは関数名の文字列を constants.c 中の表 (配列) に保持していたところ、 +はじめから表には関数のアドレスを入れておくようにした。 +これに伴い、initFunctionSymbols() (in compile.c) が不要になった。 +[Thanks to 丸山さん ] +(gentable.rb, compile.c, compiler.c) + +[20000330] + +compiler.h でマクロ STRICT_FSCALE_USE_FLOAT が定義されていない場合に +(double 型ではなく) 整数型で scale を用意するようにした。 +(code.c) + [20000221] 0.4.2 リリース。 @@ -1353,7 +1474,7 @@ for subdir in ; do ... と in の後が空だと syntax error になる問題に対処。 bash 1.14.7 では error にならなかった。 -[Thanks bug report to 高橋秀明さん ] +[Thanks 高橋秀明さん for a bug report] (GNUmakefile) [19990109] @@ -1363,7 +1484,7 @@ これまでは 0x0f, 0x0f で区切ってきたのだが、 これが AMD 3D Now! 命令の prefix として使われ、 3D Now! 命令に対応した GNU binutils が出てきたため。 -[Thanks bug report to 高橋秀明さん ] +[Thanks 高橋秀明さん for a bug report] (code.h, gentable.rb) [19990107] @@ -1447,8 +1568,8 @@ egcs 1.0.3 の生成するコードでは問題がなかった。 gcc 2.7.X で code.o を生成する際は、code.s を ruby スクリプト (postcmpl.rb) で修整するようにした。 -[Thanks bug report to 高橋秀明さん , - Justin Wells さん ] +[Thanks 高橋秀明さん + and Justin Wells さん for bug reports] (postcmpl.rb, GNUmakefile) [19981228] diff -aruN shujit-0.4.2/GNUmakefile shujit/GNUmakefile --- shujit-0.4.2/GNUmakefile Mon Feb 21 21:01:17 2000 +++ shujit/GNUmakefile Mon Apr 24 23:45:19 2000 @@ -49,7 +49,7 @@ INCDIR = -I${J_INCDIR} -I${J_INCDIR}/genunix -I${J_INCDIR}/linux -I${J_INCDIR}/freebsd -I/usr/local/include OPTFLAGS = -O2 -CDEBUGFLAGS =# -g -DCOMPILE_DEBUG# -DRUNTIME_DEBUG# -DNO_CHECK +CDEBUGFLAGS =# -g -DDEBUG -DCOMPILE_DEBUG# -DRUNTIME_DEBUG# -DNO_CHECK NOOPTCFLAGS = -pipe -fPIC ${CDEBUGFLAGS} ${INCDIR} CFLAGS = ${OPTFLAGS} ${NOOPTCFLAGS} LIBS = @@ -66,7 +66,7 @@ # source code HDR = compiler.h code.h OBJ = code.o compiler.o signal.o invoker.o computil.o opcodes.o compile.o\ - runtime.o x86tsc.o + runtime.o optimize.o x86tsc.o ifneq (${JDK_VER}, 11) OBJ += linker.o endif diff -aruN shujit-0.4.2/GNUmakefile.in shujit/GNUmakefile.in --- shujit-0.4.2/GNUmakefile.in Mon Dec 27 18:58:18 1999 +++ shujit/GNUmakefile.in Sun Apr 23 19:27:45 2000 @@ -49,7 +49,7 @@ INCDIR = -I${J_INCDIR} -I${J_INCDIR}/genunix -I${J_INCDIR}/linux -I${J_INCDIR}/freebsd -I/usr/local/include OPTFLAGS = -O2 -CDEBUGFLAGS =# -g -DCOMPILE_DEBUG# -DRUNTIME_DEBUG# -DNO_CHECK +CDEBUGFLAGS =# -g -DDEBUG -DCOMPILE_DEBUG# -DRUNTIME_DEBUG# -DNO_CHECK NOOPTCFLAGS = -pipe -fPIC ${CDEBUGFLAGS} ${INCDIR} CFLAGS = ${OPTFLAGS} ${NOOPTCFLAGS} LIBS = @@ -66,7 +66,7 @@ # source code HDR = compiler.h code.h OBJ = code.o compiler.o signal.o invoker.o computil.o opcodes.o compile.o\ - runtime.o x86tsc.o + runtime.o optimize.o x86tsc.o ifneq (${JDK_VER}, 11) OBJ += linker.o endif diff -aruN shujit-0.4.2/README shujit/README --- shujit-0.4.2/README Mon Feb 21 21:38:17 2000 +++ shujit/README Tue Apr 25 19:30:43 2000 @@ -13,8 +13,8 @@ Working on the following platforms is confirmed. - Linux - - Blackdown JDK 1.2.2 RC4, gcc 2.95.2, glibc2.1.2 and Linux 2.2.15pre7 - - JDK 1.1.8v1, gcc 2.95.2, glibc2.1.2 and Linux 2.2.15pre7 + - Blackdown JDK 1.2.2 RC4, gcc 2.95.2, glibc2.1.3 and Linux 2.2.16 pre1 + - JDK 1.1.8v1, gcc 2.95.2, glibc2.1.3 and Linux 2.2.16 pre1 - JDK 1.1.7v1a, egcs 1.1.2, libc5.4.38 and Linux 2.0.35 - FreeBSD @@ -37,9 +37,9 @@ % java -Djava.compiler=shujit ... or set JAVA_COMPILER variable to `shujit'. - If you use C shell compliants, type + If you use C shell compatible shells, type % setenv JAVA_COMPILER shujit - If you use bourne shell compliants, type + If you use bourne shell compatible shells, type % export JAVA_COMPILER=shujit * Compilation @@ -47,6 +47,9 @@ You need some tools to compile this JIT. - JDK 1.1.X or 1.2.X + This JIT can work with JDK Sun's classic VM. + For example, Linux JDK by Blackdown and Sun/Inprise, + and FreeBSD JDK are supported, but IBM JDK is not. - gcc 2.95.X or EGCS (not experimental version such as 2.92.5-19981015) You can examine version of your `gcc' command with -v option. % gcc -v @@ -54,7 +57,7 @@ - objdump (in GNU binutils) Most Linux distributions and ELF FreeBSD systems have it. - Ruby - A script which generate some tables is written in Ruby. + A script which generate some tables was written in Ruby. http://www.ruby-lang.org/ - GNU make @@ -87,6 +90,7 @@ NEYAMA Ryo (test on Linux) MIURA Toshitaka (preparation of FreeBSD) KATO Jun'ya (preparation of FreeBSD) +MARUYAMA Fuyuhiko (discussion and code) and my wife Mari. diff -aruN shujit-0.4.2/code.c shujit/code.c --- shujit-0.4.2/code.c Sun Jan 30 16:05:21 2000 +++ shujit/code.c Mon Apr 24 03:23:32 2000 @@ -39,17 +39,20 @@ /* for strictfp */ #ifdef STRICT_USE_FSCALE # ifdef STRICT_FSCALE_USE_FLOAT + /* exponents of scales */ float double_scale_pos = 15360.0f; /* 16383 - 1023 */ float double_scale_neg = -15360.0f; /* -(16383 - 1023) */ float single_scale_pos = 16256.0f; /* 16383 - 127 */ float single_scale_neg = -16256.0f; /* -(16383 - 127) */ # else -double double_scale_pos = 15360.0; -double double_scale_neg = -15360.0; -double single_scale_pos = 16256.0; -double single_scale_neg = -16256.0; + /* scales in integer */ +int32_t double_scale_pos = 15360; +int32_t double_scale_neg = -15360; +int32_t single_scale_pos = 16256; +int32_t single_scale_neg = -16256; # endif /* STRICT_FSCALE_USE_FLOAT */ #else + /* scales in extended precision floating-point */ unsigned const char double_scale_pos[10] = { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0x7b }; /* 2^ (16383 - 1023) */ unsigned const char double_scale_neg[10] = @@ -126,6 +129,21 @@ FILL_CACHE_DEBUG1(%edx, %ecx); } + CODE(opc_flush_cache, flush_cache, ST0, ST0, 0) { + } + CODE(opc_flush_cache, flush_cache, ST1, ST0, 0) { + asm("pushl %edx"); + } + CODE(opc_flush_cache, flush_cache, ST2, ST0, 0) { + asm("pushl %edx\n\tpushl %ecx"); + } + CODE(opc_flush_cache, flush_cache, ST3, ST0, 0) { + asm("pushl %ecx"); + } + CODE(opc_flush_cache, flush_cache, ST4, ST0, 0) { + asm("pushl %ecx\n\tpushl %edx"); + } + /* to another state */ CODE(opc_stateto0, stateto00, ST0, ST0, 0) {} CODE(opc_stateto0, stateto10, ST1, ST0, 0) { asm("pushl %edx"); } @@ -269,10 +287,9 @@ #ifdef RUNTIME_DEBUG /* write class and method name */ if (runtime_debug) { - register struct methodblock *mb_reg asm("edi"); - DEBUG_IN; - mb_reg = mb; + + asm("movl %0,%%edi" : : "m"(mb)); /* %edi = mb */ asm("movl " METHOD_NAME(%edi) ",%eax\n\t" "testl %eax,%eax\n\t" @@ -492,7 +509,7 @@ "addl $4,%esp") #endif /* JDK_VER */ - CODE(opc_syncenter, syncenter, STANY, STSTA, OPC_THROW) { + CODE(opc_sync_enter, sync_enter, STANY, STSTA, OPC_THROW) { /* monitorEnter(obj_monitor(o)); */ #ifdef SET_FRAME_MONITOR /* frame->monitor = (struct sys_mon *)o */ @@ -503,7 +520,7 @@ #ifdef SET_FRAME_MONITOR asm("movl %eax," FRAME_MONITOR(%edi)); #endif - METAVM_MONITOR(%eax, proxy_monitorenter, "syncenter", 0); + METAVM_MONITOR(%eax, proxy_monitorenter, "sync_enter", 0); OBJ_MONITOR(%eax); #if JDK_VER >= 12 CALL_MONITOR(%eax, monitorEnter2); @@ -514,10 +531,10 @@ } /* exit synchronized method */ - CODE(opc_syncexit, syncexit, STANY, STSTA, 0) { + CODE(opc_sync_exit, sync_exit, STANY, STSTA, 0) { /* monitorExit(obj_monitor(o)); */ asm("movl %0,%%eax" : : "m" (o)); - METAVM_MONITOR(%eax, proxy_monitorexit, "syncexit", 0); + METAVM_MONITOR(%eax, proxy_monitorexit, "sync_exit", 0); OBJ_MONITOR(%eax); #if JDK_VER >= 12 CALL_MONITOR(%eax, monitorExit2); @@ -526,7 +543,7 @@ #endif } - CODE(opc_strictenter, strictenter, STANY, STSTA, 0) { + CODE(opc_strict_enter, strict_enter, STANY, STSTA, 0) { #ifdef STRICT_PRELOAD /* push scales into FPU register */ # ifdef STRICT_USE_FSCALE @@ -534,10 +551,10 @@ asm("flds %0\n\t" : : "m" (single_scale_neg)); asm("flds %0\n\t" : : "m" (double_scale_neg)); # else - asm("fldl %0\n\t" : : "m" (single_scale_neg)); - asm("fldl %0\n\t" : : "m" (double_scale_neg)); + asm("fildl %0\n\t" : : "m" (single_scale_neg)); + asm("fildl %0\n\t" : : "m" (double_scale_neg)); # endif /* STRICT_FSCALE_USE_FLOAT */ -# else +# else /* STRICT_USE_FSCALE */ asm("fldt %0\n\t" : : "m" (*single_scale_neg)); asm("fldt %0\n\t" : : "m" (*single_scale_pos)); asm("fldt %0\n\t" : : "m" (*double_scale_neg)); @@ -546,7 +563,7 @@ #endif /* STRICT_PRELOAD */ } - CODE(opc_strictexit, strictexit, STANY, STSTA, 0) { + CODE(opc_strict_exit, strict_exit, STANY, STSTA, 0) { #ifdef STRICT_PRELOAD /* pop scales from FPU register */ # ifdef STRICT_USE_FSCALE @@ -557,6 +574,7 @@ #endif /* STRICT_PRELOAD */ } +#ifndef FORCE_DOUBLE_PRECISION /* save FPU rounding precision */ CODE(opc_fppc_save, fppc_save, STANY, STSTA, 0) { /* save FPU control word */ @@ -581,6 +599,7 @@ CODE_FPPC(single, "andl $0xfcff,%eax"); CODE_FPPC(double, "andl $0xfcff,%eax\n\torl $0x0200,%eax"); CODE_FPPC(extended, "orl $0x0300,%eax"); +#endif /* ! FORCE_DOUBLE_PRECISION */ /* throw IllegalAccessError */ #define CODE_ILLEGALACCESS(STATE) \ @@ -917,6 +936,25 @@ ILOAD_DEBUG1(%ecx); } +#ifdef OPTIMIZE_INTERNAL_CODE + CODE(opc_fload_fld, fload_fld, STANY, STSTA, 0) { + asm("subl $4,%esp\n\t"); /* to simulate the true value of %esp */ + asm("flds " STR(CONST) "(%esi)"); +#ifdef RUNTIME_DEBUG + if (runtime_debug) { + DEBUG_IN; + asm("subl $8,%esp\n\t" + "fstl (%esp)"); + PUSH_CONSTSTR(" %g\n"); + asm("call " SYMBOL(printf) "@PLT\n\t" + "addl $12,%esp"); + FFLUSH; + DEBUG_OUT; + } +#endif + } +#endif /* OPTIMIZE_INTERNAL_CODE */ + /* lload */ /* const: index * 4, (index + 1) * 4 */ #ifdef RUNTIME_DEBUG @@ -927,9 +965,6 @@ "pushl " #OPTOP2_REG "\n\tpushl " #OPTOP1_REG "\n\t"\ "pushl " #OPTOP2_REG "\n\tpushl " #OPTOP1_REG "\n\t"\ "movl $" STR(CONST) ",%eax\n\t"\ - "sarl $2,%eax\n\t"\ - "negl %eax\n\t"\ - "subl $1,%eax\n\t"\ "pushl %eax");\ PUSH_CONSTSTR(" var[%d]: 0x%016llx, %lld, %g\n");\ asm("call " SYMBOL(printf) "@PLT\n\t"\ @@ -972,73 +1007,24 @@ LLOAD_ST02; } - /* iload_[0-3] */ -#define CODE_ILOAD_N(N, OFF) \ - CODE(opc_iload_##N, [ifa]load_##N, ST0, ST1, 0) {\ - asm("movl " #OFF "(%esi),%edx");\ - BIPUSH_DEBUG1(%edx);\ - }\ - CODE(opc_iload_##N, [ifa]load_##N, ST1, ST2, 0) {\ - asm("movl " #OFF "(%esi),%ecx");\ - BIPUSH_DEBUG1(%ecx);\ - }\ - CODE(opc_iload_##N, [ifa]load_##N, ST2, ST4, 0) {\ - asm("pushl %edx\n\t"\ - "movl " #OFF "(%esi),%edx");\ - BIPUSH_DEBUG1(%edx);\ - }\ - CODE(opc_iload_##N, [ifa]load_##N, ST3, ST4, 0) {\ - asm("movl " #OFF "(%esi),%edx");\ - BIPUSH_DEBUG1(%edx);\ - }\ - CODE(opc_iload_##N, [ifa]load_##N, ST4, ST2, 0) {\ - asm("pushl %ecx\n\t"\ - "movl " #OFF "(%esi),%ecx");\ - BIPUSH_DEBUG1(%ecx);\ - } - - CODE_ILOAD_N(0, ); - CODE_ILOAD_N(1, -4); - CODE_ILOAD_N(2, -8); - CODE_ILOAD_N(3, -12); - - /* lload_[0-3] */ -#define LLOAD_N_ST02(OFF1, OFF2) \ - asm("movl " #OFF1 "(%esi),%ecx\n\t"\ - "movl " #OFF2 "(%esi),%edx");\ - LDC2_W_DEBUG1(%ecx, %edx) -#define LLOAD_N_ST04(OFF1, OFF2) \ - asm("movl " #OFF1 "(%esi),%edx\n\t"\ - "movl " #OFF2 "(%esi),%ecx");\ - LDC2_W_DEBUG1(%edx, %ecx) - -#define CODE_LLOAD_N(N, OFF1, OFF2) \ - CODE(opc_lload_##N, [ld]load_##N, ST0, ST2, 0) {\ - LLOAD_N_ST02(OFF1, OFF2);\ - }\ - CODE(opc_lload_##N, [ld]load_##N, ST1, ST2, 0) {\ - asm("pushl %edx"); /* now state 0 */\ - LLOAD_N_ST02(OFF1, OFF2);\ - }\ - CODE(opc_lload_##N, [ld]load_##N, ST2, ST4, 0) {\ - asm("pushl %edx\n\t"\ - "pushl %ecx"); /* now state 0 */\ - LLOAD_N_ST04(OFF1, OFF2);\ - }\ - CODE(opc_lload_##N, [ld]load_##N, ST3, ST4, 0) {\ - asm("pushl %ecx"); /* now state 0 */\ - LLOAD_N_ST04(OFF1, OFF2);\ - }\ - CODE(opc_lload_##N, [ld]load_##N, ST4, ST2, 0) {\ - asm("pushl %ecx\n\t"\ - "pushl %edx"); /* now state 0 */\ - LLOAD_N_ST02(OFF1, OFF2);\ +#ifdef OPTIMIZE_INTERNAL_CODE + CODE(opc_dload_dld, dload_dld, STANY, STSTA, 0) { + asm("subl $8,%esp\n\t"); /* to simulate the true value of %esp */ + asm("fldl " STR(CONST) "(%esi)"); +#ifdef RUNTIME_DEBUG + if (runtime_debug) { + DEBUG_IN; + asm("subl $8,%esp\n\t" + "fstl (%esp)"); + PUSH_CONSTSTR(" %g\n"); + asm("call " SYMBOL(printf) "@PLT\n\t" + "addl $12,%esp"); + FFLUSH; + DEBUG_OUT; + } +#endif } - - CODE_LLOAD_N(0, -4, ); - CODE_LLOAD_N(1, -8, -4); - CODE_LLOAD_N(2, -12, -8); - CODE_LLOAD_N(3, -16, -12); +#endif /* OPTIMIZE_INTERNAL_CODE */ /* * array access @@ -1193,6 +1179,21 @@ BIPUSH_DEBUG1(%ecx); } +#ifdef OPTIMIZE_INTERNAL_CODE + CODE(opc_faload_fld, [ifa]aload, ST2, ST0, OPC_THROW) { + METAVM_ALOAD(%edx, %ecx, %edx, "faload_fld_st2", 0); + UNHAND(%edx, %eax); + asm("flds (%eax,%ecx,4)"); + asm("faload_fld_st2_done:"); + } + CODE(opc_faload_fld, [ifa]aload, ST4, ST0, OPC_THROW) { + METAVM_ALOAD(%ecx, %edx, %ecx, "faload_fld_st4", 0); + UNHAND(%ecx, %eax); + asm("flds (%eax,%edx,4)"); + asm("faload_fld_st4_done:"); + } +#endif /* OPTIMIZE_INTERNAL_CODE */ + /* laload */ /* compile: fill_cache, array_check, laload */ #ifdef METAVM @@ -1252,6 +1253,21 @@ LDC2_W_DEBUG1(%ecx, %edx); } +#ifdef OPTIMIZE_INTERNAL_CODE + CODE(opc_daload_dld, [ld]aload, ST2, ST4, OPC_THROW) { + METAVM_ALOAD2(%edx, %ecx, %edx, %ecx, "daload_dld_st2", 2); + UNHAND(%edx, %eax); + asm("fldl (%eax,%ecx,8)"); + asm("daload_dld_st2_done:"); + } + CODE(opc_daload_dld, [ld]aload, ST4, ST2, OPC_THROW) { + METAVM_ALOAD2(%ecx, %edx, %ecx, %edx, "daload_dld_st4", 4); + UNHAND(%ecx, %eax); + asm("fldl (%eax,%edx,8)"); + asm("daload_dld_st4_done:"); + } +#endif /* OPTIMIZE_INTERNAL_CODE */ + /* baload */ /* compile: fill_cache, array_check, baload */ CODE(opc_baload, baload, ST2, ST1, OPC_THROW) { @@ -1305,106 +1321,53 @@ /* istore */ /* const: index * 4 */ - CODE(opc_istore, [ifa]store, ST0, ST0, 0) { - asm("popl %edx\n\t" - "movl %edx," STR(CONST) "(%esi)"); - ILOAD_DEBUG1(%edx); - } - CODE(opc_istore, [ifa]store, ST1, ST0, 0) { - asm("movl %edx," STR(CONST) "(%esi)"); - ILOAD_DEBUG1(%edx); - } - CODE(opc_istore, [ifa]store, ST2, ST1, 0) { - asm("movl %ecx," STR(CONST) "(%esi)"); - ILOAD_DEBUG1(%ecx); - } - CODE(opc_istore, [ifa]store, ST3, ST0, 0) { - asm("movl %ecx," STR(CONST) "(%esi)"); - ILOAD_DEBUG1(%ecx); - } - CODE(opc_istore, [ifa]store, ST4, ST3, 0) { - asm("movl %edx," STR(CONST) "(%esi)"); - ILOAD_DEBUG1(%edx); - } +#define CODE_ISTORE(VOP, ST_A, ST_B, ST_C, ST_D, ST_E) \ + CODE(opc_##VOP, VOP, ST0, ST_A, 0) {\ + asm("popl %edx\n\t"\ + "movl %edx," STR(CONST) "(%esi)");\ + ILOAD_DEBUG1(%edx);\ + }\ + CODE(opc_##VOP, VOP, ST1, ST_B, 0) {\ + asm("movl %edx," STR(CONST) "(%esi)");\ + ILOAD_DEBUG1(%edx);\ + }\ + CODE(opc_##VOP, VOP, ST2, ST_C, 0) {\ + asm("movl %ecx," STR(CONST) "(%esi)");\ + ILOAD_DEBUG1(%ecx);\ + }\ + CODE(opc_##VOP, VOP, ST3, ST_D, 0) {\ + asm("movl %ecx," STR(CONST) "(%esi)");\ + ILOAD_DEBUG1(%ecx);\ + }\ + CODE(opc_##VOP, VOP, ST4, ST_E, 0) {\ + asm("movl %edx," STR(CONST) "(%esi)");\ + ILOAD_DEBUG1(%edx);\ + } + +CODE_ISTORE(istore, ST0, ST0, ST1, ST0, ST3); +#ifdef OPTIMIZE_INTERNAL_CODE +CODE_ISTORE(istld, ST1, ST1, ST2, ST3, ST4); +#endif /* OPTIMIZE_INTERNAL_CODE */ /* lstore */ /* const: index * 4, (index + 1) * 4 */ /* compile: fill_cache, lstore */ - CODE(opc_lstore, [ld]store, ST2, ST0, 0) { - asm("movl %ecx," STR(CONST) "(%esi)\n\t" - "movl %edx," STR(CONST) "(%esi)"); - LLOAD_DEBUG1(%ecx, %edx); - } - CODE(opc_lstore, [ld]store, ST4, ST0, 0) { - asm("movl %edx," STR(CONST) "(%esi)\n\t" - "movl %ecx," STR(CONST) "(%esi)"); - LLOAD_DEBUG1(%edx, %ecx); - } - - /* istore_[0-3] */ -#define CODE_ISTORE_N(N, OFF) \ - CODE(opc_istore_##N, [ifa]store_##N, ST0, ST0, 0) {\ - asm("popl %edx\n\t" /* now state 1 */\ - "movl %edx," #OFF "(%esi)");\ - BIPUSH_DEBUG1(%edx);\ - }\ - CODE(opc_istore_##N, [ifa]store_##N, ST1, ST0, 0) {\ - asm("movl %edx," #OFF "(%esi)");\ - BIPUSH_DEBUG1(%edx);\ - }\ - CODE(opc_istore_##N, [ifa]store_##N, ST2, ST1, 0) {\ - asm("movl %ecx," #OFF "(%esi)");\ - BIPUSH_DEBUG1(%ecx);\ - }\ - CODE(opc_istore_##N, [ifa]store_##N, ST3, ST0, 0) {\ - asm("movl %ecx," #OFF "(%esi)");\ - BIPUSH_DEBUG1(%ecx);\ - }\ - CODE(opc_istore_##N, [ifa]store_##N, ST4, ST3, 0) {\ - asm("movl %edx," #OFF "(%esi)");\ - BIPUSH_DEBUG1(%edx);\ - } - - CODE_ISTORE_N(0, ); - CODE_ISTORE_N(1, -4); - CODE_ISTORE_N(2, -8); - CODE_ISTORE_N(3, -12); - - /* lstore_[0-3] */ -#define LSTORE_N_ST2(OFF1, OFF2) \ - asm("movl %ecx," #OFF1 "(%esi)\n\t"\ - "movl %edx," #OFF2 "(%esi)");\ - LDC2_W_DEBUG1(%ecx, %edx) -#define LSTORE_N_ST4(OFF1, OFF2) \ - asm("movl %edx," #OFF1 "(%esi)\n\t"\ - "movl %ecx," #OFF2 "(%esi)");\ - LDC2_W_DEBUG1(%edx, %ecx) - -#define CODE_LSTORE_N(N, OFF1, OFF2) \ - CODE(opc_lstore_##N, [ld]store_##N, ST0, ST0, 0) {\ - asm("popl %ecx\n\t"\ - "popl %edx"); /* now state 2 */\ - LSTORE_N_ST2(OFF1, OFF2);\ - }\ - CODE(opc_lstore_##N, [ld]store_##N, ST1, ST0, 0) {\ - asm("popl %ecx"); /* now state 4 */\ - LSTORE_N_ST4(OFF1, OFF2);\ - }\ - CODE(opc_lstore_##N, [ld]store_##N, ST2, ST0, 0) {\ - LSTORE_N_ST2(OFF1, OFF2);\ - }\ - CODE(opc_lstore_##N, [ld]store_##N, ST3, ST0, 0) {\ - asm("popl %edx"); /* now state 2 */\ - LSTORE_N_ST2(OFF1, OFF2);\ - }\ - CODE(opc_lstore_##N, [ld]store_##N, ST4, ST0, 0) {\ - LSTORE_N_ST4(OFF1, OFF2);\ - } - - CODE_LSTORE_N(0, -4, ); - CODE_LSTORE_N(1, -8, -4); - CODE_LSTORE_N(2, -12, -8); - CODE_LSTORE_N(3, -16, -12); +#define CODE_LSTORE(VOP, ST_A, ST_B) \ + CODE(opc_##VOP, VOP, ST2, ST_A, 0) {\ + asm("movl %ecx," STR(CONST) "(%esi)\n\t"\ + "movl %edx," STR(CONST) "(%esi)");\ + LLOAD_DEBUG1(%ecx, %edx);\ + }\ + CODE(opc_##VOP, VOP, ST4, ST_B, 0) {\ + asm("movl %edx," STR(CONST) "(%esi)\n\t"\ + "movl %ecx," STR(CONST) "(%esi)");\ + LLOAD_DEBUG1(%edx, %ecx);\ + } + +CODE_LSTORE(lstore, ST0, ST0); +#ifdef OPTIMIZE_INTERNAL_CODE +CODE_LSTORE(lstld, ST2, ST4); +#endif /* OPTIMIZE_INTERNAL_CODE */ /* iastore */ /* compile: iastore1, fill_cache, array_check, iastore */ @@ -1957,7 +1920,7 @@ asm("popl %eax");\ ARITH_INT_DEBUG1(%eax, %ecx, SYM);\ INT_TEST(VOP, "i" #VOP "_st0", 0, %ecx);\ - asm("cdq");\ + asm("movl %eax,%edx\n\tsarl $31,%edx"); /* instead of `cdq' */\ asm("idivl %ecx\n\t"\ "i" #VOP "_st0_done:"\ "movl " #RESULT_REG ",%ecx");\ @@ -1967,7 +1930,7 @@ "movl %edx,%ecx");\ ARITH_INT_DEBUG1(%eax, %ecx, SYM);\ INT_TEST(VOP, "i" #VOP "_st1", 1, %ecx);\ - asm("cdq");\ + asm("movl %eax,%edx\n\tsarl $31,%edx"); /* instead of `cdq' */\ asm("idivl %ecx\n\t"\ "i" #VOP "_st1_done:"\ "movl " #RESULT_REG ",%ecx");\ @@ -1976,7 +1939,7 @@ asm("movl %edx,%eax");\ ARITH_INT_DEBUG1(%eax, %ecx, SYM);\ INT_TEST(VOP, "i" #VOP "_st2", 2, %ecx);\ - asm("cdq");\ + asm("movl %eax,%edx\n\tsarl $31,%edx"); /* instead of `cdq' */\ asm("idivl %ecx\n\t"\ "i" #VOP "_st2_done:"\ "movl " #RESULT_REG ",%ecx");\ @@ -1985,7 +1948,7 @@ asm("popl %eax");\ ARITH_INT_DEBUG1(%eax, %ecx, SYM);\ INT_TEST(VOP, "i" #VOP "_st3", 3, %ecx);\ - asm("cdq");\ + asm("movl %eax,%edx\n\tsarl $31,%edx"); /* instead of `cdq' */\ asm("idivl %ecx\n\t" /* %eax ... %edx = %edx:%eax / %ecx */\ "i" #VOP "_st3_done:"\ "movl " #RESULT_REG ",%ecx");\ @@ -1995,7 +1958,7 @@ "movl %edx,%ecx");\ ARITH_INT_DEBUG1(%eax, %ecx, SYM);\ INT_TEST(VOP, "i" #VOP "_st4", 4, %ecx);\ - asm("cdq");\ + asm("movl %eax,%edx\n\tsarl $31,%edx"); /* instead of `cdq' */\ asm("idivl %ecx\n\t"\ "i" #VOP "_st4_done:"\ "movl " #RESULT_REG ",%ecx");\ @@ -2214,8 +2177,11 @@ CODE_ARITH_LONG_TEST(rem, SYMBOL(__moddi3), "mod"); /* fadd, fsub, fmul, fdiv */ + /* compile: flush_cache, fld(4), f..., fst */ + /* fmul, fdiv and strictfp: flush_cache, strict_fprep fld(4), + strict_fscdown, f..., strict_fscup, fst, strict_fsettle */ #ifdef RUNTIME_DEBUG -# define ARITH_FLOAT_DEBUG1(SYM) \ +# define ARITH_FLOAT_DEBUG1 \ if (runtime_debug) {\ asm("flds 4(%esp)\n\t"\ "flds (%esp)");\ @@ -2223,7 +2189,7 @@ asm("subl $16,%esp\n\t"\ "fstpl 8(%esp)\n\t"\ "fstpl (%esp)");\ - PUSH_CONSTSTR("%g " SYM " %g = ");\ + PUSH_CONSTSTR(" %g, %g\n");\ asm("call " SYMBOL(printf) "@PLT\n\t"\ "addl $20,%esp");\ FFLUSH;\ @@ -2235,99 +2201,37 @@ DEBUG_IN;\ asm("subl $8,%esp\n\t"\ "fstpl (%esp)");\ - PUSH_CONSTSTR("%g\n");\ + PUSH_CONSTSTR(" %g\n");\ asm("call " SYMBOL(printf) "@PLT\n\t"\ "addl $12,%esp");\ FFLUSH;\ DEBUG_OUT;\ } #else -# define ARITH_FLOAT_DEBUG1(SYM) +# define ARITH_FLOAT_DEBUG1 # define ARITH_FLOAT_DEBUG2 #endif -#define CODE_ARITH_FLOAT(VOP, ROP, SYM) \ - CODE(opc_f##VOP, f##VOP, ST0, ST0, 0) {\ - ARITH_FLOAT_SCALE_PREPARE;\ - ARITH_FLOAT_DEBUG1(SYM);\ - asm("flds 4(%esp)");\ - ARITH_FLOAT_SCALE_DOWN;\ - asm("f" #ROP "s (%esp)\n\t"\ - "addl $4,%esp");\ - ARITH_FLOAT_SCALE_UP;\ - asm("fstps (%esp)");\ - ARITH_FLOAT_SCALE_SETTLE;\ - ARITH_FLOAT_DEBUG2;\ - }\ - CODE(opc_f##VOP, f##VOP, ST1, ST0, 0) {\ - ARITH_FLOAT_SCALE_PREPARE;\ - asm("flds (%esp)\n\t"\ - "pushl %edx");\ - ARITH_FLOAT_DEBUG1(SYM);\ - ARITH_FLOAT_SCALE_DOWN;\ - asm("f" #ROP "s (%esp)\n\t"\ - "addl $4,%esp");\ - ARITH_FLOAT_SCALE_UP;\ - asm("fstps (%esp)");\ - ARITH_FLOAT_SCALE_SETTLE;\ - ARITH_FLOAT_DEBUG2;\ - }\ - CODE(opc_f##VOP, f##VOP, ST2, ST0, 0) {\ - ARITH_FLOAT_SCALE_PREPARE;\ - asm("pushl %edx\n\t"\ - "flds (%esp)\n\t"\ - "pushl %ecx");\ - ARITH_FLOAT_DEBUG1(SYM);\ - ARITH_FLOAT_SCALE_DOWN;\ - asm("f" #ROP "s (%esp)\n\t"\ - "addl $4,%esp");\ - ARITH_FLOAT_SCALE_UP;\ - asm("fstps (%esp)");\ - ARITH_FLOAT_SCALE_SETTLE;\ - ARITH_FLOAT_DEBUG2;\ - }\ - CODE(opc_f##VOP, f##VOP, ST3, ST0, 0) {\ - ARITH_FLOAT_SCALE_PREPARE;\ - asm("flds (%esp)\n\t"\ - "pushl %ecx");\ - ARITH_FLOAT_DEBUG1(SYM);\ - ARITH_FLOAT_SCALE_DOWN;\ - asm("f" #ROP "s (%esp)\n\t"\ - "addl $4,%esp");\ - ARITH_FLOAT_SCALE_UP;\ - asm("fstps (%esp)");\ - ARITH_FLOAT_SCALE_SETTLE;\ - ARITH_FLOAT_DEBUG2;\ - }\ - CODE(opc_f##VOP, f##VOP, ST4, ST0, 0) {\ - ARITH_FLOAT_SCALE_PREPARE;\ - asm("pushl %ecx\n\t"\ - "flds (%esp)\n\t"\ - "pushl %edx");\ - ARITH_FLOAT_DEBUG1(SYM);\ - ARITH_FLOAT_SCALE_DOWN;\ - asm("f" #ROP "s (%esp)\n\t"\ - "addl $4,%esp");\ - ARITH_FLOAT_SCALE_UP;\ - asm("fstps (%esp)");\ - ARITH_FLOAT_SCALE_SETTLE;\ - ARITH_FLOAT_DEBUG2;\ - } - -#define ARITH_FLOAT_SCALE_PREPARE -#define ARITH_FLOAT_SCALE_DOWN -#define ARITH_FLOAT_SCALE_UP -#define ARITH_FLOAT_SCALE_SETTLE - - CODE_ARITH_FLOAT(add, add, "+"); - CODE_ARITH_FLOAT(sub, sub, "-"); - CODE_ARITH_FLOAT(mul, mul, "*"); - CODE_ARITH_FLOAT(div, div, "/"); - -#undef ARITH_FLOAT_SCALE_PREPARE -#undef ARITH_FLOAT_SCALE_DOWN -#undef ARITH_FLOAT_SCALE_UP -#undef ARITH_FLOAT_SCALE_SETTLE + CODE(opc_fadd, fadd, ST0, ST0, 0) { + asm("addl $4,%esp\n\t" + "fadds (%esp)"); + } + + CODE(opc_fmul, fmul, ST0, ST0, 0) { + asm("addl $4,%esp\n\t" + "fmuls (%esp)"); + } + + CODE(opc_fsub, fsub, ST0, ST0, 0) { + asm("fsubs (%esp)\n\t" + "addl $4,%esp"); + } + + CODE(opc_fdiv, fdiv, ST0, ST0, 0) { + asm("fdivs (%esp)\n\t" + "addl $4,%esp"); + } + #ifdef STRICT_USE_FSCALE # ifdef STRICT_PRELOAD # define ARITH_FLOAT_SCALE_PREPARE asm("fld %st(1)") @@ -2337,7 +2241,7 @@ asm("flds %0\n\t" : : "m" (single_scale_neg)) # else # define ARITH_FLOAT_SCALE_PREPARE \ - asm("fldl %0\n\t" : : "m" (single_scale_neg)) + asm("fildl %0\n\t" : : "m" (single_scale_neg)) # endif /* STRICT_FSCALE_USE_FLOAT */ # endif /* STRICT_PRELOAD */ # define ARITH_FLOAT_SCALE_DOWN asm("fscale") @@ -2346,7 +2250,7 @@ "fxch\n\t"\ "fscale") # define ARITH_FLOAT_SCALE_SETTLE asm("ffreep %st(0)") -#else +#else /* STRICT_USE_FSCALE */ # define ARITH_FLOAT_SCALE_PREPARE # ifdef STRICT_PRELOAD # define ARITH_FLOAT_SCALE_DOWN asm("fmul %st(4)") @@ -2362,20 +2266,49 @@ # define ARITH_FLOAT_SCALE_SETTLE #endif /* STRICT_USE_FSCALE */ - CODE_ARITH_FLOAT(mul_strict, mul, "*"); - CODE_ARITH_FLOAT(div_strict, div, "/"); + CODE(opc_strict_fprep, strict_fprep, STANY, STSTA, 0) { + ARITH_FLOAT_SCALE_PREPARE; + } + + CODE(opc_fld4, fld4, STANY, STSTA, 0) { + ARITH_FLOAT_DEBUG1; + asm("flds 4(%esp)"); + } + + CODE(opc_fld, fld, STANY, STSTA, 0) { + ARITH_FLOAT_DEBUG1; + asm("flds (%esp)"); + } + + CODE(opc_strict_fscdown, strict_fscdown, STANY, STSTA, 0) { + ARITH_FLOAT_SCALE_DOWN; + } + + CODE(opc_strict_fscup, strict_fscup, STANY, STSTA, 0) { + ARITH_FLOAT_SCALE_UP; + } + + CODE(opc_fst, fst, STANY, STSTA, 0) { + asm("fstps (%esp)"); + ARITH_FLOAT_DEBUG2; + } + + CODE(opc_strict_fsettle, strict_fsettle, STANY, STSTA, 0) { + ARITH_FLOAT_SCALE_SETTLE; + } /* dadd, dsub, dmul, ddiv */ + /* compile: flush_cache, dld(8), d..., dst */ + /* dmul, ddiv and strictfp: flush_cache, strict_dprep dld(8), + strict_dscdown, d..., strict_dscup, dst, strict_dsettle */ #ifdef RUNTIME_DEBUG -# define ARITH_DOUBLE_DEBUG1(OPTOP1_REG, OPTOP2_REG, SYM) \ +# define ARITH_DOUBLE_DEBUG1 \ if (runtime_debug) {\ - asm("movl (%esp),%edi\n\t"\ - "movl 4(%esp),%eax");\ + asm("movl %esp,%edi");\ DEBUG_IN;\ - asm("pushl " #OPTOP2_REG "\n\t"\ - "pushl " #OPTOP1_REG "\n\t"\ - "pushl %eax\n\tpushl %edi");\ - PUSH_CONSTSTR(" %g " SYM " %g = ");\ + asm("pushl 4(%edi)\n\tpushl (%edi)\n\t"\ + "pushl 12(%edi)\n\tpushl 8(%edi)");\ + PUSH_CONSTSTR(" %g, %g\n");\ asm("call " SYMBOL(printf) "@PLT\n\t"\ "addl $20,%esp");\ FFLUSH;\ @@ -2387,67 +2320,37 @@ "movl 4(%esp),%eax");\ DEBUG_IN;\ asm("pushl %eax\n\tpushl %edi");\ - PUSH_CONSTSTR("%g\n");\ + PUSH_CONSTSTR(" %g\n");\ asm("call " SYMBOL(printf) "@PLT\n\t"\ "addl $12,%esp");\ FFLUSH;\ DEBUG_OUT;\ } #else -# define ARITH_DOUBLE_DEBUG1(OPTOP1_REG, OPTOP2_REG, SYM) +# define ARITH_DOUBLE_DEBUG1 # define ARITH_DOUBLE_DEBUG2 #endif -#define DOUBLE_ST24(ROP, OPTOP1_REG, OPTOP2_REG, SYM) \ - ARITH_DOUBLE_SCALE_PREPARE;\ - ARITH_DOUBLE_DEBUG1(OPTOP1_REG, OPTOP2_REG, SYM);\ - asm("fldl (%esp)"); /* load v1[0:63] */\ - ARITH_DOUBLE_SCALE_DOWN;\ - asm("pushl " #OPTOP2_REG "\n\t" /* v2[32:63] */\ - "pushl " #OPTOP1_REG "\n\t" /* v2[0:31] */\ - "f" #ROP "l (%esp)");\ - asm("addl $8,%esp");\ - ARITH_DOUBLE_SCALE_UP;\ - asm("fstpl (%esp)");\ - ARITH_DOUBLE_SCALE_SETTLE;\ - ARITH_DOUBLE_DEBUG2 - /* now state 0 */ + CODE(opc_dadd, dadd, ST0, ST0, 0) { + asm("addl $8,%esp\n\t" + "faddl (%esp)"); + } -#define CODE_ARITH_DOUBLE(VOP, ROP, SYM) \ - CODE(opc_d##VOP, d##VOP, ST0, ST0, 0) {\ - asm("popl %ecx\n\t"\ - "popl %edx"); /* now state 2 */\ - DOUBLE_ST24(ROP, %ecx, %edx, SYM);\ - }\ - CODE(opc_d##VOP, d##VOP, ST1, ST0, 0) {\ - asm("popl %ecx"); /* now state 4 */\ - DOUBLE_ST24(ROP, %edx, %ecx, SYM);\ - }\ - CODE(opc_d##VOP, d##VOP, ST2, ST0, 0) {\ - DOUBLE_ST24(ROP, %ecx, %edx, SYM);\ - }\ - CODE(opc_d##VOP, d##VOP, ST3, ST0, 0) {\ - asm("popl %edx"); /* now state 2 */\ - DOUBLE_ST24(ROP, %ecx, %edx, SYM);\ - }\ - CODE(opc_d##VOP, d##VOP, ST4, ST0, 0) {\ - DOUBLE_ST24(ROP, %edx, %ecx, SYM);\ + CODE(opc_dmul, dmul, ST0, ST0, 0) { + asm("addl $8,%esp\n\t" + "fmull (%esp)"); + } + + CODE(opc_dsub, dsub, ST0, ST0, 0) { + asm("fsubl (%esp)\n\t" + "addl $8,%esp"); + } + + CODE(opc_ddiv, ddiv, ST0, ST0, 0) { + asm("fdivl (%esp)\n\t" + "addl $8,%esp"); } -#define ARITH_DOUBLE_SCALE_PREPARE -#define ARITH_DOUBLE_SCALE_DOWN -#define ARITH_DOUBLE_SCALE_UP -#define ARITH_DOUBLE_SCALE_SETTLE - - CODE_ARITH_DOUBLE(add, add, "+"); - CODE_ARITH_DOUBLE(sub, sub, "-"); - CODE_ARITH_DOUBLE(mul, mul, "*"); - CODE_ARITH_DOUBLE(div, div, "/"); - -#undef ARITH_DOUBLE_SCALE_PREPARE -#undef ARITH_DOUBLE_SCALE_DOWN -#undef ARITH_DOUBLE_SCALE_UP -#undef ARITH_DOUBLE_SCALE_SETTLE #ifdef STRICT_USE_FSCALE # ifdef STRICT_PRELOAD # define ARITH_DOUBLE_SCALE_PREPARE asm("fld %st(0)") @@ -2457,7 +2360,7 @@ asm("flds %0\n\t" : : "m" (double_scale_neg)) # else # define ARITH_DOUBLE_SCALE_PREPARE \ - asm("fldl %0\n\t" : : "m" (double_scale_neg)) + asm("fildl %0\n\t" : : "m" (double_scale_neg)) # endif /* STRICT_FSCALE_USE_FLOAT */ # endif /* STRICT_PRELOAD */ # define ARITH_DOUBLE_SCALE_DOWN asm("fscale") @@ -2482,49 +2385,54 @@ # define ARITH_DOUBLE_SCALE_SETTLE #endif /* STRICT_USE_FSCALE */ - CODE_ARITH_DOUBLE(mul_strict, mul, "*"); - CODE_ARITH_DOUBLE(div_strict, div, "/"); + CODE(opc_strict_dprep, strict_dprep, STANY, STSTA, 0) { + ARITH_DOUBLE_SCALE_PREPARE; + } - /* frem */ -#define FREM_ST0 \ - ARITH_FLOAT_DEBUG1("mod");\ - asm("flds (%esp)\n\t" /* fld optop[-1].f (value2) */\ - "flds 4(%esp)"); /* fld optop[-2].f (value1) */\ - FUNCCALL_IN(0);\ - asm("subl $16,%esp");\ - asm("fstpl (%esp)\n\t" /* stack top = optop[-2] (value1) */\ - "fstpl 8(%esp)\n\t" /* stack top-1 = optop[-1] (value2) */\ - "call " SYMBOL(fmod) "@PLT\n\t"\ - "addl $16,%esp");\ - FUNCCALL_OUT(0);\ - asm("addl $4,%esp\n\t"\ - "fstps (%esp)");\ - ARITH_FLOAT_DEBUG2 - /* now state 0 */ + CODE(opc_dld8, dld8, STANY, STSTA, 0) { + ARITH_DOUBLE_DEBUG1; + asm("fldl 8(%esp)"); + } - CODE(opc_frem, frem, ST0, ST0, 0) { FREM_ST0; } - CODE(opc_frem, frem, ST1, ST0, 0) { - asm("pushl %edx"); /* now state 0 */ - FREM_ST0; + CODE(opc_dld, dld, STANY, STSTA, 0) { + asm("fldl (%esp)"); } - CODE(opc_frem, frem, ST2, ST0, 0) { - asm("pushl %edx\n\t" - "pushl %ecx"); /* now state 0 */ - FREM_ST0; + + CODE(opc_strict_dscdown, strict_dscdown, STANY, STSTA, 0) { + ARITH_DOUBLE_SCALE_DOWN; } - CODE(opc_frem, frem, ST3, ST0, 0) { - asm("pushl %ecx"); /* now state 0 */ - FREM_ST0; + + CODE(opc_strict_dscup, strict_dscup, STANY, STSTA, 0) { + ARITH_DOUBLE_SCALE_UP; } - CODE(opc_frem, frem, ST4, ST0, 0) { - asm("pushl %ecx\n\t" - "pushl %edx"); /* now state 0 */ - FREM_ST0; + + CODE(opc_dst, dst, STANY, STSTA, 0) { + asm("fstpl (%esp)"); + ARITH_DOUBLE_DEBUG2; + } + + CODE(opc_strict_dsettle, strict_dsettle, STANY, STSTA, 0) { + ARITH_DOUBLE_SCALE_SETTLE; + } + + /* frem */ + /* compile: flush_cache, fld, frem, fst */ + CODE(opc_frem, frem, ST0, ST0, 0) { + asm("flds 4(%esp)"); /* fld optop[-2].f (value1) */ + FUNCCALL_IN(0); + asm("subl $16,%esp"); + asm("fstpl (%esp)\n\t" /* stack top = optop[-2] (value1) */ + "fstpl 8(%esp)\n\t" /* stack top-1 = optop[-1] (value2) */ + "call " SYMBOL(fmod) "@PLT\n\t" + "addl $16,%esp"); + FUNCCALL_OUT(0); + asm("addl $4,%esp"); + /* now state 0 */ } /* drem */ + /* compile: fill_cache, drem, dst */ #define DREM_ST24(OPTOP1_REG, OPTOP2_REG) \ - ARITH_DOUBLE_DEBUG1(OPTOP1_REG, OPTOP2_REG, "mod");\ asm("popl %eax\n\t" /* eax = v1[0:31] */\ "popl %edi"); /* edi = v1[32:63] */\ FUNCCALL_IN(0);\ @@ -2535,27 +2443,12 @@ "call " SYMBOL(fmod) "@PLT\n\t"\ "addl $16,%esp");\ FUNCCALL_OUT(0);\ - asm("subl $8,%esp\n\t"\ - "fstpl (%esp)");\ - ARITH_DOUBLE_DEBUG2 + asm("subl $8,%esp"); /* now state 0 */ - CODE(opc_drem, drem, ST0, ST0, 0) { - asm("popl %ecx\n\t" - "popl %edx"); /* now state 2 */ - DREM_ST24(%ecx, %edx); - } - CODE(opc_drem, drem, ST1, ST0, 0) { - asm("popl %ecx"); /* now state 4 */ - DREM_ST24(%edx, %ecx); - } CODE(opc_drem, drem, ST2, ST0, 0) { DREM_ST24(%ecx, %edx); } - CODE(opc_drem, drem, ST3, ST0, 0) { - asm("popl %edx"); /* now state 2 */ - DREM_ST24(%ecx, %edx); - } CODE(opc_drem, drem, ST4, ST0, 0) { DREM_ST24(%edx, %ecx); } @@ -2612,61 +2505,15 @@ } /* fneg */ -#define FNEG_ST0 \ - asm("flds (%esp)\n\t"\ - "fchs\n\t"\ - "fstps (%esp)") - /* now state 0 */ - + /* compile: flush_cache, fld, fneg, fst */ CODE(opc_fneg, fneg, ST0, ST0, 0) { - FNEG_ST0; - } - CODE(opc_fneg, fneg, ST1, ST0, 0) { - asm("pushl %edx"); /* now state 0 */ - FNEG_ST0; - } - CODE(opc_fneg, fneg, ST2, ST0, 0) { - asm("pushl %edx\n\t" - "pushl %ecx"); /* now state 0 */ - FNEG_ST0; - } - CODE(opc_fneg, fneg, ST3, ST0, 0) { - asm("pushl %ecx"); /* now state 0 */ - FNEG_ST0; - } - CODE(opc_fneg, fneg, ST4, ST0, 0) { - asm("pushl %ecx\n\t" - "pushl %edx"); /* now state 0 */ - FNEG_ST0; + asm("fchs"); } /* dneg */ -#define DNEG_ST0 \ - asm("fldl (%esp)\n\t"\ - "fchs\n\t"\ - "fstpl (%esp)") - /* now state 0 */ - + /* flush_cache, dld, dneg, dst */ CODE(opc_dneg, dneg, ST0, ST0, 0) { - DNEG_ST0; - } - CODE(opc_dneg, dneg, ST1, ST0, 0) { - asm("pushl %edx"); /* now state 0 */ - DNEG_ST0; - } - CODE(opc_dneg, dneg, ST2, ST0, 0) { - asm("pushl %edx\n\t" - "pushl %ecx"); /* now state 0 */ - DNEG_ST0; - } - CODE(opc_dneg, dneg, ST3, ST0, 0) { - asm("pushl %ecx"); /* now state 0 */ - DNEG_ST0; - } - CODE(opc_dneg, dneg, ST4, ST0, 0) { - asm("pushl %ecx\n\t" - "pushl %edx"); /* now state 0 */ - DNEG_ST0; + asm("fchs"); } /* ishl */ @@ -2791,10 +2638,7 @@ if (runtime_debug) {\ DEBUG_IN;\ asm("pushl " STR(CONST) "(%esi)\n\t"\ - "movl $" STR(CONST) ",%eax\n\t"\ - "sarl $2,%eax\n\t"\ - "negl %eax\n\t"\ - "pushl %eax");\ + "pushl $" STR(CONST));\ PUSH_CONSTSTR(" var[%d] %d");\ asm("call " SYMBOL(printf) "@PLT\n\t"\ "addl $12,%esp");\ @@ -2850,58 +2694,16 @@ } /* i2f */ -#define I2F_ST0 \ - asm("fildl (%esp)\n\t"\ - "fstps (%esp)") - + /* compile: flush_cache, i2f, fst */ CODE(opc_i2f, i2f, ST0, ST0, 0) { - I2F_ST0; - } - CODE(opc_i2f, i2f, ST1, ST0, 0) { - asm("pushl %edx"); /* now state 0 */ - I2F_ST0; - } - CODE(opc_i2f, i2f, ST2, ST0, 0) { - asm("pushl %edx\n\t" - "pushl %ecx"); /* now state 0 */ - I2F_ST0; - } - CODE(opc_i2f, i2f, ST3, ST0, 0) { - asm("pushl %ecx"); /* now state 0 */ - I2F_ST0; - } - CODE(opc_i2f, i2f, ST4, ST0, 0) { - asm("pushl %ecx\n\t" - "pushl %edx"); /* now state 0 */ - I2F_ST0; + asm("fildl (%esp)"); } /* i2d */ -#define I2D_ST0 \ - asm("fildl (%esp)\n\t"\ - "fstpl -4(%esp)\n\t"\ - "subl $4,%esp") - + /* compile: flush_cache, i2d, dst */ CODE(opc_i2d, i2d, ST0, ST0, 0) { - I2D_ST0; - } - CODE(opc_i2d, i2d, ST1, ST0, 0) { - asm("pushl %edx"); /* now state 0 */ - I2D_ST0; - } - CODE(opc_i2d, i2d, ST2, ST0, 0) { - asm("pushl %edx\n\t" - "pushl %ecx"); /* now state 0 */ - I2D_ST0; - } - CODE(opc_i2d, i2d, ST3, ST0, 0) { - asm("pushl %ecx"); /* now state 0 */ - I2D_ST0; - } - CODE(opc_i2d, i2d, ST4, ST0, 0) { - asm("pushl %ecx\n\t" - "pushl %edx"); /* now state 0 */ - I2D_ST0; + asm("fildl (%esp)\n\t" + "subl $4,%esp"); } /* l2i */ @@ -2919,58 +2721,16 @@ CODE(opc_l2i, l2i, ST4, ST1, 0) {} /* l2f */ -#define L2F_ST0 \ - asm("fildll (%esp)\n\t"\ - "fstps 4(%esp)\n\t"\ - "addl $4,%esp") - + /* compile: flush_cache, l2f, fst */ CODE(opc_l2f, l2f, ST0, ST0, 0) { - L2F_ST0; - } - CODE(opc_l2f, l2f, ST1, ST0, 0) { - asm("pushl %edx"); /* now state 0 */ - L2F_ST0; - } - CODE(opc_l2f, l2f, ST2, ST0, 0) { - asm("pushl %edx\n\t" - "pushl %ecx"); /* now state 0 */ - L2F_ST0; - } - CODE(opc_l2f, l2f, ST3, ST0, 0) { - asm("pushl %ecx"); /* now state 0 */ - L2F_ST0; - } - CODE(opc_l2f, l2f, ST4, ST0, 0) { - asm("pushl %ecx\n\t" - "pushl %edx"); /* now state 0 */ - L2F_ST0; + asm("fildll (%esp)\n\t" + "addl $4,%esp"); } /* l2d */ -#define L2D_ST0 \ - asm("fildll (%esp)\n\t"\ - "fstpl (%esp)") - + /* compile: flush_cache, l2d, dst */ CODE(opc_l2d, l2d, ST0, ST0, 0) { - L2D_ST0; - } - CODE(opc_l2d, l2d, ST1, ST0, 0) { - asm("pushl %edx"); /* now state 0 */ - L2D_ST0; - } - CODE(opc_l2d, l2d, ST2, ST0, 0) { - asm("pushl %edx\n\t" - "pushl %ecx"); /* now state 0 */ - L2D_ST0; - } - CODE(opc_l2d, l2d, ST3, ST0, 0) { - asm("pushl %ecx"); /* now state 0 */ - L2D_ST0; - } - CODE(opc_l2d, l2d, ST4, ST0, 0) { - asm("pushl %ecx\n\t" - "pushl %edx"); /* now state 0 */ - L2D_ST0; + asm("fildll (%esp)"); } /* f2i, f2l, d2i, d2l */ @@ -3091,59 +2851,15 @@ CODE_REAL2INT(d2l, D2L, LONG, 2); /* f2d */ -#define F2D_ST0 \ - asm("flds (%esp)\n\t"\ - "fstpl -4(%esp)\n\t"\ - "subl $4,%esp") - + /* compile: flush_cache, fld, f2d, dst */ CODE(opc_f2d, f2d, ST0, ST0, 0) { - F2D_ST0; - } - CODE(opc_f2d, f2d, ST1, ST0, 0) { - asm("pushl %edx"); /* now state 0 */\ - F2D_ST0; - } - CODE(opc_f2d, f2d, ST2, ST0, 0) { - asm("pushl %edx\n\t"\ - "pushl %ecx"); /* now state 0 */\ - F2D_ST0; - } - CODE(opc_f2d, f2d, ST3, ST0, 0) { - asm("pushl %ecx"); /* now state 0 */\ - F2D_ST0; - } - CODE(opc_f2d, f2d, ST4, ST0, 0) { - asm("pushl %ecx\n\t"\ - "pushl %edx"); /* now state 0 */\ - F2D_ST0; + asm("subl $4,%esp"); } /* d2f */ -#define D2F_ST0 \ - asm("fldl (%esp)\n\t"\ - "fstps 4(%esp)\n\t"\ - "addl $4,%esp") - + /* compile: flush_cache, dld, d2f, fst */ CODE(opc_d2f, d2f, ST0, ST0, 0) { - D2F_ST0; - } - CODE(opc_d2f, d2f, ST1, ST0, 0) { - asm("pushl %edx"); /* now state 0 */\ - D2F_ST0; - } - CODE(opc_d2f, d2f, ST2, ST0, 0) { - asm("pushl %edx\n\t"\ - "pushl %ecx"); /* now state 0 */\ - D2F_ST0; - } - CODE(opc_d2f, d2f, ST3, ST0, 0) { - asm("pushl %ecx"); /* now state 0 */\ - D2F_ST0; - } - CODE(opc_d2f, d2f, ST4, ST0, 0) { - asm("pushl %ecx\n\t"\ - "pushl %edx"); /* now state 0 */\ - D2F_ST0; + asm("addl $4,%esp"); } /* i2b, i2c, i2s */ diff -aruN shujit-0.4.2/codedb.c shujit/codedb.c --- shujit-0.4.2/codedb.c Thu Dec 23 12:57:23 1999 +++ shujit/codedb.c Mon Apr 24 12:48:07 2000 @@ -76,10 +76,11 @@ printf(" code_size:4: 0x%x\n", info->code_size); fflush(stdout); #endif write(fd, &info->code_size, 4); + len = pctableLen(cc); #ifdef CODE_DB_DEBUG - printf(" pctablelen:4: 0x%x\n", cc->pctablelen); fflush(stdout); + printf(" pctablelen:4: 0x%x\n", len); fflush(stdout); #endif - write(fd, &cc->pctablelen, 4); + write(fd, &len, 4); #ifdef EXC_BY_SIGNAL #ifdef CODE_DB_DEBUG printf(" throwtablelen:4: 0x%x\n", info->throwtablelen); fflush(stdout); @@ -98,10 +99,13 @@ write(fd, &info->exc_handler_nativeoff, 4); write(fd, &info->finish_return_nativeoff, 4); - len = cc->pctablelen; for (i = 0; i < len; i++) { + int16_t st; + write(fd, &pcentry->opcode, 2); - write(fd, &pcentry->state, 2); + write(fd, &pcentry->flag, 2); + write(fd, &st, 2); + write(fd, &pcentry->operand, 4); write(fd, &pcentry->byteoff, 4); write(fd, &pcentry->nativeoff, 4); pcentry++; @@ -197,9 +201,10 @@ #ifdef CODE_DB_DEBUG printf(" code_size:4: 0x%x\n", info->code_size); fflush(stdout); #endif - read(fd, &cc->pctablelen, 4); + read(fd, &len, 4); + pctableSetLen(cc, len); #ifdef CODE_DB_DEBUG - printf(" pctablelen:4: 0x%x\n", cc->pctablelen); fflush(stdout); + printf(" pctablelen:4: 0x%x\n", pctableLen(cc)); fflush(stdout); #endif #ifdef EXC_BY_SIGNAL read(fd, &info->throwtablelen, 4); @@ -219,12 +224,15 @@ fflush(stdout); #endif - pctableExtend(cc, cc->pctablelen); + len = pctableLen(cc); + pctableExtend(cc, len); pcentry = cc->pctable; - len = cc->pctablelen; for (i = 0; i < len; i++) { + int16_t st; + read(fd, &pcentry->opcode, 2); - read(fd, &pcentry->state, 2); + read(fd, &pcentry->flag, 2); + read(fd, &pcentry->operand, 4); read(fd, &pcentry->byteoff, 4); read(fd, &pcentry->nativeoff, 4); pcentry++; diff -aruN shujit-0.4.2/compile.c shujit/compile.c --- shujit-0.4.2/compile.c Mon Feb 14 11:35:36 2000 +++ shujit/compile.c Mon Apr 24 16:38:23 2000 @@ -53,8 +53,8 @@ * Local Functions */ static int makePCTable(CompilerContext *cc); - -static int processAnOpcode(CompilerContext *cc, int opcode, int32_t *byteoffp); +static int processAnOpcode(CompilerContext *cc, int opcode, int byteoff); +static void makeBlockStructure(CompilerContext *cc); static void updateStates(CompilerContext *cc); static int writeCode(CompilerContext *cc); static void resolveJumpInstructions(CompilerContext *cc); @@ -144,10 +144,14 @@ if (readCompiledCode(db, db_page, cc)) goto static_part_done; } /* if (OPT_CODEDB) */ -#endif /* CODE_DB */ +#endif /* compile */ if (makePCTable(cc)) goto compile_failed; + makeBlockStructure(cc); +#ifdef OPTIMIZE_INTERNAL_CODE + optimizeInternalCode(cc); +#endif updateStates(cc); if (writeCode(cc)) goto compile_failed; resolveJumpInstructions(cc); @@ -283,7 +287,8 @@ if (compile_debug) { printf("cmplMtd() done.\n %s#%s %s\n", cbName(fieldclass(&mb->fb)), mb->fb.name, mb->fb.signature); - printf(" code: 0x%08x\n", (int)mb->CompiledCode); + printf(" code: 0x%08x, size: 0x%x(%d)\n", + (int)mb->CompiledCode, info->code_size, info->code_size); fflush(stdout); } #endif @@ -345,8 +350,8 @@ struct methodblock *mb = cc->mb; unsigned char *methodcode = mb->code; int endoff = mb->code_length; - int32_t dummy_byteoff; int32_t byteoff = 0; + int byteinc; CodeInfo *info = (CodeInfo *)(mb->CompiledCodeInfo); #if 0 @@ -360,67 +365,195 @@ #endif makepctable_start: - dummy_byteoff = -1; - if (processAnOpcode(cc, opc_methodhead, &dummy_byteoff)) + if (processAnOpcode(cc, opc_methodhead, -1) < 0) return 1; if (OPT_SETQ(OPT_FRCSTRICTFP) || (!OPT_SETQ(OPT_IGNSTRICTFP) && (mb->fb.access & ACC_STRICT))) { +#ifndef FORCE_DOUBLE_PRECISION if (!is_fpupc_double) { - if (processAnOpcode(cc, opc_fppc_save, &dummy_byteoff)) + if (processAnOpcode(cc, opc_fppc_save, -1) < 0) return 1; - if (processAnOpcode(cc, opc_fppc_double, &dummy_byteoff)) + if (processAnOpcode(cc, opc_fppc_double, -1) < 0) return 1; } +#endif /* ! FORCE_DOUBLE_PRECISION */ - if (processAnOpcode(cc, opc_strictenter, &dummy_byteoff)) + if (processAnOpcode(cc, opc_strict_enter, -1) < 0) return 1; } if (mb->fb.access & ACC_SYNCHRONIZED) - if (processAnOpcode(cc, opc_syncenter, &dummy_byteoff)) + if (processAnOpcode(cc, opc_sync_enter, -1) < 0) return 1; while (byteoff < endoff) { + cc->ninsn++; opcode = *(methodcode + byteoff); /* decompose an opcode to some micro opcodes */ switch (opcode) { case opc_iaload: case opc_laload: case opc_faload: case opc_daload: case opc_aaload: case opc_baload: case opc_caload: case opc_saload: - if (processAnOpcode(cc, opc_fill_cache, &byteoff)) - return 1; - if (processAnOpcode(cc, opc_array_check, &byteoff)) - return 1; - if (processAnOpcode(cc, opcode, &byteoff)) - return 1; + if (processAnOpcode(cc, opc_fill_cache, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_array_check, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + byteoff += byteinc; break; + case opc_lstore: case opc_dstore: - if (processAnOpcode(cc, opc_fill_cache, &byteoff)) - return 1; - if (processAnOpcode(cc, opcode, &byteoff)) - return 1; + case opc_lstore_0: case opc_dstore_0: + case opc_lstore_1: case opc_dstore_1: + case opc_lstore_2: case opc_dstore_2: + case opc_lstore_3: case opc_dstore_3: + if (processAnOpcode(cc, opc_fill_cache, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + byteoff += byteinc; break; + case opc_iastore: case opc_fastore: case opc_aastore: case opc_bastore: case opc_castore: case opc_sastore: - if (processAnOpcode(cc, opc_iastore1, &byteoff)) - return 1; - if (processAnOpcode(cc, opc_fill_cache, &byteoff)) - return 1; - if (processAnOpcode(cc, opc_array_check, &byteoff)) - return 1; - if (processAnOpcode(cc, opcode, &byteoff)) - return 1; + if (processAnOpcode(cc, opc_iastore1, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_fill_cache, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_array_check, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + byteoff += byteinc; break; + case opc_lastore: case opc_dastore: - if (processAnOpcode(cc, opc_fill_cache, &byteoff)) - return 1; - if (processAnOpcode(cc, opcode, &byteoff)) - return 1; + if (processAnOpcode(cc, opc_fill_cache, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + byteoff += byteinc; + break; + + case opc_fadd: case opc_fsub: + { + int opcode_fld = ((opcode == opc_fadd) ? opc_fld : opc_fld4); + + if (processAnOpcode(cc, opc_flush_cache, byteoff) < 0) return 1; + if (processAnOpcode(cc, opcode_fld, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + if (processAnOpcode(cc, opc_fst, byteoff) < 0) return 1; + } + byteoff += byteinc; + break; + case opc_fmul: case opc_fdiv: + { + int opcode_fld = ((opcode == opc_fmul) ? opc_fld : opc_fld4); + + if (OPT_SETQ(OPT_FRCSTRICTFP) || + (!OPT_SETQ(OPT_IGNSTRICTFP) && (mb->fb.access & ACC_STRICT))) { + if (processAnOpcode(cc, opc_flush_cache, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_strict_fprep, byteoff) < 0) return 1; + if (processAnOpcode(cc, opcode_fld, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_strict_fscdown, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + if (processAnOpcode(cc, opc_strict_fscup, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_fst, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_strict_fsettle, byteoff) < 0) return 1; + } + else { + if (processAnOpcode(cc, opc_flush_cache, byteoff) < 0) return 1; + if (processAnOpcode(cc, opcode_fld, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + if (processAnOpcode(cc, opc_fst, byteoff) < 0) return 1; + } + } + byteoff += byteinc; + break; + case opc_dadd: case opc_dsub: + { + int opcode_dld = ((opcode == opc_dadd) ? opc_dld : opc_dld8); + + if (processAnOpcode(cc, opc_flush_cache, byteoff) < 0) return 1; + if (processAnOpcode(cc, opcode_dld, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + if (processAnOpcode(cc, opc_dst, byteoff) < 0) return 1; + } + byteoff += byteinc; + break; + case opc_dmul: case opc_ddiv: + { + int opcode_dld = ((opcode == opc_dmul) ? opc_dld : opc_dld8); + + if (OPT_SETQ(OPT_FRCSTRICTFP) || + (!OPT_SETQ(OPT_IGNSTRICTFP) && (mb->fb.access & ACC_STRICT))) { + if (processAnOpcode(cc, opc_flush_cache, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_strict_dprep, byteoff) < 0) return 1; + if (processAnOpcode(cc, opcode_dld, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_strict_dscdown, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + if (processAnOpcode(cc, opc_strict_dscup, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_dst, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_strict_dsettle, byteoff) < 0) return 1; + } + else { + if (processAnOpcode(cc, opc_flush_cache, byteoff) < 0) return 1; + if (processAnOpcode(cc, opcode_dld, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + if (processAnOpcode(cc, opc_dst, byteoff) < 0) return 1; + } + } + byteoff += byteinc; break; + + case opc_i2f: case opc_l2f: + if (processAnOpcode(cc, opc_flush_cache, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + if (processAnOpcode(cc, opc_fst, byteoff) < 0) return 1; + byteoff += byteinc; + break; + + case opc_drem: + if (processAnOpcode(cc, opc_fill_cache, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + if (processAnOpcode(cc, opc_dst, byteoff) < 0) return 1; + byteoff += byteinc; + break; + + case opc_frem: + case opc_fneg: + if (processAnOpcode(cc, opc_flush_cache, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_fld, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + if (processAnOpcode(cc, opc_fst, byteoff) < 0) return 1; + byteoff += byteinc; + break; + + case opc_dneg: + if (processAnOpcode(cc, opc_flush_cache, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_dld, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + if (processAnOpcode(cc, opc_dst, byteoff) < 0) return 1; + byteoff += byteinc; + break; + + case opc_i2d: case opc_l2d: + if (processAnOpcode(cc, opc_flush_cache, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + if (processAnOpcode(cc, opc_dst, byteoff) < 0) return 1; + byteoff += byteinc; + break; + + case opc_f2d: + if (processAnOpcode(cc, opc_flush_cache, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_fld, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + if (processAnOpcode(cc, opc_dst, byteoff) < 0) return 1; + byteoff += byteinc; + break; + + case opc_d2f: + if (processAnOpcode(cc, opc_flush_cache, byteoff) < 0) return 1; + if (processAnOpcode(cc, opc_dld, byteoff) < 0) return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + if (processAnOpcode(cc, opc_fst, byteoff) < 0) return 1; + byteoff += byteinc; + break; + default: - if (processAnOpcode(cc, opcode, &byteoff)) - return 1; + if ((byteinc = processAnOpcode(cc, opcode, byteoff)) < 0) return 1; + byteoff += byteinc; break; } @@ -446,10 +579,9 @@ #endif } - dummy_byteoff = ~(1 << 31); /* exception handler */ if (cc->may_throw) { - if (processAnOpcode(cc, opc_exc_new, &dummy_byteoff)) + if (processAnOpcode(cc, opc_exc_new, INT_MAX)) return 1; } #ifdef COMPILE_DEBUG @@ -463,7 +595,7 @@ #endif if (mb->exception_table_length > 0) { - if (processAnOpcode(cc, opc_exc_handler, &dummy_byteoff)) + if (processAnOpcode(cc, opc_exc_handler, INT_MAX)) return 1; } #ifdef COMPILE_DEBUG @@ -477,25 +609,27 @@ #endif /* method tail */ - if (processAnOpcode(cc, opc_epilogue, &dummy_byteoff)) + if (processAnOpcode(cc, opc_epilogue, INT_MAX)) return 1; if (mb->fb.access & ACC_SYNCHRONIZED) - if (processAnOpcode(cc, opc_syncexit, &dummy_byteoff)) + if (processAnOpcode(cc, opc_sync_exit, INT_MAX)) return 1; if (OPT_SETQ(OPT_FRCSTRICTFP) || (!OPT_SETQ(OPT_IGNSTRICTFP) && (mb->fb.access & ACC_STRICT))) { +#ifndef FORCE_DOUBLE_PRECISION if (!is_fpupc_double) { - if (processAnOpcode(cc, opc_fppc_restore, &dummy_byteoff)) + if (processAnOpcode(cc, opc_fppc_restore, INT_MAX)) return 1; } +#endif /* ! FORCE_DOUBLE_PRECISION */ - if (processAnOpcode(cc, opc_strictexit, &dummy_byteoff)) + if (processAnOpcode(cc, opc_strict_exit, INT_MAX)) return 1; } - if (processAnOpcode(cc, opc_methodtail, &dummy_byteoff)) + if (processAnOpcode(cc, opc_methodtail, INT_MAX)) return 1; return 0; @@ -503,144 +637,239 @@ /* - * returns: true if an exception occurred. + * returns: increment count for bytecode PC, + * or -1 if an exception occurred. */ -static int processAnOpcode(CompilerContext *cc, int opcode, - int32_t *byteoffp) { +static int processAnOpcode(CompilerContext *cc, int opcode, int byteoff) { struct methodblock *mb = cc->mb; CodeInfo *info = (CodeInfo *)mb->CompiledCodeInfo; cp_item_type *constant_pool = cbConstantPool(fieldclass(&mb->fb)); unsigned char *type_table = constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type; - unsigned char *bytepc = mb->code + *byteoffp; + int byteinc = 0; + unsigned char *bytepc = mb->code + byteoff; int code_opcode; + int32_t operand; #ifdef COMPILE_DEBUG int compile_debug = cc->compile_debug; #endif - + #ifdef COMPILE_DEBUG if (compile_debug) { printf("procOpc(): %s(0x%02x,%d)\n", ((opcode > opc_nonnull_quick) ? "(null)" : opcode_symbol[opcode]), opcode, opcode); - printf(" b off: 0x%x(%d)\n", *byteoffp, *byteoffp); + printf(" b off: 0x%x(%d)\n", byteoff, byteoff); fflush(stdout); } #endif - /* translate an opcode to an internal opcode */ - switch (opcode) { + /* translate an opcode to the correspoinding internal opcode */ + code_opcode = opcode; + operand = -1; + +proc_opc_switch: + switch (code_opcode) { + case opc_iconst_0: case opc_aconst_null: case opc_fconst_0: code_opcode = opc_iconst_0; break; + case opc_lconst_0: case opc_dconst_0: code_opcode = opc_lconst_0; break; - case opc_sipush: - case opc_ldc: - case opc_ldc_w: - case opc_ldc_quick: - case opc_ldc_w_quick: - code_opcode = opc_bipush; break; - case opc_ldc2_w_quick: - code_opcode = opc_ldc2_w; break; - - case opc_fload: - case opc_aload: - code_opcode = opc_iload; break; - case opc_dload: - code_opcode = opc_lload; break; - - case opc_fload_0: - case opc_aload_0: - code_opcode = opc_iload_0; break; - case opc_fload_1: - case opc_aload_1: - code_opcode = opc_iload_1; break; - case opc_fload_2: - case opc_aload_2: - code_opcode = opc_iload_2; break; - case opc_fload_3: - case opc_aload_3: - code_opcode = opc_iload_3; break; - case opc_dload_0: - code_opcode = opc_lload_0; break; - case opc_dload_1: - code_opcode = opc_lload_1; break; - case opc_dload_2: - code_opcode = opc_lload_2; break; - case opc_dload_3: - code_opcode = opc_lload_3; break; - case opc_faload: - case opc_aaload: + case opc_bipush: case opc_sipush: + case opc_ldc: case opc_ldc_w: + case opc_ldc_quick: case opc_ldc_w_quick: + /* `code_opcode = opc_bipush' is located after the switch sentence. */ + switch (code_opcode) { + case opc_bipush: + operand = (signed char)bytepc[1]; /* signed */ + break; + case opc_sipush: + operand = GET_INT16(bytepc + 1); + break; + case opc_ldc: + case opc_ldc_quick: + operand = bytepc[1]; /* unsigned */ + break; + case opc_ldc_w: + case opc_ldc_w_quick: + operand = GET_UINT16(bytepc + 1); + break; + } + code_opcode = opc_bipush; + break; + case opc_ldc2_w: case opc_ldc2_w_quick: + code_opcode = opc_ldc2_w; + operand = GET_UINT16(bytepc + 1); + break; + + case opc_iload: case opc_fload: case opc_aload: + code_opcode = opc_iload; + { + if (*bytepc == opc_wide) + operand = GET_UINT16(bytepc + 2); + else + operand = bytepc[1]; +#ifdef COMPILE_DEBUG + if (compile_debug) { printf(" index: %d\n", operand); fflush(stdout); } +#endif + } + break; + case opc_lload: case opc_dload: + code_opcode = opc_lload; + { + if (*bytepc == opc_wide) + operand = GET_UINT16(bytepc + 2); + else + operand = bytepc[1]; +#ifdef COMPILE_DEBUG + if (compile_debug) { printf(" index: %d\n", operand); fflush(stdout); } +#endif + } + break; + + case opc_iload_0: case opc_fload_0: case opc_aload_0: + code_opcode = opc_iload; operand = 0; + break; + case opc_iload_1: case opc_fload_1: case opc_aload_1: + code_opcode = opc_iload; operand = 1; + break; + case opc_iload_2: case opc_fload_2: case opc_aload_2: + code_opcode = opc_iload; operand = 2; + break; + case opc_iload_3: case opc_fload_3: case opc_aload_3: + code_opcode = opc_iload; operand = 3; + break; + + case opc_lload_0: case opc_dload_0: + code_opcode = opc_lload; operand = 0; + break; + case opc_lload_1: case opc_dload_1: + code_opcode = opc_lload; operand = 1; + break; + case opc_lload_2: case opc_dload_2: + code_opcode = opc_lload; operand = 2; + break; + case opc_lload_3: case opc_dload_3: + code_opcode = opc_lload; operand = 3; + break; + + case opc_iaload: case opc_faload: case opc_aaload: code_opcode = opc_iaload; break; - case opc_daload: + + case opc_laload: case opc_daload: code_opcode = opc_laload; break; - case opc_fstore: - case opc_astore: - code_opcode = opc_istore; break; - case opc_dstore: - code_opcode = opc_lstore; break; - - case opc_fstore_0: - case opc_astore_0: - code_opcode = opc_istore_0; break; - case opc_fstore_1: - case opc_astore_1: - code_opcode = opc_istore_1; break; - case opc_fstore_2: - case opc_astore_2: - code_opcode = opc_istore_2; break; - case opc_fstore_3: - case opc_astore_3: - code_opcode = opc_istore_3; break; - case opc_dstore_0: - code_opcode = opc_lstore_0; break; - case opc_dstore_1: - code_opcode = opc_lstore_1; break; - case opc_dstore_2: - code_opcode = opc_lstore_2; break; - case opc_dstore_3: - code_opcode = opc_lstore_3; break; + case opc_istore: case opc_fstore: case opc_astore: + code_opcode = opc_istore; + { + if (*bytepc == opc_wide) + operand = GET_UINT16(bytepc + 2); + else + operand = bytepc[1]; +#ifdef COMPILE_DEBUG + if (compile_debug) { printf(" index: %d\n", operand); fflush(stdout); } +#endif + } + break; + case opc_lstore: case opc_dstore: + code_opcode = opc_lstore; + { + if (*bytepc == opc_wide) + operand = GET_UINT16(bytepc + 2); + else + operand = bytepc[1]; +#ifdef COMPILE_DEBUG + if (compile_debug) { printf(" index: %d\n", operand); fflush(stdout); } +#endif + } + break; + + case opc_istore_0: case opc_fstore_0: case opc_astore_0: + code_opcode = opc_istore; operand = 0; + break; + case opc_istore_1: case opc_fstore_1: case opc_astore_1: + code_opcode = opc_istore; operand = 1; + break; + case opc_istore_2: case opc_fstore_2: case opc_astore_2: + code_opcode = opc_istore; operand = 2; + break; + case opc_istore_3: case opc_fstore_3: case opc_astore_3: + code_opcode = opc_istore; operand = 3; + break; + + case opc_lstore_0: case opc_dstore_0: + code_opcode = opc_lstore; operand = 0; + break; + case opc_lstore_1: case opc_dstore_1: + code_opcode = opc_lstore; operand = 1; + break; + case opc_lstore_2: case opc_dstore_2: + code_opcode = opc_lstore; operand = 2; + break; + case opc_lstore_3: case opc_dstore_3: + code_opcode = opc_lstore; operand = 3; + break; - case opc_fastore: + case opc_iastore: case opc_fastore: code_opcode = opc_iastore; break; - case opc_dastore: +/* + case opc_aastore: + code_opcode = opc_aastore; break; +*/ + case opc_lastore: case opc_dastore: code_opcode = opc_lastore; break; - case opc_if_acmpeq: + case opc_iinc: + /* code_opcode = opc_iinc; */ + { + if (*bytepc == opc_wide) + operand = GET_UINT16(bytepc + 2); + else + operand = bytepc[1]; +#ifdef COMPILE_DEBUG + if (compile_debug) { printf(" index: %d\n", operand); fflush(stdout); } +#endif + } + break; + + case opc_if_icmpeq: case opc_if_acmpeq: code_opcode = opc_if_icmpeq; break; - case opc_if_acmpne: + case opc_if_icmpne: case opc_if_acmpne: code_opcode = opc_if_icmpne; break; - case opc_freturn: - case opc_areturn: + case opc_ireturn: case opc_freturn: case opc_areturn: code_opcode = opc_ireturn; break; - case opc_dreturn: + case opc_lreturn: case opc_dreturn: code_opcode = opc_lreturn; break; - case opc_ifnull: + case opc_ifeq: case opc_ifnull: code_opcode = opc_ifeq; break; - case opc_ifnonnull: + case opc_ifne: case opc_ifnonnull: code_opcode = opc_ifne; break; - case opc_goto_w: + case opc_goto: case opc_goto_w: code_opcode = opc_goto; break; - case opc_jsr_w: + case opc_jsr: case opc_jsr_w: code_opcode = opc_jsr; break; + case opc_ret: + /* code_opcode = opc_ret; */ + operand = bytepc[1]; + break; #define ADJUST_GETMEMBER(vop) \ - case opc_##vop##:\ {\ - unsigned index = GET_UINT16(bytepc + 1);\ struct fieldblock *fb;\ char *sig;\ \ - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) {\ + operand = GET_UINT16(bytepc + 1);\ + \ + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) {\ if (!ResolveClassConstantFromClass2(\ - fieldclass(&mb->fb), index,\ + fieldclass(&mb->fb), operand,\ cc->ee, 1 << CONSTANT_Fieldref, FALSE)) {\ code_opcode = opc_throw_noclassdef;\ exceptionClear(cc->ee);\ @@ -648,62 +877,95 @@ }\ \ if (code_opcode != opc_throw_noclassdef) {\ - fb = constant_pool[index].fb;\ + fb = constant_pool[operand].fb;\ sig = fieldsig(fb);\ code_opcode =\ ((sig[0] == SIGNATURE_LONG) || (sig[0] == SIGNATURE_DOUBLE)) ?\ opc_##vop##2 : opc_##vop;\ }\ - }\ - break + } + case opc_getstatic: ADJUST_GETMEMBER(getstatic); + break; + case opc_putstatic: ADJUST_GETMEMBER(putstatic); + break; + case opc_getfield: case opc_getfield_quick_w: ADJUST_GETMEMBER(getfield); + break; + case opc_putfield: case opc_putfield_quick_w: ADJUST_GETMEMBER(putfield); + break; case opc_getfield_quick: - code_opcode = opc_getfield; break; + code_opcode = opc_getfield; + operand = bytepc[1]; + break; case opc_putfield_quick: - code_opcode = opc_putfield; break; + code_opcode = opc_putfield; + operand = bytepc[1]; + break; case opc_getfield2_quick: - code_opcode = opc_getfield2; break; + code_opcode = opc_getfield2; + operand = bytepc[1]; + break; case opc_putfield2_quick: - code_opcode = opc_putfield2; break; + code_opcode = opc_putfield2; + operand = bytepc[1]; + break; case opc_getstatic_quick: - code_opcode = opc_getstatic; break; + code_opcode = opc_getstatic; + operand = GET_UINT16(bytepc + 1); + break; case opc_putstatic_quick: - code_opcode = opc_putstatic; break; + code_opcode = opc_putstatic; + operand = GET_UINT16(bytepc + 1); + break; case opc_getstatic2_quick: - code_opcode = opc_getstatic2; break; + code_opcode = opc_getstatic2; + operand = GET_UINT16(bytepc + 1); + break; case opc_putstatic2_quick: - code_opcode = opc_putstatic2; break; + code_opcode = opc_putstatic2; + operand = GET_UINT16(bytepc + 1); + break; + case opc_invokevirtual: case opc_invokevirtual_quick_w: - code_opcode = opc_invokevirtual; break; + code_opcode = opc_invokevirtual; + operand = GET_UINT16(bytepc + 1); + break; + case opc_invokespecial: case opc_invokenonvirtual_quick: case opc_invokesuper_quick: - code_opcode = opc_invokespecial; break; + code_opcode = opc_invokespecial; + operand = GET_UINT16(bytepc + 1); + break; + case opc_invokestatic: case opc_invokestatic_quick: - code_opcode = opc_invokestatic; break; + code_opcode = opc_invokestatic; + operand = GET_UINT16(bytepc + 1); + break; + case opc_invokeinterface: case opc_invokeinterface_quick: - code_opcode = opc_invokeinterface; break; + code_opcode = opc_invokeinterface; + operand = GET_UINT16(bytepc + 1); + break; case opc_new: case opc_anewarray: - code_opcode = opcode; + /* code_opcode = code_opcode; */ + operand = GET_UINT16(bytepc + 1); { /* check whether the class exists or not */ - unsigned index; - index = GET_UINT16(bytepc + 1); - - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) { + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { if (!ResolveClassConstantFromClass2( - fieldclass(&mb->fb), index, + fieldclass(&mb->fb), operand, cc->ee, 1 << CONSTANT_Class, FALSE)) { code_opcode = opc_throw_noclassdef; exceptionClear(cc->ee); @@ -711,39 +973,50 @@ } } break; + case opc_new_quick: + /* code_opcode = opc_new_quick; */ + operand = GET_UINT16(bytepc + 1); + break; + + case opc_newarray: + /* code_opcode = opc_newarray; */ + operand = bytepc[1]; +#ifdef COMPILE_DEBUG + if (compile_debug) { printf(" type: %d\n", operand); fflush(stdout); } +#endif + break; case opc_anewarray_quick: - code_opcode = opc_anewarray; break; + code_opcode = opc_anewarray; + operand = GET_UINT16(bytepc + 1); + break; + case opc_multianewarray: case opc_multianewarray_quick: - code_opcode = opc_multianewarray; break; + code_opcode = opc_multianewarray; + operand = GET_UINT16(bytepc + 1); + break; + case opc_checkcast: case opc_checkcast_quick: - code_opcode = opc_checkcast; break; + code_opcode = opc_checkcast; + operand = GET_UINT16(bytepc + 1); + break; + case opc_instanceof: case opc_instanceof_quick: - code_opcode = opc_instanceof; break; + code_opcode = opc_instanceof; + operand = GET_UINT16(bytepc + 1); + break; case opc_wide: - code_opcode = *(bytepc + 1); break; + code_opcode = *(bytepc + 1); + goto proc_opc_switch; /* translate again */ + break; default: - code_opcode = opcode; break; + /* code_opcode = code_opcode */ + break; } /* switch (opcode) */ - /* adjust for strictfp */ - if (OPT_SETQ(OPT_FRCSTRICTFP) || - (!OPT_SETQ(OPT_IGNSTRICTFP) && (mb->fb.access & ACC_STRICT))) { - switch (code_opcode) { - case opc_fmul: - code_opcode = opc_fmul_strict; break; - case opc_dmul: - code_opcode = opc_dmul_strict; break; - case opc_fdiv: - code_opcode = opc_fdiv_strict; break; - case opc_ddiv: - code_opcode = opc_ddiv_strict; break; - } - } - /* throwing IllegalAccessError if the access is not allowed */ { int opc_is_put = 0, opc_is_get = 0; @@ -762,8 +1035,7 @@ int fb_access; ClassClass *fb_class; /* the field must be already resolved above */ - index = GET_UINT16(bytepc + 1); - fb = constant_pool[index].fb; + fb = constant_pool[operand].fb; if (!(src_mb = cc->mb)) { #ifdef COMPILE_DEBUG @@ -812,15 +1084,13 @@ if ((code_opcode == opc_invokevirtual) || (code_opcode == opc_invokespecial) || (code_opcode == opc_invokestatic)) { - int index; struct methodblock *src_mb; struct fieldblock *method_fb; ClassClass *src_clazz, *method_clazz; - index = GET_UINT16(bytepc + 1); - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) { + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), - index, cc->ee, 1 << CONSTANT_Methodref, FALSE)) { + operand, cc->ee, 1 << CONSTANT_Methodref, FALSE)) { code_opcode = opc_throw_noclassdef; exceptionClear(cc->ee); @@ -836,7 +1106,7 @@ code_opcode = opc_throw_illegalaccess; goto check_invoke_done; } - method_fb = &constant_pool[index].mb->fb; + method_fb = &constant_pool[operand].mb->fb; src_clazz = fieldclass(&src_mb->fb); method_clazz = fieldclass(method_fb); @@ -901,20 +1171,18 @@ #ifdef SPECIAL_INLINING /* special inlining */ if (code_opcode == opc_invokestatic) { - int index; struct methodblock *method; - index = GET_UINT16(bytepc + 1); - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) { + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), - index, cc->ee, 1 << CONSTANT_Methodref, FALSE)) { + operand, cc->ee, 1 << CONSTANT_Methodref, FALSE)) { code_opcode = opc_throw_noclassdef; exceptionClear(cc->ee); } } if (code_opcode != opc_throw_noclassdef) { - method = constant_pool[index].mb; + method = constant_pool[operand].mb; if (!strcmp(cbName(fieldclass(&method->fb)), "java/lang/Math")) { char *mname = method->fb.name; @@ -945,22 +1213,21 @@ #if 1 /* translate invokevirtual to invokespecial */ if (opcode == opc_invokevirtual) { - unsigned index = GET_UINT16(bytepc + 1); struct methodblock *method; - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) { + 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", index, - CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, index)); + 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), - index, cc->ee, 1 << CONSTANT_Methodref, FALSE); + operand, cc->ee, 1 << CONSTANT_Methodref, FALSE); #if COMPILE_DEBUG if (compile_debug) { - printf(" resolving cp[%d] done.\n", index); + printf(" resolving cp[%d] done.\n", operand); if (exceptionOccurred(cc->ee)) { JHandle *exc = cc->ee->exception.exc; printf("exception occurred: %s\n", @@ -977,7 +1244,7 @@ } if (code_opcode != opc_throw_noclassdef) { - method = constant_pool[index].mb; + method = constant_pool[operand].mb; if (method->fb.access & (ACC_PRIVATE | ACC_FINAL)) { #ifdef COMPILE_DEBUG @@ -996,24 +1263,22 @@ /* translate invokevirtual Object# to invokeignored_quick */ if ((code_opcode == opc_invokespecial) || (code_opcode == opc_invokestatic)) { - int32_t index; struct methodblock *method; - index = GET_UINT16(bytepc + 1); - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) { + 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", index, - CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, index)); + 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), - index, cc->ee, 1 << CONSTANT_Methodref, FALSE); + operand, cc->ee, 1 << CONSTANT_Methodref, FALSE); #if COMPILE_DEBUG if (compile_debug) { - printf(" resolving cp[%d] done.\n", index); + printf(" resolving cp[%d] done.\n", operand); if (exceptionOccurred(cc->ee)) { JHandle *exc = cc->ee->exception.exc; printf("exception occurred: %s\n", @@ -1030,7 +1295,7 @@ } if (code_opcode != opc_throw_noclassdef) { - method = constant_pool[index].mb; + method = constant_pool[operand].mb; if (!(method->fb.access & (ACC_NATIVE | ACC_ABSTRACT)) && (method->code[0] == opc_return)) { @@ -1066,8 +1331,8 @@ #ifdef COMPILE_DEBUG if (compile_debug) { if (code_opcode != opcode) { - printf(" adj opc 0x%02x(%d) to 0x%02x(%d)\n", - opcode, opcode, code_opcode, code_opcode); + printf(" adj to 0x%02x(%d)\n", + code_opcode, code_opcode); fflush(stdout); } } @@ -1075,7 +1340,7 @@ /* register opcode, bytepc, state to the table */ - pctableAdd(cc, code_opcode, -1, *byteoffp, -1); + pctableAdd(cc, code_opcode, operand, byteoff); /* confirm whether the method may throw an exception */ @@ -1088,7 +1353,7 @@ /* update bytecode PC */ - if (opcode <= opc_nonnull_quick) { + if (opcode <= opc_nonnull_quick) { /* an original, not added insn. */ switch (opcode) { case opc_tableswitch: { @@ -1097,7 +1362,7 @@ int32_t h = (int32_t)ntohl((unsigned long)argp[2]); argp += 3 + (h - l + 1); - *byteoffp += ((unsigned char *)argp) - bytepc; + byteinc = ((unsigned char *)argp) - bytepc; } break; case opc_lookupswitch: @@ -1106,28 +1371,154 @@ int32_t npairs = (int32_t)ntohl((unsigned long)argp[1]); argp += 2 + (npairs * 2); - *byteoffp += ((unsigned char *)argp) - bytepc; + byteinc = ((unsigned char *)argp) - bytepc; } break; case opc_wide: if (*(bytepc + 1) == opc_iinc) - *byteoffp += 6; + byteinc = 6; else - *byteoffp += 4; + byteinc = 4; break; default: - *byteoffp += opcode_length[opcode]; + byteinc = opcode_length[opcode]; break; } /* switch (opcode) */ } /* if (opcode <= opc_nonnull_quick) */ - return 0; + return byteinc; +} + + +/* + * Recognize basic blocks. + */ +static void makeBlockStructure(CompilerContext *cc) { + pcentry *entry, *tgtentry, *next; + unsigned char *bytepc; + int opcode; + int tgtpc; + int i, j; +#ifdef COMPILE_DEBUG + int compile_debug = cc->compile_debug; +#endif + +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf("makeBlockSt():\n"); + fflush(stdout); + } +#endif + + for (i = 0; i < pctableLen(cc); i++) { +#define GET_NEXT \ + if (!(next = pctableNext(cc, entry))) break + + entry = cc->pctable + i; + opcode = entry->opcode; + bytepc = cc->mb->code + entry->byteoff; + + if ((opc_ifeq <= opcode) && (opcode <= opc_jsr)) { /* if*, goto, jsr */ + /* jump offset */ + if ((*bytepc == opc_goto_w) /*|| (*bytepc == opc_jsr_w)*/) + tgtpc = GET_INT32(bytepc + 1); + else + tgtpc = GET_INT16(bytepc + 1); + tgtpc += entry->byteoff; + +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" 0x%x(%d): to 0x%x(%d)\n", + entry->byteoff, entry->byteoff, tgtpc, tgtpc); + fflush(stdout); + } +#endif + + tgtentry = pctableGet(cc, tgtpc); + sysAssert(tgtentry != NULL); + pcentrySetBlockTop(tgtentry); + } + else if (opcode == opc_jsr) { + GET_NEXT; +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" jsr at 0x%x(%d)\n", entry->byteoff, entry->byteoff); + fflush(stdout); + } +#endif + pcentrySetBlockTop(next); + break; + } + else if (opcode == opc_tableswitch) { /* tableswitch */ + int32_t *argp = (int32_t *)ALIGNUP32(bytepc + 1); + int32_t defoff = (int32_t)ntohl((unsigned long)argp[0]) + entry->byteoff; + int32_t l = (int32_t)ntohl((unsigned long)argp[1]); + int32_t h = (int32_t)ntohl((unsigned long)argp[2]); +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" tableswitch at 0x%x(%d):\n", entry->byteoff, entry->byteoff); + fflush(stdout); + } +#endif + + tgtentry = pctableGet(cc, defoff); + sysAssert(tgtentry != NULL); + pcentrySetBlockTop(tgtentry); + + argp += 3; /* skip default, low, and high */ + + for (j = 0; j < (h - l + 1); j++) { + int32_t off = (int32_t)ntohl((unsigned long)argp[j]) + entry->byteoff; +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" to 0x%x(%d)\n", off, off); + fflush(stdout); + } +#endif + tgtentry = pctableGet(cc, off); + sysAssert(tgtentry != NULL); + pcentrySetBlockTop(tgtentry); + } + } + else if (opcode == opc_lookupswitch) { /* lookupswitch */ + int32_t *argp = (int32_t *)ALIGNUP32(bytepc + 1); + int32_t defoff = (int32_t)ntohl((unsigned long)argp[0]) + entry->byteoff; + int32_t npairs = (int32_t)ntohl((unsigned long)argp[1]); +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" lookupswitch at 0x%x(%d):\n", entry->byteoff, entry->byteoff); + fflush(stdout); + } +#endif + + tgtentry = pctableGet(cc, defoff); + sysAssert(tgtentry != NULL); + pcentrySetBlockTop(tgtentry); + + argp += 2; /* skip default and npairs */ + + for (j = 0; j < npairs; j++) { + int32_t off = ntohl((unsigned long)argp[1]) + entry->byteoff; +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" to 0x%x(%d)\n", off, off); + fflush(stdout); + } +#endif + tgtentry = pctableGet(cc, off); + sysAssert(tgtentry != NULL); + pcentrySetBlockTop(tgtentry); + + argp += 2; + } + } + } } static void updateStates(CompilerContext *cc) { pcentry *pctable; - int pctablelen = cc->pctablelen; + int pctablelen = pctableLen(cc); CodeTable *codep; int opcode; int state; @@ -1137,9 +1528,8 @@ #endif #ifdef COMPILE_DEBUG - if (compile_debug) { + if (compile_debug) printf("updateStates():\n"); - } #endif state = 0; for (i = 0; i < pctablelen; i++) { @@ -1147,7 +1537,7 @@ opcode = pctable->opcode; codep = &code_table[opcode][state]; - pctable->state = state; + pcentrySetState(pctable, state); #ifdef COMPILE_DEBUG if (compile_debug) { printf(" %s(0x%02x,%d)\tst:%d\n", @@ -1201,7 +1591,7 @@ int nativeoff = table->nativeoff; /* offset in byte code -> offset in native code */ cf->compiled_CatchFrame = (void *)nativeoff; - cf->state = table->state; + cf->state = pcentryState(table); cf++; } @@ -1223,6 +1613,7 @@ pcentry *pctable; int opcode, state; + int32_t operand; int32_t nativeoff = 0, nextoff = 0; unsigned char *bytepc; int i; @@ -1242,10 +1633,11 @@ } #endif - for (i = 0; i < cc->pctablelen; i++) { + for (i = 0; i < pctableLen(cc); i++) { pctable = cc->pctable + i; opcode = pctable->opcode; - state = pctable->state; + operand = pctable->operand; + state = pcentryState(pctable); bytepc = mb->code + pctable->byteoff; #ifdef COMPILE_DEBUG @@ -1310,9 +1702,12 @@ /* register jump instructions to table and update nextoff. */ - if ((opc_ifeq <= opcode) && (opcode <= opc_ret)) - /* || ((opc_ifnull <= opcode) && (opcode <= opc_ifnonnull)) */ - /* || (opcode == opc_goto_w) || (opcode == opc_jsr_w)) */ { + if ((opc_ifeq <= opcode) && (opcode <= opc_ret)) { + /* internal opcodes: + ifeq, ifne, iflt, ifge, ifgt, ifle, + if_icmpeq, if_icmne, if_icmlt, if_icmge, if_icmgt, if_icmle, + if_acmpeq, if_acmpne, + goto, jsr, ret */ int tgtoff = -1; int tgtstate; int last_state; @@ -1342,7 +1737,8 @@ jumpoff = GET_INT16(bytepc + 1); tgtoff = pctable->byteoff + jumpoff; tgttable = pctableGet(cc, tgtoff); - tgtstate = tgttable->state; + sysAssert(tgttable != NULL); + tgtstate = pcentryState(tgttable); #ifdef COMPILE_DEBUG if (compile_debug) { int tgtop = tgttable->opcode; @@ -1359,14 +1755,14 @@ /* || ((opc_ifnull <= opcode) && (opcode <= opc_ifnonnull)) */ { int rop = 0, rop_rev = 0; + switch (opcode) { #define JP_CASE(OP, ROP4, ROP_REV1) \ - case opc_if##OP:\ - case opc_if_icmp##OP:\ - rop = ROP4; rop_rev = ROP_REV1;\ - break + case opc_if##OP:\ + case opc_if_icmp##OP:\ + rop = ROP4; rop_rev = ROP_REV1;\ + break /* 0x0f, ROP4 takes 4 byte operand, ROP_REV1 takes 1 byte. */ - switch (opcode) { JP_CASE(eq, 0x84/*je*/, 0x75/*jne*/); JP_CASE(ne, 0x85/*jne*/, 0x74/*je*/); JP_CASE(lt, 0x8c/*jl*/, 0x7d/*jge*/); @@ -1390,29 +1786,30 @@ } /* code_statetoX */ pctableInsert(cc, i + 1, - opc_stateto0 + tgtstate, last_state, - pctable->byteoff, nextoff); + opc_stateto0 + tgtstate, -1/* as operand */, pctable->byteoff, + last_state, nextoff); i++; writeToBuffer(cc, (unsigned char *)assembledCode + transcodep->offset, transcodep->length); nextoff += transcodep->length; + /* jmp X(4byte) */ { unsigned char code_jp[] = { 0xe9, 0, 0, 0, 0 }; writeToBuffer(cc, code_jp, 5); + nextoff += 5; } - nextoff += 5; } jptableAdd(cc, tgtoff, nextoff - 4); } - else /* ((opc_goto <= opcode) || (opcode <= opc_ret)) */ - /* || ((opcode == opc_goto_w) && (opcode == opc_jsr_w)) */ { + else { + /* internal opcodes: goto, jsr, ret */ /* code_sattetoX */ pctableInsert(cc, i + 1, - opc_stateto0 + tgtstate, last_state, - pctable->byteoff, nextoff); + opc_stateto0 + tgtstate, -1/* as operand */, pctable->byteoff, + last_state, nextoff); i++; writeToBuffer(cc, (unsigned char *)assembledCode + transcodep->offset, transcodep->length); @@ -1442,167 +1839,123 @@ switch (opcode) { case opc_bipush: { - int32_t v; - switch (*bytepc) { - case opc_bipush: - v = (signed char)bytepc[1]; -#ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" const: %d\n", v); fflush(stdout); - } -#endif - break; - case opc_sipush: - v = GET_INT16(bytepc + 1); -#ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" const: %d\n", v); fflush(stdout); - } -#endif - break; - case opc_ldc: - v = bytepc[1]; -#ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" index: %d\n", v); fflush(stdout); - } -#endif - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, v)) - if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), v, cc->ee, + int orig_opc = *bytepc; + + if ((orig_opc == opc_ldc) || (orig_opc == opc_ldc_w) || + (orig_opc == opc_ldc_quick) || (orig_opc == opc_ldc_w_quick)) { + if ((orig_opc == opc_ldc) || (orig_opc == opc_ldc_w)) { + sysAssert(operand != -1); + /* resolve */ + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) + if (!ResolveClassConstantFromClass2( + fieldclass(&mb->fb), operand, cc->ee, (1 << CONSTANT_Integer) | (1 << CONSTANT_Float) | - (1 << CONSTANT_String), - FALSE)) - return 1; - if (CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, v) == - CONSTANT_String) - goto wc_ldc_break; - v = constant_pool[v].i; - break; - case opc_ldc_w: - v = GET_UINT16(bytepc + 1); -#ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" index: %d\n", v); fflush(stdout); + (1 << CONSTANT_String), FALSE)) { + return 1; + } } -#endif - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, v)) - if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), v, cc->ee, - (1 << CONSTANT_Integer) | (1 << CONSTANT_Float) | - (1 << CONSTANT_String), - FALSE)) - return 1; - if (CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, v) == - CONSTANT_String) - goto wc_ldc_break; - v = constant_pool[v].i; - break; - case opc_ldc_quick: - v = bytepc[1]; + if (CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, operand) != + CONSTANT_String) { + int32_t val = constant_pool[operand].i; #ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" index: %d\n", v); fflush(stdout); - } + if (compile_debug) { + printf(" index: %d\n", operand); + if (CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, operand) == + CONSTANT_Integer) + printf(" value: %d\n", val); + else + printf(" value: %e(float)\n", val); + fflush(stdout); + } #endif - if (CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, v) == - CONSTANT_String) - goto wc_ldc_break; - v = constant_pool[v].i; - break; - case opc_ldc_w_quick: - v = GET_UINT16(bytepc + 1); + memcpy(bufp + constant_table[opcode][state][0], &val, 4); + } + } + else { /* other than opc_ldc* */ #ifdef COMPILE_DEBUG if (compile_debug) { - printf(" index: %d\n", v); fflush(stdout); + printf(" value: %d\n", operand); fflush(stdout); } #endif - if (CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, v) == - CONSTANT_String) - goto wc_ldc_break; - v = constant_pool[v].i; - break; - default: - goto wc_ldc_break; + memcpy(bufp + constant_table[opcode][state][0], &operand, 4); } - - memcpy(bufp + constant_table[opcode][state][0], &v, 4); } - wc_ldc_break: break; case opc_ldc2_w: { - int index = GET_UINT16(bytepc + 1); - int32_t cp_entry1 = constant_pool[index].i; - int32_t cp_entry2 = constant_pool[index + 1].i; + int32_t cp_entry[2]; + sysAssert(operand != -1); #ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" index: %d\n", index); fflush(stdout); - } + if (compile_debug) { printf(" index: %d\n", operand); fflush(stdout);} #endif - if (*bytepc == opc_ldc2_w) { - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) { + if (*bytepc == opc_ldc2_w) { /* resolve */ + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { if (!ResolveClassConstantFromClass2( - fieldclass(&mb->fb), index, cc->ee, - (1 << CONSTANT_Long) | (1 << CONSTANT_Double), - FALSE)) + fieldclass(&mb->fb), operand, cc->ee, + (1 << CONSTANT_Long) | (1 << CONSTANT_Double), FALSE)) return 1; } - cp_entry1 = constant_pool[index].i; - cp_entry2 = constant_pool[index + 1].i; - } /* opc_ldc2_w_quick */ - memcpy(bufp + constant_table[opcode][state][0], &cp_entry2, 4); - memcpy(bufp + constant_table[opcode][state][1], &cp_entry1, 4); + } + cp_entry[0] = constant_pool[operand].i; + cp_entry[1] = constant_pool[operand + 1].i; +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" value: %lld, %15g\n", + *((long long *)cp_entry), *((double *)cp_entry)); + fflush(stdout); + } +#endif + + memcpy(bufp + constant_table[opcode][state][0], cp_entry + 1, 4); + memcpy(bufp + constant_table[opcode][state][1], cp_entry, 4); } break; - case opc_iload: - case opc_istore: + case opc_iload: case opc_fload_fld: + case opc_istore: case opc_istld: case opc_ret: { int32_t index; - if (*bytepc == opc_wide) - index = GET_UINT16(bytepc + 2); - else - index = bytepc[1]; + sysAssert(operand != -1); #ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" index: %d\n", index); fflush(stdout); - } + if (compile_debug) { printf(" index: %d\n", operand); fflush(stdout);} #endif + + index = operand * -4; + memcpy(bufp + constant_table[opcode][state][0], &index, 4); #ifdef RUNTIME_DEBUG - memcpy(bufp + constant_table[opcode][state][1], &index, 4); + if (opcode != opc_fload_fld) { + memcpy(bufp + constant_table[opcode][state][1], &operand, 4); + } #endif - index *= -4; - memcpy(bufp + constant_table[opcode][state][0], &index, 4); } break; - case opc_lload: - case opc_lstore: + case opc_lload: case opc_dload_dld: + case opc_lstore: case opc_lstld: { int32_t index; - if (*bytepc == opc_wide) - index = GET_UINT16(bytepc + 2); - else - index = bytepc[1]; + sysAssert(operand != -1); #ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" index: %d\n", index); fflush(stdout); - } + if (compile_debug) { printf(" index: %d\n", operand); fflush(stdout);} #endif - index = (index + 1) * -4; + + index = (operand + 1) * -4; memcpy(bufp + constant_table[opcode][state][0], &index, 4); + if (opcode != opc_dload_dld) { + index += 4; + memcpy(bufp + constant_table[opcode][state][1], &index, 4); #ifdef RUNTIME_DEBUG - memcpy(bufp + constant_table[opcode][state][2], &index, 4); + memcpy(bufp + constant_table[opcode][state][2], &operand, 4); #endif - index += 4; - memcpy(bufp + constant_table[opcode][state][1], &index, 4); + } } break; #if defined(METAVM) && !defined(METAVM_NO_ARRAY) - case opc_iaload: /* includes opc_aaload */ + case opc_iaload: case opc_faload_fld: case opc_baload: case opc_caload: case opc_saload: @@ -1616,7 +1969,7 @@ } break; - case opc_iastore: + case opc_iastore: /* including fastore */ case opc_bastore: case opc_castore: case opc_sastore: @@ -1637,27 +1990,29 @@ case opc_iinc: { int32_t index, constbyte; + sysAssert(operand != -1); if (*bytepc == opc_wide) { - index = GET_UINT16(bytepc + 2); constbyte = GET_INT16(bytepc + 4); } else { - index = bytepc[1]; - constbyte = ((signed char *)bytepc)[2]; + constbyte = (signed char)bytepc[2]; } #ifdef COMPILE_DEBUG if (compile_debug) { - printf(" vars[%d] += %d\n", index, constbyte); fflush(stdout); + printf(" vars[%d] += %d\n", operand, constbyte); fflush(stdout); } #endif - index *= -4; + index = operand * -4; #ifdef RUNTIME_DEBUG memcpy(bufp + constant_table[opcode][state][2], &index, 4); memcpy(bufp + constant_table[opcode][state][2] + 4, &constbyte, 4); + /* for IINC_DEBUG1 */ memcpy(bufp + constant_table[opcode][state][0], &index, 4); - memcpy(bufp + constant_table[opcode][state][1], &index, 4); + memcpy(bufp + constant_table[opcode][state][1], &operand, 4); + + /* for IINC_DEBUG2 */ memcpy(bufp + constant_table[opcode][state][3], &index, 4); memcpy(bufp + constant_table[opcode][state][4], &constbyte, 4); #else @@ -1763,19 +2118,19 @@ {\ struct fieldblock *fb = NULL;\ int32_t slot;\ + sysAssert(operand != -1);\ + \ if ((*bytepc == opc_##vop##_quick) || (*bytepc == opc_##vop##2_quick))\ /* after lossy translation (which is suppressed) */\ - slot = bytepc[1];\ + slot = operand;\ else { /* ..field, ..field_quick_w */\ - int index = GET_UINT16(bytepc + 1);\ - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) {\ + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) {\ if (!ResolveClassConstantFromClass2(\ - fieldclass(&mb->fb), index, cc->ee,\ - 1 << CONSTANT_Fieldref,\ - FALSE))\ + fieldclass(&mb->fb), operand, cc->ee,\ + 1 << CONSTANT_Fieldref, FALSE))\ return 1;\ }\ - fb = constant_pool[index].fb;\ + fb = constant_pool[operand].fb;\ CONST_GETMEMBER_DEBUG1;\ slot = fb->u.offset / sizeof(OBJECT);\ }\ @@ -1802,7 +2157,7 @@ } # define WC_CONST_INVOKE_DEBUG2() \ if (compile_debug) {\ - method = constant_pool[index].mb;\ + method = constant_pool[operand].mb;\ printf(" clz initialized: %s\n",\ (CB_INITIALIZED(method->fb.clazz) ? "true" : "false"));\ if (!(method->CompiledCodeInfo)) {\ @@ -1830,17 +2185,16 @@ #define WC_CONST_INVOKE(vop, VIRTUALP, INTERFACEP) \ {\ - int32_t index;\ struct methodblock *method;\ char *sig;\ int32_t args_size, localvar_space, ret_size;\ + sysAssert(operand != -1);\ \ - index = GET_UINT16(bytepc + 1);\ if (*bytepc == opc_invoke##vop) {\ - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) {\ + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) {\ WC_CONST_INVOKE_DEBUG1();\ if (!ResolveClassConstantFromClass2(\ - fieldclass(&mb->fb), index, cc->ee,\ + fieldclass(&mb->fb), operand, cc->ee,\ 1 << (INTERFACEP ?\ CONSTANT_InterfaceMethodref : CONSTANT_Methodref),\ FALSE))\ @@ -1848,7 +2202,7 @@ }\ WC_CONST_INVOKE_DEBUG2();\ }\ - method = constant_pool[index].mb;\ + method = constant_pool[operand].mb;\ args_size = method->args_size;\ \ localvar_space = (method->nlocals - args_size);\ @@ -1909,22 +2263,18 @@ case opc_newarray: { - int32_t type = bytepc[1]; -#ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" type: %d\n", type); fflush(stdout); - } -#endif - memcpy(bufp + constant_table[opcode][state][0], &type, 4); + sysAssert(operand != -1); + memcpy(bufp + constant_table[opcode][state][0], &operand, 4); } break; case opc_multianewarray: { int32_t dimensions = bytepc[3]; + sysAssert(operand != -1); #ifdef COMPILE_DEBUG if (compile_debug) { - printf(" index: %d\n dimensions: %d\n", index, dimensions); + printf(" index: %d\n dimensions: %d\n", operand, dimensions); fflush(stdout); } #endif @@ -1975,7 +2325,7 @@ /* update native offset */ nativeoff = nextoff; - } /* for (i = 0; i < cc->pctablelen; i++) */ + } /* for (i = 0; i < pctableLen(cc); i++) */ #ifdef COMPILE_DEBUG if (compile_debug) { @@ -1997,6 +2347,7 @@ pcentry *pctable; int opcode, state; + int32_t operand; int32_t nativeoff = 0; unsigned char *bytepc; int i; @@ -2007,10 +2358,11 @@ int compile_debug = cc->compile_debug; #endif - for (i = 0; i < cc->pctablelen; i++) { + for (i = 0; i < pctableLen(cc); i++) { pctable = cc->pctable + i; opcode = pctable->opcode; - state = pctable->state; + operand = pctable->operand; + state = pcentryState(pctable); bytepc = mb->code + pctable->byteoff; nativeoff = pctable->nativeoff; @@ -2044,97 +2396,51 @@ switch (opcode) { case opc_bipush: - { - int32_t v; - switch (*bytepc) { - case opc_ldc: - v = bytepc[1]; -#ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" index: %d\n", v); fflush(stdout); - } -#endif - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, v)) - if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), v, cc->ee, - (1 << CONSTANT_Integer) | (1 << CONSTANT_Float) | - (1 << CONSTANT_String), - FALSE)) - return 1; - if (CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, v) != - CONSTANT_String) - goto rc_ldc_break; - v = constant_pool[v].i; - break; - case opc_ldc_w: - v = GET_UINT16(bytepc + 1); -#ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" index: %d\n", v); fflush(stdout); - } -#endif - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, v)) - if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb), v, cc->ee, - (1 << CONSTANT_Integer) | (1 << CONSTANT_Float) | - (1 << CONSTANT_String), - FALSE)) - return 1; - if (CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, v) != - CONSTANT_String) - goto rc_ldc_break; - v = constant_pool[v].i; - break; - case opc_ldc_quick: - v = bytepc[1]; -#ifdef COMPILE_DEBUG - if (compile_debug) { - printf(" index: %d\n", v); fflush(stdout); - } -#endif - if (CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, v) != - CONSTANT_String) - goto rc_ldc_break; - v = constant_pool[v].i; - break; - case opc_ldc_w_quick: - v = GET_UINT16(bytepc + 1); + switch (*bytepc) { + case opc_ldc: + case opc_ldc_w: + case opc_ldc_quick: + case opc_ldc_w_quick: + sysAssert(operand != -1); + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) + if (!ResolveClassConstantFromClass2( + fieldclass(&mb->fb), operand, cc->ee, + (1 << CONSTANT_Integer) | (1 << CONSTANT_Float) | + (1 << CONSTANT_String), FALSE)) + return 1; + if (CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, operand) == + CONSTANT_String) { + int32_t val = constant_pool[operand].i; #ifdef COMPILE_DEBUG if (compile_debug) { - printf(" index: %d\n", v); fflush(stdout); + printf(" index: %d\n value: 0x%x\n", operand, val); + fflush(stdout); } #endif - if (CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, v) != - CONSTANT_String) - goto rc_ldc_break; - v = constant_pool[v].i; - break; - default: - goto rc_ldc_break; + memcpy(bufp + constant_table[opcode][state][0], &val, 4); } - - memcpy(bufp + constant_table[opcode][state][0], &v, 4); + break; } - rc_ldc_break: break; case opc_getstatic: case opc_putstatic: { - unsigned index = GET_UINT16(bytepc + 1); struct fieldblock *fb; OBJECT *addr; + sysAssert(operand != -1); #ifdef COMPILE_DEBUG if (compile_debug) { - printf(" index: %d\n", index); fflush(stdout); + printf(" index: %d\n", operand); fflush(stdout); } #endif - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) { + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { if (!ResolveClassConstantFromClass2( - fieldclass(&mb->fb), index, cc->ee, - 1 << CONSTANT_Fieldref, - FALSE)) + fieldclass(&mb->fb), operand, cc->ee, + 1 << CONSTANT_Fieldref, FALSE)) return 1; } - fb = constant_pool[index].fb; + fb = constant_pool[operand].fb; #ifdef COMPILE_DEBUG if (compile_debug) { printf(" %s#%s\n", cbName(fb->clazz), fb->name); fflush(stdout); @@ -2159,22 +2465,21 @@ case opc_getstatic2: case opc_putstatic2: { - int32_t index = GET_UINT16(bytepc + 1); struct fieldblock *fb; stack_item *addr; + sysAssert(operand != -1); #ifdef COMPILE_DEBUG if (compile_debug) { - printf(" index: %d\n", index); fflush(stdout); + printf(" index: %d\n", operand); fflush(stdout); } #endif - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) { + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) { if (!ResolveClassConstantFromClass2( - fieldclass(&mb->fb), index, cc->ee, - 1 << CONSTANT_Fieldref, - FALSE)) + fieldclass(&mb->fb), operand, cc->ee, + 1 << CONSTANT_Fieldref, FALSE)) return 1; } - fb = constant_pool[index].fb; + fb = constant_pool[operand].fb; #ifdef COMPILE_DEBUG if (compile_debug) { printf(" %s#%s\n", cbName(fb->clazz), fb->name); fflush(stdout); @@ -2222,21 +2527,19 @@ #define RC_CONST_INVOKE(vop, VIRTUALP, INTERFACEP) \ {\ - unsigned index;\ struct methodblock *method;\ \ - index = GET_UINT16(bytepc + 1);\ if (*bytepc == opc_invoke##vop) {\ - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) {\ + 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 << (INTERFACEP ?\ CONSTANT_InterfaceMethodref : CONSTANT_Methodref),\ FALSE))\ return 1;\ }\ }\ - method = constant_pool[index].mb;\ + method = constant_pool[operand].mb;\ \ RC_CONST_INVOKE_DEBUG1;\ \ @@ -2267,7 +2570,7 @@ #ifdef COMPILE_DEBUG # define CONST_NEW_DEBUG1 \ if (compile_debug) {\ - printf(" index: %d\n", index); fflush(stdout);\ + printf(" index: %d\n", operand); fflush(stdout);\ } # define CONST_NEW_DEBUG2 \ if (compile_debug) {\ @@ -2286,20 +2589,20 @@ #endif #define _CONST_NEW(vop, RESOLVE) \ - int32_t index = GET_UINT16(bytepc + 1);\ ClassClass *cb;\ + sysAssert(operand != -1);\ CONST_NEW_DEBUG1;\ \ if (RESOLVE) {\ if (*bytepc == opc_##vop) {\ - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) {\ + if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, operand)) {\ if (!ResolveClassConstantFromClass2(fieldclass(&mb->fb),\ - index, cc->ee, 1 << CONSTANT_Class, FALSE))\ + operand, cc->ee, 1 << CONSTANT_Class, FALSE))\ return 1;\ }\ }\ }\ - cb = constant_pool[index].clazz;\ + cb = constant_pool[operand].clazz;\ CALL_INITCLASS_NEW;\ CONST_NEW_DEBUG2; #define CONST_NEW1(vop, RESOLVE) \ @@ -2340,25 +2643,24 @@ case opc_multianewarray: { - int32_t index = GET_UINT16(bytepc + 1); ClassClass *cb; + sysAssert(operand != -1); if (*bytepc == opc_multianewarray) { - if (!CONSTANT_POOL_TYPE_TABLE_IS_RESOLVED(type_table, index)) { + 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", index, - CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, index)); + 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), index, - cc->ee, 1 << CONSTANT_Class, - FALSE); + fieldclass(&mb->fb), operand, + cc->ee, 1 << CONSTANT_Class, FALSE); #if COMPILE_DEBUG if (compile_debug) { - printf(" resolving cp[%d] done.\n", index); + printf(" resolving cp[%d] done.\n", operand); if (exceptionOccurred(cc->ee)) { JHandle *exc = cc->ee->exception.exc; printf("exception occurred: %s\n", @@ -2371,7 +2673,7 @@ if (!res_result) return 1; } } - cb = constant_pool[index].clazz; + cb = constant_pool[operand].clazz; #ifdef COMPILE_DEBUG if (compile_debug) { printf(" clazz: %s\n", cbName(cb)); fflush(stdout); @@ -2397,7 +2699,7 @@ break; #endif } /* resolve constants: switch (opcode) */ - } /* for (i = 0; i < cc->pctablelen; i++) */ + } /* for (i = 0; i < pctableLen(cc); i++) */ #ifdef COMPILE_DEBUG if (compile_debug) { @@ -2447,7 +2749,7 @@ unsigned char *nativeCode = cc->buffer; pcentry *pctable = cc->pctable; - pcentry *pctable_end = pctable + cc->pctablelen; + pcentry *pctable_end = pctable + pctableLen(cc); int i; #ifdef COMPILE_DEBUG @@ -2456,7 +2758,7 @@ while (pctable < pctable_end) { int opcode = pctable->opcode; - int state = pctable->state; + int state = pcentryState(pctable); #ifdef COMPILE_DEBUG if (compile_debug) { int byteoff = pctable->byteoff; @@ -2572,8 +2874,9 @@ /* default */ tgttable = pctableGet(cc, byteoff + defoff); + sysAssert(tgttable != NULL); tblp[0] = tgttable->nativeoff; - codep = &code_table[opc_goto_st0 + tgttable->state][last_state]; + codep = &code_table[opc_goto_st0 + pcentryState(tgttable)][last_state]; tblp[1] = (int32_t)(((unsigned char *)assembledCode) + codep->offset); #ifdef COMPILE_DEBUG if (compile_debug) { @@ -2584,13 +2887,15 @@ } #endif tblp += 2; - argp += 3; /* skit default, low and high */ + argp += 3; /* skit default, low, and high */ for (i = 0; i < (h - l + 1); i++) { int32_t off = (int32_t)ntohl((unsigned long)argp[i]); tgttable = pctableGet(cc, byteoff + off); + sysAssert(tgttable != NULL); tblp[0] = tgttable->nativeoff; - codep = &code_table[opc_goto_st0 + tgttable->state][last_state]; + codep = + &code_table[opc_goto_st0 + pcentryState(tgttable)][last_state]; tblp[1] = (int32_t)(((unsigned char *)assembledCode) + codep->offset); #ifdef COMPILE_DEBUG @@ -2648,8 +2953,10 @@ tblp[0] = match; tgttable = pctableGet(cc, byteoff + off); + sysAssert(tgttable != NULL); tblp[1] = tgttable->nativeoff; - codep = &code_table[opc_goto_st0 + tgttable->state][last_state]; + codep = + &code_table[opc_goto_st0 + pcentryState(tgttable)][last_state]; tblp[2] = (int32_t)(((unsigned char *)assembledCode) + codep->offset); #ifdef COMPILE_DEBUG @@ -2666,9 +2973,10 @@ /* (int32_t)dummy_match and (int32_t)default */ tgttable = pctableGet(cc, byteoff + defoff); + sysAssert(tgttable != NULL); tblp[0] = 0; tblp[1] = tgttable->nativeoff; - codep = &code_table[opc_goto_st0 + tgttable->state][last_state]; + codep = &code_table[opc_goto_st0 + pcentryState(tgttable)][last_state]; tblp[2] = (int32_t)(((unsigned char *)assembledCode) + codep->offset); #ifdef COMPILE_DEBUG if (compile_debug) { @@ -2690,50 +2998,12 @@ } -#undef INITFUNC_DEBUG -void initFunctionSymbols() { - FuncTable *funcp; - int opcode, state; -#ifdef INITFUNC_DEBUG - printf("initFuncSym() called.\n"); fflush(stdout); -#endif - - for (opcode = 0; opcode < NOPCODES; opcode++) { - for (state = 0; state < NSTATES; state++) { - funcp = func_table[opcode][state]; - while (funcp->offset >= 0) { - char *funcptr; - - funcptr = (char *)symbolInSystemClassLoader(funcp->name); -#ifdef INITFUNC_DEBUG - printf(" 0x%02x(%d) st:%d `%s' offset %d\n", opcode, opcode, state, - funcp->name, funcp->offset); - printf(" addr. %08x\n", funcptr); - fflush(stdout); -#endif - if (!funcptr) { - /* NOTREACHED */ - fprintf(stderr, "FATAL: can't resolve a symbol `%s'\n", funcp->name); - JVM_Exit(1); - } - funcp->name = funcptr; - - funcp++; - } - } /* for (state) */ - } /* for (opcode) */ -#ifdef INITFUNC_DEBUG - printf("initFuncSym() done.\n\n"); fflush(stdout); -#endif -} - - #undef RES_FUNC_DEBUG static void resolveFunctionSymbols(CompilerContext *cc) { unsigned char *nativeCode = cc->mb->CompiledCode; pcentry *pctable = cc->pctable; - pcentry *pctable_end = pctable + cc->pctablelen; + pcentry *pctable_end = pctable + pctableLen(cc); FuncTable *funcp; #ifdef RES_FUNC_DEBUG @@ -2742,7 +3012,7 @@ while (pctable < pctable_end) { int opcode = pctable->opcode; - int state = pctable->state; + int state = pcentryState(pctable); funcp = func_table[opcode][state]; @@ -2751,11 +3021,11 @@ char *funcptr; int32_t arg; - funcptr = funcp->name; + funcptr = funcp->address; if (!funcptr) { /* NOTREACHED */ fprintf(stderr, "FATAL: symbol `%s' was not resolved.\n", - funcp->name); + funcp->address); JVM_Exit(1); } diff -aruN shujit-0.4.2/compiler.c shujit/compiler.c --- shujit-0.4.2/compiler.c Mon Feb 14 16:06:24 2000 +++ shujit/compiler.c Sun Apr 23 03:31:23 2000 @@ -229,84 +229,15 @@ } - /* initialization */ - - /* sysAddDLSegment() some libraries to get addresses of functions */ - /* __divdi3, __moddi3, printf, fflush in libc */ - /* fmod in libm */ +#ifdef FORCE_DOUBLE_PRECISION + /* set rounding precision as double */ { - char *libs_orig = getenv("JAVA_COMPILER_LIBS"); - if (!libs_orig) libs_orig = LIBS_ADDDLSEG; /* defined in compiler.h */ - - if (libs_orig) { - char *libs; - char sep, nextsep, *elem, *next; -#define NEXT {\ - char *commap, *barp;\ - elem = next; sep = nextsep;\ - commap = strchr(elem, ','); barp = strchr(elem, '|');\ - if (commap)\ - if (barp)\ - if (barp < commap) { next = barp; nextsep = '|'; }\ - else { next = commap; nextsep = ','; }\ - else { next = commap; nextsep = ','; }\ - else\ - if (barp) { next = barp; nextsep = '|'; }\ - else { next = strchr(elem, '\0'); nextsep = '\0'; }\ - *next = '\0'; next++;\ -} - -#define SKIP {\ - char *commap;\ - if (nextsep == ',') NEXT\ - else {\ - commap = strchr(next, ',');\ - if (commap) {\ - next = commap + 1; nextsep = ',';\ - NEXT\ - }\ - else sep = '\0';\ - }\ -} - - libs = strdup(libs_orig); - - next = libs; nextsep = '|'; /* initialize */ - NEXT - do { - int loaded = 0; - do { - struct stat buf; - if (!stat(elem, &buf)) { - if (JVM_LoadLibrary(elem)) { - loaded = 1; - break; - } - } -#ifdef COMPILE_DEBUG - else { - printf("can't stat() file: %s\n", elem); fflush(stdout); - } -#endif - NEXT - } while (sep == '|'); - - if (!loaded) { - printf("FATAL: JIT compiler can't find required libraries: %s\n", - libs_orig); - JVM_Exit(1); - } - - SKIP - } while (sep != '\0'); - - sysFree(libs); - } /* if (libs_orig) */ + unsigned short cw; + asm("fnstcw %0" : "=m"(cw)); + cw = (cw & ~0x0300) | 0x0200; + asm("fldcw %0" : : "m"(cw)); } - - - /* resolve function symbols in the func_table */ - initFunctionSymbols(); +#endif /* FORCE_DOUBLE_PRECISION */ /* resolve some symbols */ diff -aruN shujit-0.4.2/compiler.h shujit/compiler.h --- shujit-0.4.2/compiler.h Sun Feb 6 18:44:15 2000 +++ shujit/compiler.h Mon Apr 24 16:39:30 2000 @@ -32,70 +32,91 @@ /* * Internal Opcodes */ -#define opc_impdep1 254 /* 0xfe */ -#define opc_impdep2 255 +#define opc_impdep1 254 /* 0xfe */ +#define opc_impdep2 255 -#define opc_methodhead 256 /* 0x100 */ -#define opc_epilogue 257 -#define opc_exc_new 258 -#define opc_exc_handler 259 -#define opc_methodtail 260 -#define opc_syncenter 261 -#define opc_syncexit 262 -#define opc_strictenter 263 -#define opc_strictexit 264 - -#define opc_fppc_save 265 /* 0x109 */ -#define opc_fppc_restore 266 -#define opc_fppc_single 267 -#define opc_fppc_double 268 -#define opc_fppc_extended 269 - -#define opc_throw_illegalaccess 270 -#define opc_throw_noclassdef 271 - -#define opc_fill_cache 272 /* 0x110 */ -#define opc_array_check 273 - -#define opc_invokeignored_static 274 /* 0x112 */ - -#define opc_fmul_strict 275 /* 0x113 */ -#define opc_dmul_strict 276 -#define opc_fdiv_strict 277 -#define opc_ddiv_strict 278 - -#define opc_getstatic2 279 /* 0x117 */ -#define opc_putstatic2 280 -#define opc_getfield2 281 -#define opc_putfield2 282 - -#define opc_iastore1 283 /* 0x11b */ -#define opc_lastore1 284 - -#define opc_stateto0 285 /* 0x11d */ -#define opc_stateto1 286 -#define opc_stateto2 287 -#define opc_stateto3 288 -#define opc_stateto4 289 - -#define opc_goto_st0 290 /* 0x122 */ -#define opc_goto_st1 291 -#define opc_goto_st2 292 -#define opc_goto_st3 293 -#define opc_goto_st4 294 - -#define opc_sqrt 295 /* 0x125 */ -#define opc_sin 296 -#define opc_cos 297 -#define opc_tan 298 -#define opc_atan2 299 -#define opc_atan 300 -#define opc_exp 301 -#define opc_log 302 -#define opc_floor 303 -#define opc_ceil 304 +#define opc_methodhead 256 /* 0x100 */ +#define opc_epilogue 257 +#define opc_exc_new 258 +#define opc_exc_handler 259 +#define opc_methodtail 260 +#define opc_sync_enter 261 +#define opc_sync_exit 262 +#define opc_fld4 263 +#define opc_fld 264 +#define opc_fst 265 +#define opc_dld8 266 +#define opc_dld 267 +#define opc_dst 268 + +#define opc_strict_enter 269 +#define opc_strict_exit 270 + +#define opc_fppc_save 271 +#define opc_fppc_restore 272 +#define opc_fppc_single 273 +#define opc_fppc_double 274 +#define opc_fppc_extended 275 + +#define opc_strict_fprep 276 +#define opc_strict_fscdown 277 +#define opc_strict_fscup 278 +#define opc_strict_fsettle 279 +#define opc_strict_dprep 280 /* 0x108 */ +#define opc_strict_dscdown 281 +#define opc_strict_dscup 282 +#define opc_strict_dsettle 283 + +#define opc_throw_illegalaccess 284 +#define opc_throw_noclassdef 285 + +#define opc_fill_cache 286 +#define opc_flush_cache 287 /* 0x11f */ +#define opc_array_check 288 + +#define opc_invokeignored_static 289 + +#define opc_getstatic2 290 +#define opc_putstatic2 291 +#define opc_getfield2 292 +#define opc_putfield2 293 + +#define opc_iastore1 294 +#define opc_lastore1 295 + +#define opc_stateto0 296 +#define opc_stateto1 297 +#define opc_stateto2 298 +#define opc_stateto3 299 +#define opc_stateto4 300 + +#define opc_goto_st0 301 +#define opc_goto_st1 302 +#define opc_goto_st2 303 +#define opc_goto_st3 304 +#define opc_goto_st4 305 + +#define opc_sqrt 306 +#define opc_sin 307 +#define opc_cos 308 +#define opc_tan 309 +#define opc_atan2 310 +#define opc_atan 311 +#define opc_exp 312 +#define opc_log 313 +#define opc_floor 314 +#define opc_ceil 315 + +/* for OPTIMIZE_INTERNAL_CODE */ +#define opc_fload_fld 316 +#define opc_dload_dld 317 +#define opc_faload_fld 318 +#define opc_daload_dld 319 -#define NOPCODES 305 /* 0x131 */ +#define opc_istld 320 +#define opc_lstld 321 + +#define NOPCODES 322 /* offerred by Sun */ @@ -139,17 +160,19 @@ * macro definition */ -/* features */ +/* feature control */ #define NULLEXC_BY_SIGNAL #define ARITHEXC_BY_SIGNAL #define GET_SIGCONTEXT -#undef IGNORE_DISABLE +#define FORCE_DOUBLE_PRECISION +#define OPTIMIZE_INTERNAL_CODE +#define SPECIAL_INLINING +#define DIRECT_INV_NATIVE #undef NO_REWRITE #undef INITCLASS_IN_COMPILING +#undef IGNORE_DISABLE #undef CONTROL_COMPILED_FLAG -#define SPECIAL_INLINING -#define DIRECT_INV_NATIVE #if defined(NULLEXC_BY_SIGNAL) || defined(ARITHEXC_BY_SIGNAL) #define EXC_BY_SIGNAL @@ -168,13 +191,10 @@ #if defined(linux) # define SEARCH_SIGCONTEXT -# define LIBS_ADDDLSEG NULL #elif defined(__FreeBSD__) # undef SEARCH_SIGCONTEXT -# define LIBS_ADDDLSEG "/usr/lib/libc.so.3|/usr/lib/libc.so.3.1|/usr/lib/libc.so.3.0,/usr/lib/libm.so.2|/usr/lib/libm.so.2.0" #else # undef SEARCH_SIGCONTEXT -# define LIBS_ADDDLSEG NULL #endif @@ -399,6 +419,7 @@ int32_t ret_size; char *argsizes; char *terse_sig; + char *ret_sig; #ifdef DIRECT_INV_NATIVE char *code; /* old fasion native methods not wrapped by stub */ @@ -424,8 +445,9 @@ typedef struct pcentry { uint16_t opcode; - uint16_t state; - int32_t byteoff; /* must be able to be less than 0, so not unsigned */ + uint16_t flag; + int32_t operand; + int32_t byteoff; /* can be less than 0, so should be signed */ uint32_t nativeoff; } pcentry; @@ -619,12 +641,24 @@ extern void pctableExtend(CompilerContext *cc, uint32_t size); #endif /* CODE_DB */ extern void pctableClear(CompilerContext *cc); +extern uint32_t pctableLen(CompilerContext *cc); +extern void pctableSetLen(CompilerContext *cc, uint32_t len); extern void pctableAdd(CompilerContext *cc, - int opcode, int state, unsigned int byteoff, unsigned int nativeoff); -extern void pctableInsert(CompilerContext *cc, int index, - int opcode, int state, unsigned int byteoff, unsigned int nativeoff); + int opcode, int operand, unsigned int byteoff); +extern pcentry *pctableInsert(CompilerContext *cc, int index, + int opcode, int operand, unsigned int byteoff, + int state, int nativeoff); +extern void pctableNDelete(CompilerContext *cc, int index, int len); extern void pctableDelete(CompilerContext *cc, int index); +extern pcentry *pctableNext(CompilerContext *cc, pcentry *entry); extern pcentry *pctableGet(CompilerContext *cc, int byteoff); +extern void pcentryClear(pcentry *entry); +#define pcentryState(PCENTRY) (((PCENTRY)->flag) & 0xf) +#define pcentrySetState(PCENTRY, ST) \ + ((PCENTRY)->flag &= ~0xf); ((PCENTRY)->flag |= (ST & 0xf)) +#define pcentryBlockTop(PCENTRY) (((PCENTRY)->flag >> 4) & 0x1) +#define pcentrySetBlockTop(PCENTRY) ((PCENTRY)->flag |= 0x10) +#define pcentryClearBlockTop(PCENTRY) ((PCENTRY)->flag &= ~0x10) extern void jptableAdd(CompilerContext *cc, unsigned int tgtoff, unsigned int argoff); @@ -641,7 +675,6 @@ extern throwentry *throwtableGet(CodeInfo *info, uint32_t nativeoff); #endif /* EXC_BY_SIGNAL */ - /* in invoker.c */ extern bool_t compileAndInvokeMethod( JHandle *o, struct methodblock *mb, int args_size, ExecEnv *ee, @@ -653,7 +686,9 @@ /* in compile.c */ extern int compileMethod(struct methodblock *mb); extern void freeMethod(struct methodblock *mb); -extern void initFunctionSymbols(); + +/* in optimize.c */ +extern void optimizeInternalCode(CompilerContext *cc); #ifdef CODE_DB /* in codedb.c */ diff -aruN shujit-0.4.2/computil.c shujit/computil.c --- shujit-0.4.2/computil.c Sun Feb 6 15:47:29 2000 +++ shujit/computil.c Mon Apr 24 04:39:05 2000 @@ -290,8 +290,18 @@ } +inline uint32_t pctableLen(CompilerContext *cc) { + return cc->pctablelen; +} + + +void pctableSetLen(CompilerContext *cc, uint32_t len) { + cc->pctablelen = len; +} + + void pctableAdd(CompilerContext *cc, - int opcode, int state, unsigned int byteoff, unsigned int nativeoff) { + int opcode, int operand, unsigned int byteoff) { pcentry *entryp; if (cc->pctablelen >= cc->pctablesize) { /* extend table size */ @@ -303,18 +313,22 @@ } entryp = cc->pctable + cc->pctablelen; + entryp->opcode = opcode; - entryp->state = state; + entryp->operand = operand; entryp->byteoff = byteoff; - entryp->nativeoff = nativeoff; + + pcentrySetState(entryp, 0); + pcentryClearBlockTop(entryp); + entryp->nativeoff = -1; cc->pctablelen++; - if (opcode <= opc_nonnull_quick) cc->ninsn++; } -void pctableInsert(CompilerContext *cc, int index, - int opcode, int state, unsigned int byteoff, unsigned int nativeoff) { +pcentry *pctableInsert(CompilerContext *cc, int index, + int opcode, int operand, unsigned int byteoff, + int state, int nativeoff) { pcentry *entryp; if (cc->pctablelen >= cc->pctablesize) { /* extend table size */ @@ -327,23 +341,38 @@ memmove(entryp + 1, entryp, sizeof(pcentry) * (cc->pctablelen - index)); entryp->opcode = opcode; - entryp->state = state; + entryp->operand = operand; entryp->byteoff = byteoff; + pcentrySetState(entryp, state); entryp->nativeoff = nativeoff; - (cc->pctablelen)++; - if (opcode <= opc_nonnull_quick) cc->ninsn++; + pcentryClearBlockTop(entryp); + + cc->pctablelen++; + + return entryp; +} + + +void pctableNDelete(CompilerContext *cc, int index, int len) { + pcentry *entryp = cc->pctable + index; + + memmove(entryp, entryp + len, + sizeof(pcentry) * (cc->pctablelen - index - len)); + (cc->pctablelen) -= len; } void pctableDelete(CompilerContext *cc, int index) { - pcentry *entryp; - entryp = cc->pctable + index; + pctableNDelete(cc, index, 1); +} - (cc->pctablelen)--; - if (entryp->opcode <= opc_nonnull_quick) cc->ninsn--; - memmove(entryp, entryp + 1, sizeof(pcentry) * (cc->pctablelen - index)); +pcentry *pctableNext(CompilerContext *cc, pcentry *entry) { + if ((entry - cc->pctable) + 1 < cc->pctablelen) + return entry + 1; + else + return NULL; } @@ -367,6 +396,13 @@ } if (l == h) { /* not found */ +#ifdef COMPILE_DEBUG + struct methodblock *mb = cc->mb; + printf("FATAL: pctableGet(%s#%s %s)\n", + cbName(mb->fb.clazz), mb->fb.name, mb->fb.signature); + printf(" not found: %x(%d)\n", byteoff, byteoff); + fflush(stdout); +#endif return NULL; } @@ -378,6 +414,16 @@ } +void pcentryClear(pcentry *entry) { + entry->opcode = 0; + entry->operand = -1; + entry->byteoff = -1; + pcentrySetState(entry, 0); + pcentryClearBlockTop(entry); + entry->nativeoff = -1; +} + + /* Jump instruction table */ void jptableAdd(CompilerContext *cc, @@ -451,7 +497,9 @@ while (*sig) { switch (*sig) { case ')': - sizes[i++] = 0; terse_sig[j++] = TERSE_SIG_ENDFUNC; sig++; break; + sizes[i++] = 0; terse_sig[j++] = TERSE_SIG_ENDFUNC; sig++; + info->ret_sig = sig; + break; case 'V': sizes[i++] = 0; terse_sig[j++] = TERSE_SIG_VOID; sig++; break; case 'Z': @@ -490,7 +538,7 @@ fprintf(stderr, "FATAL: too many arguments (> %d).\n", AS_BUF_SIZE); JVM_Exit(1); } - } /* while (*sig != ')') */ + } /* while (*sig) */ info->argsizes = sysMalloc(i); memcpy(info->argsizes, sizes, i); diff -aruN shujit-0.4.2/gentable.rb shujit/gentable.rb --- shujit-0.4.2/gentable.rb Tue Dec 28 19:51:44 1999 +++ shujit/gentable.rb Mon Apr 24 02:54:42 2000 @@ -4,7 +4,7 @@ CONST_C_FNAME = 'constants.c' CONST_H_FNAME = 'constants.h' -NOPCODES = 305 +NOPCODES = 322 NSTATES = 5 STANY = 5 STSTA = 5 @@ -352,7 +352,7 @@ (0..(NSTATES - 1)).each do |j| f.print " {" $_ = func_table[i][j] - $_.each {|array| f.print "{#{array[0]}, \"#{array[1]}\"}, "} if $_ + $_.each {|array| f.print "{#{array[0]}, (char *)#{array[1]}}, "} if $_ f.print "{-1, 0}" if j == NSTATES - 1 f.print "}\n" @@ -383,6 +383,19 @@ open(CONST_H_FNAME, "w") do |f| + f.print <= 12 +extern sys_mon_t * monitorEnter2(struct execenv *, uintptr_t); +extern int monitorExit2(struct execenv *, uintptr_t); +#endif + +EOF if max_code_offset < 65536 && max_code_len < 256 f.print <invoker), cbName(mb->fb.clazz), mb->fb.name, mb->fb.signature); fflush(stdout); @@ -428,10 +429,25 @@ for (; i < args_size; i++) { JHandle *arg = vars[-i].h; - if ((sig[0] == 'D') || (sig[0] == 'J')) i++; - printf(" 0x%08x @ 0x%08x ", (int)arg, (int)(vars - i)); - sig = showObjectBody(sig, arg); - printf("\n"); + if ((sig[0] == 'J') || (sig[0] == 'D')) { + stack_item *argp; + + i++; + argp = vars - i; + + if (sig[0] == 'J') + printf(" %lld,0x%llx", *((long long *)argp)); + else + printf(" %10g", *((double *)argp)); + printf(" @ 0x%08x\n", argp); + + sig++; + } + else { + printf(" 0x%08x @ 0x%08x ", (int)arg, (int)(vars - i)); + sig = showObjectBody(sig, arg); + printf("\n"); + } } } fflush(stdout); @@ -472,6 +488,8 @@ #ifdef RUNTIME_DEBUG if (runtime_debug) { + CodeInfo *info = (CodeInfo *)mb->CompiledCodeInfo; + printf("compiled method finished by %x: %s#%s %s\n", (int)sysThreadSelf(), cbName(mb->fb.clazz), mb->fb.name, mb->fb.signature); @@ -489,9 +507,20 @@ showExcStackTrace(exc); fflush(stdout); } + else { + if ((*(info->ret_sig) != 'D') && (*(info->ret_sig) != 'J')) { + stack_item *optop = old_frame->optop; + + printf(" ret val: (%s)", info->ret_sig); + showObjectBody(info->ret_sig, optop[-1].h); + printf("\n"); + fflush(stdout); + } + } + printf("\n"); fflush(stdout); - } /* if (runtime_debug) */ + } #endif @@ -533,8 +562,17 @@ else if ((!strcmp(cbName(mb->fb.clazz), "java/lang/FloatingDecimal")) && (!strcmp(mb->fb.name, ""))) runtime_debug = 1; - else if ((!strcmp(cbName(mb->fb.clazz), "java/lang/FloatingDecimal")) - && (!strcmp(mb->fb.name, "developLongDigits"))) + else if ((!strcmp(cbName(mb->fb.clazz), "java/util/Hashtable")) + && (!strcmp(mb->fb.name, "get"))) + runtime_debug = 1; + else if ((!strcmp(cbName(mb->fb.clazz), "java/awt/FlowLayout")) + && (!strcmp(mb->fb.name, "setAlignment"))) + runtime_debug = 1; + else if ((!strcmp(cbName(mb->fb.clazz), "Linpack"))) + runtime_debug = 1; + else if ((!strcmp(cbName(mb->fb.clazz), "StrictfpBenchmark"))) + runtime_debug = 1; + else if ((!strcmp(cbName(mb->fb.clazz), "StrictfpTest"))) runtime_debug = 1; #if 1 else if (!strcmp(mb->fb.name, "main")) diff -aruN shujit-0.4.2/optimize.c shujit/optimize.c --- shujit-0.4.2/optimize.c Thu Jan 1 09:00:00 1970 +++ shujit/optimize.c Tue Apr 25 00:22:06 2000 @@ -0,0 +1,184 @@ +/* + This file is part of shuJIT, + Just In Time compiler for Sun Java Virtual Machine. + + Copyright (C) 2000 SHUDO Kazuyuki + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + $Id$ +*/ + +#include "compiler.h" + + +/* + * Peephole optimization. + */ +#ifdef OPTIMIZE_INTERNAL_CODE +void optimizeInternalCode(CompilerContext *cc) { +#ifdef COMPILE_DEBUG + int compile_debug = cc->compile_debug; +#endif + pcentry *entry; + int opcode, opcode1; + int i; + +#ifdef COMPILE_DEBUG + if (compile_debug) { + struct methodblock *mb = cc->mb; + printf("optIntCode called: %s#%s %s.\n", + cbName(mb->fb.clazz), mb->fb.name, mb->fb.signature); + fflush(stdout); + } +#endif + + for (i = 0; i < pctableLen(cc); i++) { + pcentry *entry1, *entry2, *entry3; +#define GET_1_ENTRY \ + if (!(entry1 = pctableNext(cc, entry))) break;\ + if (pcentryBlockTop(entry1)) break +#define GET_2_ENTRIES \ + GET_1_ENTRY; \ + if (!(entry2 = pctableNext(cc, entry1))) break;\ + if (pcentryBlockTop(entry2)) break +#define GET_3_ENTRIES \ + GET_2_ENTRIES; \ + if (!(entry3 = pctableNext(cc, entry2))) break;\ + if (pcentryBlockTop(entry1)) break + + entry = cc->pctable + i; + + switch (entry->opcode) { + case opc_dst: + /* combine FPU store and load instructions */ + GET_2_ENTRIES; + if ((pcentryState(entry) == 0) && + (entry1->opcode == opc_flush_cache) && (entry2->opcode == opc_dld)) { +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" boff:0x%x(%d)\n", entry->byteoff, entry->byteoff); + printf(" dst,flush_cache,dld found.\n"); + fflush(stdout); + } +#endif + *entry = *entry1; /* copy opc_flush_cache */ + pctableNDelete(cc, i + 1, 2); + } + break; + + case opc_fst: + /* combine FPU store and load instructions */ + GET_2_ENTRIES; + if ((pcentryState(entry) == 0) && + (entry1->opcode == opc_flush_cache) && (entry2->opcode == opc_fld)) { +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" boff:0x%x(%d)\n", entry->byteoff, entry->byteoff); + printf(" fst,flush_cache,fld found.\n"); + fflush(stdout); + } +#endif + *entry = *entry1; /* copy opc_flush_cache */ + pctableNDelete(cc, i + 1, 2); + } + break; + + case opc_iload: + /* load a float value to a FPU register directly */ + GET_2_ENTRIES; + if ((entry1->opcode == opc_flush_cache) && (entry2->opcode == opc_fld)) { +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" boff:0x%x(%d)\n", entry->byteoff, entry->byteoff); + printf(" fload,flush_cache,fld found.\n"); + fflush(stdout); + } +#endif + *entry1 = *entry; + entry1->opcode = opc_fload_fld; + + entry->opcode = opc_flush_cache; + + pctableDelete(cc, i + 2); + } + break; + + case opc_lload: + /* load a double value to a FPU register directly */ + GET_2_ENTRIES; + if ((entry1->opcode == opc_flush_cache) && (entry2->opcode == opc_dld)) { +#ifdef COMPILE_DEBUG + if (compile_debug) { + printf(" boff:0x%x(%d)\n", entry->byteoff, entry->byteoff); + printf(" dload,flush_cache,dld found.\n"); + fflush(stdout); + } +#endif + *entry1 = *entry; + entry1->opcode = opc_dload_dld; + + entry->opcode = opc_flush_cache; + + pctableDelete(cc, i + 2); + } + break; + + case opc_istore: + /* save wasteful `iload' */ + GET_1_ENTRY; + if ((entry1->opcode == opc_iload) && + (entry->operand == entry1->operand)) { +#ifde