From ce829b1c77c051c87c69181789d1d8c88d673bd3 Mon Sep 17 00:00:00 2001 From: JET Date: Wed, 28 Sep 2011 15:08:23 -0600 Subject: [PATCH 001/140] Added VFP emitters (have yet to compile). --- src/arm.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/arm.cpp b/src/arm.cpp index 16241d180c..dd0720ea97 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -21,6 +21,10 @@ using namespace vm; namespace { namespace isa { +// SYSTEM REGISTERS +const int FPSID = 0x0; +const int FPSCR = 0x1; +const int FPEXC = 0x8; // INSTRUCTION OPTIONS enum CONDITION { EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV }; enum SHIFTOP { LSL, LSR, ASR, ROR }; @@ -51,6 +55,14 @@ inline int SWI(int cond, int imm) { return cond<<28 | 0x0f<<24 | (imm&0xffffff); } inline int SWAP(int cond, int B, int Rn, int Rd, int Rm) { return cond<<28 | 1<<24 | B<<22 | Rn<<16 | Rd<<12 | 9<<4 | Rm; } +inline int COOP(int cond, int opcode_1, int CRn, int CRd, int cp_num, int opcode_2, int CRm) +{ return cond<<28 | 0xe<<24 | opcode_1<<20 | CRn<<16 | CRd<<12 | cp_num<<8 | opcode_2<<5 | CRm; } +inline int COXFER(int cond, int P, int U, int N, int W, int L, int Rn, int CRd, int cp_num, int offset) +{ return cond<<28 | 0x6<<25 | P<<24 | U<<23 | N<<22 | W<<21 | L<<20 | Rn<<16 | CRd<<12 | cp_num<<8 | (offset&0xff); } +inline int COREG(int cond, int opcode_1, int L, int CRn, int Rd, int cp_num, int opcode_2, int CRm) +{ return cond<<28 | 0xe<<24 | opcode_1<<21 | L<<20 | CRn<<16 | Rd<<12 | cp_num<<8 | opcode_2<<5 | 1<<4 | CRm; } +inline int COREG2(int cond, int L, int Rn, int Rd, int cp_num, int opcode, int CRm) +{ return cond<<28 | 0xc4<<20 | L<<20 | Rn<<16 | Rd<<12 | cp_num<<8 | opcode<<4 | CRm;} // FIELD CALCULATORS inline int calcU(int imm) { return imm >= 0 ? 1 : 0; } // INSTRUCTIONS @@ -115,6 +127,58 @@ inline int ldmfd(int Rn, int rlist) { return BLOCKXFER(AL, 0, 1, 0, 1, 1, Rn, rl inline int stmfd(int Rn, int rlist) { return BLOCKXFER(AL, 1, 0, 0, 1, 0, Rn, rlist); } inline int swp(int Rd, int Rm, int Rn) { return SWAP(AL, 0, Rn, Rd, Rm); } inline int swpb(int Rd, int Rm, int Rn) { return SWAP(AL, 1, Rn, Rd, Rm); } +// COPROCESSOR INSTRUCTIONS +inline int cdp(int coproc, int opcode_1, int CRd, int CRn, int CRm, int opcode_2) { return COOP(AL, opcode_1, CRn, CRd, coproc, opcode_2, CRm); } +inline int mcr(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 0, CRn, Rd, coproc, opcode_2, CRm); } +inline int mcrr(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 0, Rn, Rd, coproc, opcode, CRm); } +inline int mrc(int coproc, int opcode_1, int Rd, int CRn, int CRm, int opcode_2=0) { return COREG(AL, opcode_1, 1, CRn, Rd, coproc, opcode_2, CRm); } +inline int mrrc(int coproc, int opcode, int Rd, int Rn, int CRm) { return COREG2(AL, 1, Rn, Rd, coproc, opcode, CRm); } +inline int ldc(int coproc, int CRd, int Rn, int offset=0, int W=0) { return COXFER(AL, 1, 1, 0, W, 1, Rn, CRd, coproc, offset); } +inline int ldcl(int coproc, int CRd, int Rn, int offset=0, int W=0) { return COXFER(AL, 1, 1, 1, W, 1, Rn, CRd, coproc, offset); } +inline int stc(int coproc, int CRd, int Rn, int offset=0, int W=0) { return COXFER(AL, 1, 1, 0, W, 0, Rn, CRd, coproc, offset); } +inline int stcl(int coproc, int CRd, int Rn, int offset=0, int W=0) { return COXFER(AL, 1, 1, 1, W, 0, Rn, CRd, coproc, offset); } +// VFP FLOATING-POINT INSTRUCTIONS +inline int fmacs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } +inline int fnmacs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } +inline int fmscs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|1, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } +inline int fnmscs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|1, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } +inline int fmuls(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } +inline int fnmuls(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|2, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } +inline int fadds(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } +inline int fsubs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } +inline int fdivs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|8, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } +inline int fmacd(int Dd, int Dn, int Dm) { return COOP(AL, 0, Dn, Dd, 11, 0, Dm); } +inline int fnmacd(int Dd, int Dn, int Dm) { return COOP(AL, 0, Dn, Dd, 11, 2, Dm); } +inline int fmscd(int Dd, int Dn, int Dm) { return COOP(AL, 1, Dn, Dd, 11, 0, Dm); } +inline int fnmscd(int Dd, int Dn, int Dm) { return COOP(AL, 1, Dn, Dd, 11, 2, Dm); } +inline int fmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 0, Dm); } +inline int fnmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 2, Dm); } +inline int faddd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 0, Dm); } +inline int fsubd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 2, Dm); } +inline int fdivd(int Dd, int Dn, int Dm) { return COOP(AL, 8, Dn, Dd, 11, 0, Dm); } +inline int fldms(int Rn, int Sd, int n) { return COXFER(AL, 0, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, offset); } +inline int fldmd(int Rn, int Dd, int n) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, offset<<1); } +inline int fldmx(int Rn, int Dd, int n) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, offset<<1|1); } +inline int fstms(int Rn, int Sd, int n) { return COXFER(AL, 0, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, offset); } +inline int fstmd(int Rn, int Dd, int n) { return COXFER(AL, 0, 1, 0, 0, 0, Rn, Dd, 11, offset<<1); } +inline int fstmx(int Rn, int Dd, int n) { return COXFER(AL, 0, 1, 0, 0, 0, Rn, Dd, 11, offset<<1|1); } +inline int flds(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, offset); }; +inline int fldd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 1, Rn, Dd, 11, offset); }; +inline int fsts(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, offset); }; +inline int fstd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 0, Rn, Dd, 11, offset); }; +inline int fmsr(int Sn, int Rd) { return mcr(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); } +inline int fmrs(int Rd, int Sn) { return mrc(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); } +inline int fmdlr(int Dn, int Rd) { return mcr(11, 0, Rd, Dn, 0); } +inline int fmrdl(int Rd, int Dn) { return mrc(11, 0, Rd, Dn, 0); } +inline int fmdhr(int Dn, int Rd) { return mcr(11, 1, Rd, Dn, 0); } +inline int fmrdh(int Rd, int Dn) { return mrc(11, 1, Rd, Dn, 0); } +inline int fmxr(int reg, int Rd) { return mcr(10, 7, Rd, reg, 0); } +inline int fmrx(int Rd, int reg) { return mrc(10, 7, Rd, reg, 0); } +inline int fmsrr(int Sm, int Rd, int Rn) { return mcrr(10, 1 | ((Sm&1)<<1), Rd, Rn, Sm>>1); } +inline int fmrrs(int Rd, int Rn, int Sm) { return mrrc(10, 1 | ((Sm&1)<<1), Rd, Rn, Sm>>1); } +inline int fmdrr(int Dm, int Rd, int Rn) { return mcrr(11, 1, Rd, Rn, Dm); } +inline int fmrrd(int Rd, int Rn, int Dm) { return mrrc(11, 1, Rd, Rn, Dm); } +// FLAG SETTERS inline int SETCOND(int ins, int cond) { return ((ins&0x0fffffff) | (cond<<28)); } inline int SETS(int ins) { return ins | 1<<20; } // PSEUDO-INSTRUCTIONS From 5cf21f49c76094f93a81ca77312462fe7bf4ff5a Mon Sep 17 00:00:00 2001 From: JET Date: Wed, 28 Sep 2011 15:38:27 -0600 Subject: [PATCH 002/140] Compiler error fix. --- src/arm.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index 89c8c99198..f79a96bc82 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -156,12 +156,12 @@ inline int fnmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 2, Dm inline int faddd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 0, Dm); } inline int fsubd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 2, Dm); } inline int fdivd(int Dd, int Dn, int Dm) { return COOP(AL, 8, Dn, Dd, 11, 0, Dm); } -inline int fldms(int Rn, int Sd, int n) { return COXFER(AL, 0, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, offset); } -inline int fldmd(int Rn, int Dd, int n) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, offset<<1); } -inline int fldmx(int Rn, int Dd, int n) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, offset<<1|1); } -inline int fstms(int Rn, int Sd, int n) { return COXFER(AL, 0, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, offset); } -inline int fstmd(int Rn, int Dd, int n) { return COXFER(AL, 0, 1, 0, 0, 0, Rn, Dd, 11, offset<<1); } -inline int fstmx(int Rn, int Dd, int n) { return COXFER(AL, 0, 1, 0, 0, 0, Rn, Dd, 11, offset<<1|1); } +inline int fldms(int Rn, int Sd, int count) { return COXFER(AL, 0, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, count); } +inline int fldmd(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, count<<1); } +inline int fldmx(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, count<<1|1); } +inline int fstms(int Rn, int Sd, int count) { return COXFER(AL, 0, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, count); } +inline int fstmd(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 0, Rn, Dd, 11, count<<1); } +inline int fstmx(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 0, Rn, Dd, 11, count<<1|1); } inline int flds(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, offset); }; inline int fldd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 1, Rn, Dd, 11, offset); }; inline int fsts(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, offset); }; From 97bc388f57fef328a73aded164637b628042a177 Mon Sep 17 00:00:00 2001 From: JET Date: Thu, 29 Sep 2011 14:25:31 -0600 Subject: [PATCH 003/140] ARM VFP multiplication testing. --- src/arm.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/arm.cpp b/src/arm.cpp index f79a96bc82..b973ddcacf 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -1002,6 +1002,20 @@ void multiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::R } } +void floatMultiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { + if (size == 8) { + emit(con, fmdrr(0, a->low, a->high)); + emit(con, fmdrr(1, b->low, b->high)); + emit(con, fmuld(0, 0, 1)); + emit(con, fmrrd(t->low, t->high, 0)); + } else { + emit(con, fmsr(0, a->low)); + emit(con, fmsr(1, b->low)); + emit(con, fmuls(0, 0, 1)); + emit(con, fmrs(t->low, 0)); + } +} + int normalize(Context* c, int offset, int index, unsigned scale, bool* preserveIndex, bool* release) @@ -1807,6 +1821,8 @@ populateTables(ArchitectureContext* c) to[index(c, Multiply, R)] = CAST3(multiplyR); + to[index(c, FloatMultiply, R)] = CAST3(floatMultiplyR); + to[index(c, ShiftLeft, R)] = CAST3(shiftLeftR); to[index(c, ShiftLeft, C)] = CAST3(shiftLeftC); @@ -2137,6 +2153,7 @@ class MyArchitecture: public Assembler::Architecture { case Or: case Xor: case Multiply: + case FloatMultiply: *aTypeMask = *bTypeMask = (1 << RegisterOperand); break; @@ -2144,7 +2161,6 @@ class MyArchitecture: public Assembler::Architecture { case Remainder: case FloatAdd: case FloatSubtract: - case FloatMultiply: case FloatDivide: case FloatRemainder: case JumpIfFloatEqual: From fab278f09db4870300ea12dba1fe8df7578299ea Mon Sep 17 00:00:00 2001 From: JET Date: Tue, 6 Dec 2011 09:24:30 -0700 Subject: [PATCH 004/140] More emitters and such; probably not compiling. --- src/arm.cpp | 197 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 165 insertions(+), 32 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index b973ddcacf..e822035bfa 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -148,14 +148,44 @@ inline int fadds(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, S inline int fsubs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|3, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1)|2, Sm>>1); } inline int fdivs(int Sd, int Sn, int Sm) { return COOP(AL, (Sd&1)<<2|8, Sn>>1, Sd>>1, 10, (Sn&1)<<2|(Sm&1), Sm>>1); } inline int fmacd(int Dd, int Dn, int Dm) { return COOP(AL, 0, Dn, Dd, 11, 0, Dm); } -inline int fnmacd(int Dd, int Dn, int Dm) { return COOP(AL, 0, Dn, Dd, 11, 2, Dm); } -inline int fmscd(int Dd, int Dn, int Dm) { return COOP(AL, 1, Dn, Dd, 11, 0, Dm); } -inline int fnmscd(int Dd, int Dn, int Dm) { return COOP(AL, 1, Dn, Dd, 11, 2, Dm); } -inline int fmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 0, Dm); } -inline int fnmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 2, Dm); } -inline int faddd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 0, Dm); } -inline int fsubd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 2, Dm); } -inline int fdivd(int Dd, int Dn, int Dm) { return COOP(AL, 8, Dn, Dd, 11, 0, Dm); } +inline int fnmacd(int Dd, int Dn, int Dm) { return COOP(AL, 0, Dn, Dd, 11, 2, Dm); } +inline int fmscd(int Dd, int Dn, int Dm) { return COOP(AL, 1, Dn, Dd, 11, 0, Dm); } +inline int fnmscd(int Dd, int Dn, int Dm) { return COOP(AL, 1, Dn, Dd, 11, 2, Dm); } +inline int fmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 0, Dm); } +inline int fnmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 2, Dm); } +inline int faddd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 0, Dm); } +inline int fsubd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 2, Dm); } +inline int fdivd(int Dd, int Dn, int Dm) { return COOP(AL, 8, Dn, Dd, 11, 0, Dm); } +inline int fcpys(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 0, Sd, 10, 2|Sm&1, Sm); } +inline int fabss(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 0, Sd, 10, 6|Sm&1, Sm); } +inline int fnegs(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 1, Sd, 10, 2|Sm&1, Sm); } +inline int fsqrts(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 1, Sd, 10, 6|Sm&1, Sm); } +inline int fcmps(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 4, Sd, 10, 2|Sm&1, Sm); } +inline int fcmpes(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 4, Sd, 10, 6|Sm&1, Sm); } +inline int fcmpzs(int Sd) { return COOP(AL, 0xb|Sd&1, 5, Sd, 10, 2|Sm&1, 0); } +inline int fcmpezs(int Sd) { return COOP(AL, 0xb|Sd&1, 5, Sd, 10, 6|Sm&1, 0); } +inline int fcvtds(int Dd, int Sm) { return COOP(AL, 0xb|Sd&1, 7, Dd, 10, 6|Sm&1, Sm); } +inline int fuitos(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 8, Sd, 10, 2|Sm&1, Sm); } +inline int fsitos(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 8, Sd, 10, 6|Sm&1, Sm); } +inline int ftouis(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 0xc, Sd, 10, 2|Sm&1, Sm); } +inline int ftouizs(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 0xc, Sd, 10, 6|Sm&1, Sm); } +inline int ftosis(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 0xd, Sd, 10, 2|Sm&1, Sm); } +inline int ftosizs(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 0xd, Sd, 10, 6|Sm&1, Sm); } +inline int fcpyd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 2, Dm); } +inline int fabsd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 6, Dm); } +inline int fnegd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 2, Dm); } +inline int fsqrtd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 6, Dm); } +inline int fcmpd(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 2, Dm); } +inline int fcmped(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 6, Dm); } +inline int fcmpzd(int Dd) { return COOP(AL, 0xb, 5, Dd, 11, 2, 0); } +inline int fcmpezd(int Dd) { return COOP(AL, 0xb, 5, Dd, 11, 6, 0); } +inline int fcvtsd(int Sd, int Dm) { return COOP(AL, 0xb, 7, Sd, 11, 6, Dm); } +inline int fuitod(int Dd, int Dm) { return COOP(AL, 0xb, 8, Dd, 11, 2, Dm); } +inline int fsitod(int Dd, int Dm) { return COOP(AL, 0xb, 8, Dd, 11, 6, Dm); } +inline int ftouid(int Dd, int Dm) { return COOP(AL, 0xb, 0xc, Dd, 11, 2, Dm); } +inline int ftouizd(int Dd, int Dm) { return COOP(AL, 0xb, 0xc, Dd, 11, 6, Dm); } +inline int ftosid(int Dd, int Dm) { return COOP(AL, 0xb, 0xd, Dd, 11, 2, Dm); } +inline int ftosizd(int Dd, int Dm) { return COOP(AL, 0xb, 0xd, Dd, 11, 6, Dm); } inline int fldms(int Rn, int Sd, int count) { return COXFER(AL, 0, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, count); } inline int fldmd(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, count<<1); } inline int fldmx(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, count<<1|1); } @@ -200,6 +230,10 @@ inline int ble(int offset) { return SETCOND(b(offset), LE); } inline int bge(int offset) { return SETCOND(b(offset), GE); } inline int blo(int offset) { return SETCOND(b(offset), CC); } inline int bhs(int offset) { return SETCOND(b(offset), CS); } +// HARDWARE FLAGS +bool vfpSupported() { + return true; +} } const uint64_t MASK_LO32 = 0xffffffff; @@ -228,6 +262,11 @@ inline int carry16(target_intptr_t v) { return static_cast(v) < 0 ? 1 : inline bool isOfWidth(int64_t i, int size) { return static_cast(i) >> size == 0; } inline bool isOfWidth(int i, int size) { return static_cast(i) >> size == 0; } +const uint64_t GPR32_MASK = 0xffff; +const uint64_t GPR64_MASK = 0xffff0000ffff; +const uint64_t FPR32_MASK = 0xffff00000; +const uint64_t FPR64_MASK = 0xffff0000; + const unsigned FrameHeaderSize = 1; const unsigned StackAlignmentInBytes = 8; @@ -534,6 +573,7 @@ using namespace isa; // shortcut functions inline void emit(Context* con, int code) { con->code.append4(code); } inline int newTemp(Context* con) { return con->client->acquireTemporary(); } +inline int newTemp(Context* con, unsigned mask) { return con->client->acquireTemporary(mask); } inline void freeTemp(Context* con, int r) { con->client->releaseTemporary(r); } inline int64_t getValue(Assembler::Constant* c) { return c->value->value(); } @@ -1002,17 +1042,87 @@ void multiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::R } } +void floatAbsoluteRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { + if (size == 8) { + emit(con, fabsd(b->low, a->low)); + } else { + emit(con, fabss(b->low, a->low)); + } +} + +void floatNegateRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { + if (size == 8) { + emit(con, fnegd(b->low, a->low)); + } else { + emit(con, fnegs(b->low, a->low)); + } +} + +void float2FloatRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { + if (size == 8) { + emit(con, fcvtsd(b->low, a->low)); + } else { + emit(con, fcvtds(b->low, a->low)); + } +} + +void float2IntRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { + int tmp = newTemp(FPR_MASK); + if (size == 8) { // double to int + emit(con, ftosid(tmp, a->low)); + } else { // float to int + emit(con, ftosis(tmp, a->low)); + } // else thunked + emit(con, fmrs(b->low, tmp)); + freeTemp(con, tmp); +} + +void int2FloatRR(Context* con, unsigned UNUSED, Assembler::Register* a, unsigned size, Assembler::Register* b) { + emit(con, fmsr(b->low, a->low)); + if (size == 8) { // int to double + emit(con, fsitod(b->low, b->low)); + } else { // int to float + emit(con, fsitos(b->low, b->low)); + } // else thunked +} + +void floatSqrtRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { + if (size == 8) { + emit(con, fsqrtd(b->low, a->low)); + } else { + emit(con, fsqrts(b->low, a->low)); + } +} + +void floatAddR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { + if (size == 8) { + emit(con, faddd(t->low, a->low, b->low)); + } else { + emit(con, fadds(t->low, a->low, b->low)); + } +} + +void floatSubtractR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { + if (size == 8) { + emit(con, fsubd(t->low, a->low, b->low)); + } else { + emit(con, fsubs(t->low, a->low, b->low)); + } +} + void floatMultiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { if (size == 8) { - emit(con, fmdrr(0, a->low, a->high)); - emit(con, fmdrr(1, b->low, b->high)); - emit(con, fmuld(0, 0, 1)); - emit(con, fmrrd(t->low, t->high, 0)); + emit(con, fmuld(t->low, a->low, b->low)); } else { - emit(con, fmsr(0, a->low)); - emit(con, fmsr(1, b->low)); - emit(con, fmuls(0, 0, 1)); - emit(con, fmrs(t->low, 0)); + emit(con, fmuls(t->low, a->low, b->low)); + } +} + +void floatDivideR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { + if (size == 8) { + emit(con, fdivd(t->low, a->low, b->low)); + } else { + emit(con, fdivs(t->low, a->low, b->low)); } } @@ -1815,13 +1925,23 @@ populateTables(ArchitectureContext* c) bo[index(c, Negate, R, R)] = CAST2(negateRR); + bo[index(c, FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); + bo[index(c, FloatNegate, R, R)] = CAST2(floatNegateRR); + bo[index(c, Float2Float, R, R)] = CAST2(float2FloatRR); + bo[index(c, Float2Int, R, R)] = CAST2(float2IntRR); + bo[index(c, Int2Float, R, R)] = CAST2(int2FloatRR); + bo[index(c, FloatSquareRoot, R)] = CAST2(floatSqrtRR); + to[index(c, Add, R)] = CAST3(addR); to[index(c, Subtract, R)] = CAST3(subR); to[index(c, Multiply, R)] = CAST3(multiplyR); + to[index(c, FloatAdd, R)] = CAST3(floatAddR); + to[index(c, FloatSubtract, R)] = CAST3(floatSubtractR); to[index(c, FloatMultiply, R)] = CAST3(floatMultiplyR); + to[index(c, FloatDivide, R)] = CAST3(floatDivideR); to[index(c, ShiftLeft, R)] = CAST3(shiftLeftR); to[index(c, ShiftLeft, C)] = CAST3(shiftLeftC); @@ -1852,15 +1972,15 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned floatRegisterSize() { - return 0; + return vfpSupported() ? 16 : 0; } virtual uint32_t generalRegisterMask() { - return 0xFFFF; + return GPR_MASK; } virtual uint32_t floatRegisterMask() { - return 0; + return vfpSupported() ? FPR_MASK : 0; } virtual int scratch() { @@ -2062,30 +2182,40 @@ class MyArchitecture: public Assembler::Architecture { virtual void planSource (BinaryOperation op, - unsigned, uint8_t* aTypeMask, uint64_t* aRegisterMask, - unsigned, bool* thunk) + unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, + unsigned bSize, bool* thunk) { - *aTypeMask = ~0; - *aRegisterMask = ~static_cast(0); - - *thunk = false; + *aTypeMask = (1 << RegisterOperand); switch (op) { - case Negate: - *aTypeMask = (1 << RegisterOperand); - break; - case Absolute: case FloatAbsolute: case FloatSquareRoot: case FloatNegate: case Float2Float: + if (vfpSupported()) { + } else { + *thunk = true; + } + break; + case Float2Int: + if (vfpSupported() && bSize == 4) { + } else { + *thunk = true; + } + break; + case Int2Float: - *thunk = true; + if (vfpSupported() && aSize == 4) { + } else { + *thunk = true; + } break; default: + *aRegisterMask = ~static_cast(0); + *thunk = false; break; } } @@ -2153,7 +2283,6 @@ class MyArchitecture: public Assembler::Architecture { case Or: case Xor: case Multiply: - case FloatMultiply: *aTypeMask = *bTypeMask = (1 << RegisterOperand); break; @@ -2161,6 +2290,7 @@ class MyArchitecture: public Assembler::Architecture { case Remainder: case FloatAdd: case FloatSubtract: + case FloatMultiply: case FloatDivide: case FloatRemainder: case JumpIfFloatEqual: @@ -2173,7 +2303,10 @@ class MyArchitecture: public Assembler::Architecture { case JumpIfFloatGreaterOrUnordered: case JumpIfFloatLessOrEqualOrUnordered: case JumpIfFloatGreaterOrEqualOrUnordered: - *thunk = true; + if (vfpSupported()) { + } else { + *thunk = true; + } break; default: From 9c58c7c9369fbdcf1b32b245873fad209bac5591 Mon Sep 17 00:00:00 2001 From: JET Date: Tue, 17 Jan 2012 14:10:51 -0700 Subject: [PATCH 005/140] compiling; all VFP emitters are now correct --- src/arm.cpp | 54 ++++++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index 7d6a3dac91..dd3c61ee1d 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -156,21 +156,21 @@ inline int fnmuld(int Dd, int Dn, int Dm) { return COOP(AL, 2, Dn, Dd, 11, 2, Dm inline int faddd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 0, Dm); } inline int fsubd(int Dd, int Dn, int Dm) { return COOP(AL, 3, Dn, Dd, 11, 2, Dm); } inline int fdivd(int Dd, int Dn, int Dm) { return COOP(AL, 8, Dn, Dd, 11, 0, Dm); } -inline int fcpys(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 0, Sd, 10, 2|Sm&1, Sm); } -inline int fabss(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 0, Sd, 10, 6|Sm&1, Sm); } -inline int fnegs(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 1, Sd, 10, 2|Sm&1, Sm); } -inline int fsqrts(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 1, Sd, 10, 6|Sm&1, Sm); } -inline int fcmps(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 4, Sd, 10, 2|Sm&1, Sm); } -inline int fcmpes(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 4, Sd, 10, 6|Sm&1, Sm); } -inline int fcmpzs(int Sd) { return COOP(AL, 0xb|Sd&1, 5, Sd, 10, 2|Sm&1, 0); } -inline int fcmpezs(int Sd) { return COOP(AL, 0xb|Sd&1, 5, Sd, 10, 6|Sm&1, 0); } -inline int fcvtds(int Dd, int Sm) { return COOP(AL, 0xb|Sd&1, 7, Dd, 10, 6|Sm&1, Sm); } -inline int fuitos(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 8, Sd, 10, 2|Sm&1, Sm); } -inline int fsitos(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 8, Sd, 10, 6|Sm&1, Sm); } -inline int ftouis(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 0xc, Sd, 10, 2|Sm&1, Sm); } -inline int ftouizs(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 0xc, Sd, 10, 6|Sm&1, Sm); } -inline int ftosis(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 0xd, Sd, 10, 2|Sm&1, Sm); } -inline int ftosizs(int Sd, int Sm) { return COOP(AL, 0xb|Sd&1, 0xd, Sd, 10, 6|Sm&1, Sm); } +inline int fcpys(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int fabss(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int fnegs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int fsqrts(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 1, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int fcmps(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 4, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int fcmpes(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 4, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int fcmpzs(int Sd) { return COOP(AL, 0xb|(Sd&1)<<2, 5, Sd>>1, 10, 2, 0); } +inline int fcmpezs(int Sd) { return COOP(AL, 0xb|(Sd&1)<<2, 5, Sd>>1, 10, 6, 0); } +inline int fcvtds(int Dd, int Sm) { return COOP(AL, 0xb, 7, Dd, 10, 6|(Sm&1), Sm>>1); } +inline int fuitos(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 8, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int fsitos(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 8, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int ftouis(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int ftouizs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 10, 6|(Sm&1), Sm>>1); } +inline int ftosis(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 10, 2|(Sm&1), Sm>>1); } +inline int ftosizs(int Sd, int Sm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 10, 6|(Sm&1), Sm>>1); } inline int fcpyd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 2, Dm); } inline int fabsd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 6, Dm); } inline int fnegd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 2, Dm); } @@ -179,13 +179,13 @@ inline int fcmpd(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 2, Dm); } inline int fcmped(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 6, Dm); } inline int fcmpzd(int Dd) { return COOP(AL, 0xb, 5, Dd, 11, 2, 0); } inline int fcmpezd(int Dd) { return COOP(AL, 0xb, 5, Dd, 11, 6, 0); } -inline int fcvtsd(int Sd, int Dm) { return COOP(AL, 0xb, 7, Sd, 11, 6, Dm); } -inline int fuitod(int Dd, int Dm) { return COOP(AL, 0xb, 8, Dd, 11, 2, Dm); } -inline int fsitod(int Dd, int Dm) { return COOP(AL, 0xb, 8, Dd, 11, 6, Dm); } -inline int ftouid(int Dd, int Dm) { return COOP(AL, 0xb, 0xc, Dd, 11, 2, Dm); } -inline int ftouizd(int Dd, int Dm) { return COOP(AL, 0xb, 0xc, Dd, 11, 6, Dm); } -inline int ftosid(int Dd, int Dm) { return COOP(AL, 0xb, 0xd, Dd, 11, 2, Dm); } -inline int ftosizd(int Dd, int Dm) { return COOP(AL, 0xb, 0xd, Dd, 11, 6, Dm); } +inline int fcvtsd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 7, Sd>>1, 11, 6, Dm); } +inline int fuitod(int Dd, int Sm) { return COOP(AL, 0xb, 8, Dd, 11, 2|(Sm&1), Sm>>1); } +inline int fsitod(int Dd, int Sm) { return COOP(AL, 0xb, 8, Dd, 11, 6|(Sm&1), Sm>>1); } +inline int ftouid(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 11, 2, Dm); } +inline int ftouizd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 11, 6, Dm); } +inline int ftosid(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 11, 2, Dm); } +inline int ftosizd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 11, 6, Dm); } inline int fldms(int Rn, int Sd, int count) { return COXFER(AL, 0, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, count); } inline int fldmd(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, count<<1); } inline int fldmx(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, count<<1|1); } @@ -262,10 +262,8 @@ inline int carry16(target_intptr_t v) { return static_cast(v) < 0 ? 1 : inline bool isOfWidth(int64_t i, int size) { return static_cast(i) >> size == 0; } inline bool isOfWidth(int i, int size) { return static_cast(i) >> size == 0; } -const uint64_t GPR32_MASK = 0xffff; -const uint64_t GPR64_MASK = 0xffff0000ffff; -const uint64_t FPR32_MASK = 0xffff00000; -const uint64_t FPR64_MASK = 0xffff0000; +const uint32_t GPR_MASK = 0xffff; +const uint32_t FPR_MASK = 0xffff0000; const unsigned FrameHeaderSize = 1; @@ -1067,7 +1065,7 @@ void float2FloatRR(Context* con, unsigned size, Assembler::Register* a, unsigned } void float2IntRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { - int tmp = newTemp(FPR_MASK); + int tmp = newTemp(con, FPR_MASK); if (size == 8) { // double to int emit(con, ftosid(tmp, a->low)); } else { // float to int @@ -1930,7 +1928,7 @@ populateTables(ArchitectureContext* c) bo[index(c, Float2Float, R, R)] = CAST2(float2FloatRR); bo[index(c, Float2Int, R, R)] = CAST2(float2IntRR); bo[index(c, Int2Float, R, R)] = CAST2(int2FloatRR); - bo[index(c, FloatSquareRoot, R)] = CAST2(floatSqrtRR); + bo[index(c, FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); to[index(c, Add, R)] = CAST3(addR); From 233725e232ff33711c13edb4be68315794dd62b1 Mon Sep 17 00:00:00 2001 From: JET Date: Wed, 18 Jan 2012 12:41:51 -0700 Subject: [PATCH 006/140] All tests passing (again). --- src/arm.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index dd3c61ee1d..eabb131ef7 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, Avian Contributors +/* Copyright (c) 2010-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -232,7 +232,7 @@ inline int blo(int offset) { return SETCOND(b(offset), CC); } inline int bhs(int offset) { return SETCOND(b(offset), CS); } // HARDWARE FLAGS bool vfpSupported() { - return true; + return false; // TODO } } @@ -247,10 +247,10 @@ inline unsigned lo8(int64_t i) { return (unsigned)(i&MASK_LO8); } inline unsigned hi8(int64_t i) { return lo8(i>>8); } inline int ha16(int32_t i) { - return ((i >> 16) + ((i & 0x8000) ? 1 : 0)) & 0xffff; + return ((i >> 16) + ((i & 0x8000) ? 1 : 0)) & 0xffff; } inline int unha16(int32_t high, int32_t low) { - return ((high - ((low & 0x8000) ? 1 : 0)) << 16) | low; + return ((high - ((low & 0x8000) ? 1 : 0)) << 16) | low; } inline bool isInt8(target_intptr_t v) { return v == static_cast(v); } @@ -2183,37 +2183,38 @@ class MyArchitecture: public Assembler::Architecture { unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask, unsigned bSize, bool* thunk) { - *aTypeMask = (1 << RegisterOperand); + *thunk = false; + *aTypeMask = ~0; + *aRegisterMask = ~static_cast(0); switch (op) { + case Negate: + *aTypeMask = (1 << RegisterOperand); + break; + case Absolute: case FloatAbsolute: case FloatSquareRoot: case FloatNegate: case Float2Float: - if (vfpSupported()) { - } else { + if (!vfpSupported()) { *thunk = true; } break; case Float2Int: - if (vfpSupported() && bSize == 4) { - } else { + if (!vfpSupported() || bSize != 4) { *thunk = true; } break; case Int2Float: - if (vfpSupported() && aSize == 4) { - } else { + if (!vfpSupported() || aSize != 4) { *thunk = true; } break; default: - *aRegisterMask = ~static_cast(0); - *thunk = false; break; } } @@ -2301,8 +2302,7 @@ class MyArchitecture: public Assembler::Architecture { case JumpIfFloatGreaterOrUnordered: case JumpIfFloatLessOrEqualOrUnordered: case JumpIfFloatGreaterOrEqualOrUnordered: - if (vfpSupported()) { - } else { + if (!vfpSupported()) { *thunk = true; } break; From 47b91f38eea22558c412849df229a367c1276c82 Mon Sep 17 00:00:00 2001 From: JET Date: Thu, 26 Jan 2012 18:26:29 -0700 Subject: [PATCH 007/140] Additional floating-point support code; passing all tests when vfpSupport() returns false. --- src/arm.cpp | 410 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 264 insertions(+), 146 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index eabb131ef7..a2f628857c 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -234,6 +234,7 @@ inline int bhs(int offset) { return SETCOND(b(offset), CS); } bool vfpSupported() { return false; // TODO } + } const uint64_t MASK_LO32 = 0xffffffff; @@ -262,9 +263,19 @@ inline int carry16(target_intptr_t v) { return static_cast(v) < 0 ? 1 : inline bool isOfWidth(int64_t i, int size) { return static_cast(i) >> size == 0; } inline bool isOfWidth(int i, int size) { return static_cast(i) >> size == 0; } +const int N_GPRS = 16; +const int N_FPRS = 16; const uint32_t GPR_MASK = 0xffff; const uint32_t FPR_MASK = 0xffff0000; +inline bool isFpr(Assembler::Register* reg) { + return reg->low >= N_GPRS; +} + +inline int toFpr(Assembler::Register* reg) { + return reg->low - N_GPRS; +} + const unsigned FrameHeaderSize = 1; const unsigned StackAlignmentInBytes = 8; @@ -570,10 +581,37 @@ using namespace isa; // shortcut functions inline void emit(Context* con, int code) { con->code.append4(code); } -inline int newTemp(Context* con) { return con->client->acquireTemporary(); } -inline int newTemp(Context* con, unsigned mask) { return con->client->acquireTemporary(mask); } -inline void freeTemp(Context* con, int r) { con->client->releaseTemporary(r); } -inline int64_t getValue(Assembler::Constant* c) { return c->value->value(); } + +inline int newTemp(Context* con) { + return con->client->acquireTemporary(); +} + +inline int newTemp(Context* con, unsigned mask) { + return con->client->acquireTemporary(mask); +} + +inline void freeTemp(Context* con, int r) { + con->client->releaseTemporary(r); +} + +inline int64_t getValue(Assembler::Constant* c) { + return c->value->value(); +} + +inline Assembler::Register makeTemp(Context* con) { + Assembler::Register tmp(newTemp(con)); + return tmp; +} + +inline Assembler::Register makeTemp64(Context* con) { + Assembler::Register tmp(newTemp(con), newTemp(con)); + return tmp; +} + +inline void freeTemp(Context* con, const Assembler::Register& tmp) { + if (tmp.low != NoRegister) freeTemp(con, tmp.low); + if (tmp.high != NoRegister) freeTemp(con, tmp.high); +} inline void write4(uint8_t* dst, uint32_t v) @@ -879,46 +917,59 @@ swapRR(Context* c, unsigned aSize, Assembler::Register* a, } void -moveRR(Context* c, unsigned srcSize, Assembler::Register* src, +moveRR(Context* con, unsigned srcSize, Assembler::Register* src, unsigned dstSize, Assembler::Register* dst) { + bool srcIsFpr = isFpr(src); + bool dstIsFpr = isFpr(dst); + if (srcIsFpr || dstIsFpr) { // floating-point register(s) involved + /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> %d <- %d\n", dst->low, src->low); + // FPR to FPR + if (srcIsFpr && dstIsFpr) emit(con, fcpys(toFpr(dst), toFpr(src))); + // FPR to GPR + else if (srcIsFpr) emit(con, fmrs(dst->low, toFpr(src))); + // GPR to FPR + else emit(con, fmsr(toFpr(dst), src->low)); + return; + } + switch (srcSize) { case 1: - emit(c, lsli(dst->low, src->low, 24)); - emit(c, asri(dst->low, dst->low, 24)); + emit(con, lsli(dst->low, src->low, 24)); + emit(con, asri(dst->low, dst->low, 24)); break; - + case 2: - emit(c, lsli(dst->low, src->low, 16)); - emit(c, asri(dst->low, dst->low, 16)); + emit(con, lsli(dst->low, src->low, 16)); + emit(con, asri(dst->low, dst->low, 16)); break; - + case 4: case 8: if (srcSize == 4 and dstSize == 8) { - moveRR(c, 4, src, 4, dst); - emit(c, asri(dst->high, src->low, 31)); + moveRR(con, 4, src, 4, dst); + emit(con, asri(dst->high, src->low, 31)); } else if (srcSize == 8 and dstSize == 8) { Assembler::Register srcHigh(src->high); Assembler::Register dstHigh(dst->high); if (src->high == dst->low) { if (src->low == dst->high) { - swapRR(c, 4, src, 4, dst); + swapRR(con, 4, src, 4, dst); } else { - moveRR(c, 4, &srcHigh, 4, &dstHigh); - moveRR(c, 4, src, 4, dst); + moveRR(con, 4, &srcHigh, 4, &dstHigh); + moveRR(con, 4, src, 4, dst); } } else { - moveRR(c, 4, src, 4, dst); - moveRR(c, 4, &srcHigh, 4, &dstHigh); + moveRR(con, 4, src, 4, dst); + moveRR(con, 4, &srcHigh, 4, &dstHigh); } } else if (src->low != dst->low) { - emit(c, mov(dst->low, src->low)); + emit(con, mov(dst->low, src->low)); } break; - default: abort(c); + default: abort(con); } } @@ -937,26 +988,32 @@ moveZRR(Context* c, unsigned srcSize, Assembler::Register* src, } void -moveCR2(Context* c, unsigned, Assembler::Constant* src, - unsigned dstSize, Assembler::Register* dst, Promise* callOffset) +moveCR2(Context* con, unsigned size, Assembler::Constant* src, + Assembler::Register* dst, Promise* callOffset) { - if (dstSize <= 4) { + if (isFpr(dst)) { // floating-point + Assembler::Register tmp = makeTemp(con); + /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> %d <- 0x%llx\n", tmp.low, getValue(src)); + moveCR2(con, size, src, &tmp, 0); + moveRR(con, size, &tmp, size, dst); + freeTemp(con, tmp); + } else if (size <= 4) { if (src->value->resolved() and isOfWidth(getValue(src), 8)) { - emit(c, movi(dst->low, lo8(getValue(src)))); + emit(con, movi(dst->low, lo8(getValue(src)))); } else { - appendConstantPoolEntry(c, src->value, callOffset); - emit(c, ldri(dst->low, ProgramCounter, 0)); + appendConstantPoolEntry(con, src->value, callOffset); + emit(con, ldri(dst->low, ProgramCounter, 0)); } } else { - abort(c); // todo + abort(con); // todo } } void -moveCR(Context* c, unsigned srcSize, Assembler::Constant* src, - unsigned dstSize, Assembler::Register* dst) +moveCR(Context* con, unsigned size, Assembler::Constant* src, + unsigned, Assembler::Register* dst) { - moveCR2(c, srcSize, src, dstSize, dst, 0); + moveCR2(con, size, src, dst, 0); } void addR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { @@ -1096,7 +1153,8 @@ void floatAddR(Context* con, unsigned size, Assembler::Register* a, Assembler::R if (size == 8) { emit(con, faddd(t->low, a->low, b->low)); } else { - emit(con, fadds(t->low, a->low, b->low)); + fprintf(stderr, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ %d <- %d + %d\n", toFpr(t), toFpr(a), toFpr(b)); + emit(con, fadds(toFpr(t), toFpr(a), toFpr(b))); } } @@ -1175,71 +1233,91 @@ normalize(Context* c, int offset, int index, unsigned scale, } void -store(Context* c, unsigned size, Assembler::Register* src, +store(Context* con, unsigned size, Assembler::Register* src, int base, int offset, int index, unsigned scale, bool preserveIndex) { if (index != NoRegister) { bool release; int normalized = normalize - (c, offset, index, scale, &preserveIndex, &release); + (con, offset, index, scale, &preserveIndex, &release); - switch (size) { - case 1: - emit(c, strb(src->low, base, normalized)); - break; + if (isFpr(src)) { // floating-point store + if (size == 4) { + /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> fpr store base-indexed\n"); + Assembler::Register base_(base), + normalized_(normalized), + absAddr = makeTemp(con); + addR(con, size, &base_, &normalized_, &absAddr); + emit(con, fsts(toFpr(src), absAddr.low)); + freeTemp(con, absAddr); + } + else abort(con); + } else { + switch (size) { + case 1: + emit(con, strb(src->low, base, normalized)); + break; - case 2: - emit(c, strh(src->low, base, normalized)); - break; + case 2: + emit(con, strh(src->low, base, normalized)); + break; - case 4: - emit(c, str(src->low, base, normalized)); - break; + case 4: + emit(con, str(src->low, base, normalized)); + break; - case 8: { - Assembler::Register srcHigh(src->high); - store(c, 4, &srcHigh, base, 0, normalized, 1, preserveIndex); - store(c, 4, src, base, 4, normalized, 1, preserveIndex); - } break; + case 8: { + Assembler::Register srcHigh(src->high); + store(con, 4, &srcHigh, base, 0, normalized, 1, preserveIndex); + store(con, 4, src, base, 4, normalized, 1, preserveIndex); + } break; - default: abort(c); + default: abort(con); + } } - if (release) c->client->releaseTemporary(normalized); + if (release) con->client->releaseTemporary(normalized); } else if (size == 8 or abs(offset) == (abs(offset) & 0xFF) or (size != 2 and abs(offset) == (abs(offset) & 0xFFF))) { - switch (size) { - case 1: - emit(c, strbi(src->low, base, offset)); - break; + if (isFpr(src)) { + /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> fpr store offset -> %d\n", src->low); + if (size == 4) emit(con, fsts(toFpr(src), base, offset)); + else abort(con); + } else { + switch (size) { + case 1: + emit(con, strbi(src->low, base, offset)); + break; - case 2: - emit(c, strhi(src->low, base, offset)); - break; + case 2: + emit(con, strhi(src->low, base, offset)); + break; - case 4: - emit(c, stri(src->low, base, offset)); - break; + case 4: + emit(con, stri(src->low, base, offset)); + break; - case 8: { - Assembler::Register srcHigh(src->high); - store(c, 4, &srcHigh, base, offset, NoRegister, 1, false); - store(c, 4, src, base, offset + 4, NoRegister, 1, false); - } break; + case 8: { + Assembler::Register srcHigh(src->high); + store(con, 4, &srcHigh, base, offset, NoRegister, 1, false); + store(con, 4, src, base, offset + 4, NoRegister, 1, false); + } break; - default: abort(c); + default: abort(con); + } } } else { - Assembler::Register tmp(c->client->acquireTemporary()); + Assembler::Register tmp(con->client->acquireTemporary()); ResolvedPromise offsetPromise(offset); Assembler::Constant offsetConstant(&offsetPromise); - moveCR(c, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, &tmp); + moveCR(con, TargetBytesPerWord, &offsetConstant, + TargetBytesPerWord, &tmp); - store(c, size, src, base, 0, tmp.low, 1, false); + store(con, size, src, base, 0, tmp.low, 1, false); - c->client->releaseTemporary(tmp.low); + con->client->releaseTemporary(tmp.low); } } @@ -1270,98 +1348,124 @@ moveAndUpdateRM(Context* c, unsigned srcSize UNUSED, Assembler::Register* src, } void -load(Context* c, unsigned srcSize, int base, int offset, int index, +load(Context* con, unsigned srcSize, int base, int offset, int index, unsigned scale, unsigned dstSize, Assembler::Register* dst, bool preserveIndex, bool signExtend) { if (index != NoRegister) { bool release; int normalized = normalize - (c, offset, index, scale, &preserveIndex, &release); + (con, offset, index, scale, &preserveIndex, &release); - switch (srcSize) { - case 1: - if (signExtend) { - emit(c, ldrsb(dst->low, base, normalized)); - } else { - emit(c, ldrb(dst->low, base, normalized)); + if (isFpr(dst)) { // floating-point store + if (srcSize == 4) { + /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> fpr load base-indexed\n"); + Assembler::Register base_(base), + normalized_(normalized), + absAddr = makeTemp(con); + addR(con, srcSize, &base_, &normalized_, &absAddr); + emit(con, flds(toFpr(dst), absAddr.low)); + freeTemp(con, absAddr); } - break; + else abort(con); + } else { + switch (srcSize) { + case 1: + if (signExtend) { + emit(con, ldrsb(dst->low, base, normalized)); + } else { + emit(con, ldrb(dst->low, base, normalized)); + } + break; - case 2: - if (signExtend) { - emit(c, ldrsh(dst->low, base, normalized)); - } else { - emit(c, ldrh(dst->low, base, normalized)); + case 2: + if (signExtend) { + emit(con, ldrsh(dst->low, base, normalized)); + } else { + emit(con, ldrh(dst->low, base, normalized)); + } + break; + + case 4: + case 8: { + if (srcSize == 4 and dstSize == 8) { + load(con, 4, base, 0, normalized, 1, 4, dst, preserveIndex, + false); + moveRR(con, 4, dst, 8, dst); + } else if (srcSize == 8 and dstSize == 8) { + Assembler::Register dstHigh(dst->high); + load(con, 4, base, 0, normalized, 1, 4, &dstHigh, + preserveIndex, false); + load(con, 4, base, 4, normalized, 1, 4, dst, preserveIndex, + false); + } else { + emit(con, ldr(dst->low, base, normalized)); + } + } break; + + default: abort(con); } - break; - - case 4: - case 8: { - if (srcSize == 4 and dstSize == 8) { - load(c, 4, base, 0, normalized, 1, 4, dst, preserveIndex, false); - moveRR(c, 4, dst, 8, dst); - } else if (srcSize == 8 and dstSize == 8) { - Assembler::Register dstHigh(dst->high); - load(c, 4, base, 0, normalized, 1, 4, &dstHigh, preserveIndex, false); - load(c, 4, base, 4, normalized, 1, 4, dst, preserveIndex, false); - } else { - emit(c, ldr(dst->low, base, normalized)); - } - } break; - - default: abort(c); } - if (release) c->client->releaseTemporary(normalized); + if (release) con->client->releaseTemporary(normalized); } else if ((srcSize == 8 and dstSize == 8) or abs(offset) == (abs(offset) & 0xFF) or (srcSize != 2 and (srcSize != 1 or not signExtend) and abs(offset) == (abs(offset) & 0xFFF))) { - switch (srcSize) { - case 1: - if (signExtend) { - emit(c, ldrsbi(dst->low, base, offset)); - } else { - emit(c, ldrbi(dst->low, base, offset)); + if (isFpr(dst)) { + /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> fpr load offset <- %d\n", dst->low); + if (srcSize == 4) emit(con, flds(toFpr(dst), base, offset)); + else abort(con); + } else { + switch (srcSize) { + case 1: + if (signExtend) { + emit(con, ldrsbi(dst->low, base, offset)); + } else { + emit(con, ldrbi(dst->low, base, offset)); + } + break; + + case 2: + if (signExtend) { + emit(con, ldrshi(dst->low, base, offset)); + } else { + emit(con, ldrhi(dst->low, base, offset)); + } + break; + + case 4: + emit(con, ldri(dst->low, base, offset)); + break; + + case 8: { + if (dstSize == 8) { + Assembler::Register dstHigh(dst->high); + load(con, 4, base, offset, NoRegister, 1, 4, &dstHigh, false, + false); + load(con, 4, base, offset + 4, NoRegister, 1, 4, dst, false, + false); + } else { + emit(con, ldri(dst->low, base, offset)); + } + } break; + + default: abort(con); } - break; - - case 2: - if (signExtend) { - emit(c, ldrshi(dst->low, base, offset)); - } else { - emit(c, ldrhi(dst->low, base, offset)); - } - break; - - case 4: - emit(c, ldri(dst->low, base, offset)); - break; - - case 8: { - if (dstSize == 8) { - Assembler::Register dstHigh(dst->high); - load(c, 4, base, offset, NoRegister, 1, 4, &dstHigh, false, false); - load(c, 4, base, offset + 4, NoRegister, 1, 4, dst, false, false); - } else { - emit(c, ldri(dst->low, base, offset)); - } - } break; - - default: abort(c); } } else { - Assembler::Register tmp(c->client->acquireTemporary()); + Assembler::Register tmp(con->client->acquireTemporary()); ResolvedPromise offsetPromise(offset); Assembler::Constant offsetConstant(&offsetPromise); - moveCR(c, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, &tmp); + moveCR(con, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, + &tmp); - load(c, srcSize, base, 0, tmp.low, 1, dstSize, dst, false, signExtend); + load(con, srcSize, base, 0, tmp.low, 1, dstSize, dst, false, + signExtend); - c->client->releaseTemporary(tmp.low); + con->client->releaseTemporary(tmp.low); } } @@ -1773,7 +1877,7 @@ longCallC(Context* c, unsigned size UNUSED, Assembler::Constant* target) assert(c, size == TargetBytesPerWord); Assembler::Register tmp(4); - moveCR2(c, TargetBytesPerWord, target, TargetBytesPerWord, &tmp, offset(c)); + moveCR2(c, TargetBytesPerWord, target, &tmp, offset(c)); callR(c, TargetBytesPerWord, &tmp); } @@ -1783,7 +1887,7 @@ longJumpC(Context* c, unsigned size UNUSED, Assembler::Constant* target) assert(c, size == TargetBytesPerWord); Assembler::Register tmp(4); // a non-arg reg that we don't mind clobbering - moveCR2(c, TargetBytesPerWord, target, TargetBytesPerWord, &tmp, offset(c)); + moveCR2(c, TargetBytesPerWord, target, &tmp, offset(c)); jumpR(c, TargetBytesPerWord, &tmp); } @@ -1970,7 +2074,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned floatRegisterSize() { - return vfpSupported() ? 16 : 0; + return vfpSupported() ? 4 : 0; } virtual uint32_t generalRegisterMask() { @@ -2197,19 +2301,31 @@ class MyArchitecture: public Assembler::Architecture { case FloatSquareRoot: case FloatNegate: case Float2Float: - if (!vfpSupported()) { + if (vfpSupported()) { + *aTypeMask = (1 << RegisterOperand); + *aRegisterMask = FPR_MASK; + *thunk = true; + } else { *thunk = true; } break; case Float2Int: - if (!vfpSupported() || bSize != 4) { + if (vfpSupported() && bSize == 4 && aSize == 4) { + *aTypeMask = (1 << RegisterOperand); + *aRegisterMask = FPR_MASK; + *thunk = true; + } else { *thunk = true; } break; case Int2Float: - if (!vfpSupported() || aSize != 4) { + if (vfpSupported() && aSize == 4 && bSize == 4) { + *aTypeMask = (1 << RegisterOperand); + *aRegisterMask = FPR_MASK; + *thunk = true; + } else { *thunk = true; } break; @@ -2287,6 +2403,9 @@ class MyArchitecture: public Assembler::Architecture { case Divide: case Remainder: + *thunk = true; + break; + case FloatAdd: case FloatSubtract: case FloatMultiply: @@ -2302,9 +2421,8 @@ class MyArchitecture: public Assembler::Architecture { case JumpIfFloatGreaterOrUnordered: case JumpIfFloatLessOrEqualOrUnordered: case JumpIfFloatGreaterOrEqualOrUnordered: - if (!vfpSupported()) { - *thunk = true; - } + if (vfpSupported()) *thunk = true; + else *thunk = true; break; default: From bc5661d6f387675b40b4805ca9e7be37df20a0ce Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 18 Feb 2012 15:17:10 -0700 Subject: [PATCH 008/140] start work on OpenJDK 7 class library port --- .../lang/ReflectiveOperationException.java | 13 ++ openjdk-src.mk | 19 +- src/classpath-openjdk.cpp | 209 +++++++++--------- src/types.def | 2 + 4 files changed, 139 insertions(+), 104 deletions(-) create mode 100644 classpath/java/lang/ReflectiveOperationException.java diff --git a/classpath/java/lang/ReflectiveOperationException.java b/classpath/java/lang/ReflectiveOperationException.java new file mode 100644 index 0000000000..e3c8c0872f --- /dev/null +++ b/classpath/java/lang/ReflectiveOperationException.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +public class ReflectiveOperationException extends Exception { } diff --git a/openjdk-src.mk b/openjdk-src.mk index 28166a9542..a2dd051cce 100644 --- a/openjdk-src.mk +++ b/openjdk-src.mk @@ -45,7 +45,6 @@ openjdk-sources = \ $(openjdk-src)/share/native/java/util/zip/CRC32.c \ $(openjdk-src)/share/native/java/util/zip/Deflater.c \ $(openjdk-src)/share/native/java/util/zip/Inflater.c \ - $(openjdk-src)/share/native/java/util/zip/ZipEntry.c \ $(openjdk-src)/share/native/java/util/zip/ZipFile.c \ $(openjdk-src)/share/native/java/util/zip/zip_util.c \ $(openjdk-src)/share/native/sun/management/VMManagementImpl.c \ @@ -76,6 +75,7 @@ openjdk-headers-classes = \ java.lang.Double \ java.lang.Float \ java.lang.Integer \ + java.lang.Long \ java.lang.Object \ java.lang.Package \ java.lang.Runtime \ @@ -124,7 +124,7 @@ openjdk-headers-classes = \ sun.net.spi.DefaultProxySelector \ sun.nio.ch.FileKey \ sun.nio.ch.FileChannelImpl \ - sun.nio.ch.FileDispatcher \ + sun.nio.ch.FileDispatcherImpl \ sun.nio.ch.DatagramChannelImpl \ sun.nio.ch.DatagramDispatcher \ sun.nio.ch.IOStatus \ @@ -235,6 +235,10 @@ ifeq ($(platform),windows) else openjdk-sources += \ $(openjdk-src)/solaris/native/common/jdk_util_md.c \ + $(openjdk-src)/solaris/native/common/jni_util_md.c \ + $(openjdk-src)/solaris/native/common/deps/syscalls_fp.c \ + $(openjdk-src)/solaris/native/common/deps/gconf2/gconf_fp.c \ + $(openjdk-src)/solaris/native/common/deps/glib2/gio_fp.c \ $(openjdk-src)/solaris/native/java/io/canonicalize_md.c \ $(openjdk-src)/solaris/native/java/io/Console_md.c \ $(openjdk-src)/solaris/native/java/io/FileDescriptor_md.c \ @@ -265,7 +269,7 @@ else $(openjdk-src)/solaris/native/sun/nio/ch/DatagramChannelImpl.c \ $(openjdk-src)/solaris/native/sun/nio/ch/DatagramDispatcher.c \ $(openjdk-src)/solaris/native/sun/nio/ch/FileChannelImpl.c \ - $(openjdk-src)/solaris/native/sun/nio/ch/FileDispatcher.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/FileDispatcherImpl.c \ $(openjdk-src)/solaris/native/sun/nio/ch/FileKey.c \ $(openjdk-src)/solaris/native/sun/nio/ch/IOUtil.c \ $(openjdk-src)/solaris/native/sun/nio/ch/Net.c \ @@ -276,6 +280,7 @@ else $(openjdk-src)/solaris/native/sun/nio/ch/PollArrayWrapper.c \ $(openjdk-src)/solaris/native/sun/nio/ch/InheritedChannel.c \ $(openjdk-src)/solaris/native/sun/nio/ch/NativeThread.c \ + $(openjdk-src)/solaris/native/sun/nio/fs/UnixNativeDispatcher.c \ ifeq ($(platform),linux) openjdk-sources += \ @@ -287,6 +292,7 @@ else java.io.UnixFileSystem \ sun.nio.ch.InheritedChannel \ sun.nio.ch.EPollArrayWrapper \ + sun.nio.fs.UnixNativeDispatcher \ openjdk-cflags += "-I$(openjdk-src)/solaris/javavm/export" \ "-I$(openjdk-src)/solaris/native/common" \ @@ -297,7 +303,12 @@ else "-I$(openjdk-src)/solaris/native/sun/management" \ "-I$(openjdk-src)/solaris/native/sun/nio/ch" \ "-I$(openjdk-src)/solaris/javavm/include" \ - "-I$(openjdk-src)/solaris/hpi/include" + "-I$(openjdk-src)/solaris/hpi/include" \ + "-I$(openjdk-src)/solaris/native/common/deps" \ + "-I$(openjdk-src)/solaris/native/common/deps/glib2" \ + "-I$(openjdk-src)/solaris/native/common/deps/gconf2" \ + $(shell pkg-config --cflags glib-2.0) \ + $(shell pkg-config --cflags gconf-2.0) endif openjdk-local-sources = \ diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index c2b8471dde..a7f8539e79 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -551,31 +551,12 @@ class MyClasspath : public Classpath { expect(t, loadLibrary(t, libraryPath, "java", true, true)); #endif // not AVIAN_OPENJDK_SRC - object constructor = resolveMethod - (t, type(t, Machine::ClassLoaderType), "", - "(Ljava/lang/ClassLoader;)V"); + object assertionLock = resolveField + (t, type(t, Machine::ClassLoaderType), "assertionLock", + "Ljava/lang/Object;"); - PROTECT(t, constructor); - - t->m->processor->invoke(t, constructor, root(t, Machine::BootLoader), 0); - - t->m->processor->invoke - (t, constructor, root(t, Machine::AppLoader), - root(t, Machine::BootLoader)); - - object scl = resolveField - (t, type(t, Machine::ClassLoaderType), "scl", "Ljava/lang/ClassLoader;"); - - PROTECT(t, scl); - - object sclSet = resolveField - (t, type(t, Machine::ClassLoaderType), "sclSet", "Z"); - - set(t, classStaticTable(t, type(t, Machine::ClassLoaderType)), - fieldOffset(t, scl), root(t, Machine::AppLoader)); - - cast(classStaticTable(t, type(t, Machine::ClassLoaderType)), - fieldOffset(t, sclSet)) = true; + set(t, root(t, Machine::BootLoader), fieldOffset(t, assertionLock), + root(t, Machine::BootLoader)); t->m->processor->invoke (t, root(t, Machine::BootLoader), "java/lang/System", @@ -1318,15 +1299,17 @@ getZipFileEntry(Thread* t, object method, uintptr_t* arguments) ZipFile* file = reinterpret_cast(peer); if (file->region) { - THREAD_RUNTIME_ARRAY(t, char, p, stringLength(t, path) + 2); - stringChars(t, path, RUNTIME_ARRAY_BODY(p)); + THREAD_RUNTIME_ARRAY(t, char, p, byteArrayLength(t, path) + 2); + memcpy(RUNTIME_ARRAY_BODY(p), &byteArrayBody(t, path, 0), + byteArrayLength(t, path)); + RUNTIME_ARRAY_BODY(p)[byteArrayLength(t, path)] = 0; replace('\\', '/', RUNTIME_ARRAY_BODY(p)); if (addSlash) { - RUNTIME_ARRAY_BODY(p)[stringLength(t, path)] = '/'; - RUNTIME_ARRAY_BODY(p)[stringLength(t, path) + 1] = 0; + RUNTIME_ARRAY_BODY(p)[byteArrayLength(t, path)] = '/'; + RUNTIME_ARRAY_BODY(p)[byteArrayLength(t, path) + 1] = 0; } - return reinterpret_cast(find(file, p, stringLength(t, path))); + return reinterpret_cast(find(file, p, byteArrayLength(t, path))); } else { int64_t entry = longValue (t, t->m->processor->invoke @@ -1340,6 +1323,43 @@ getZipFileEntry(Thread* t, object method, uintptr_t* arguments) } } +int64_t JNICALL +getZipFileEntryBytes(Thread* t, object method, uintptr_t* arguments) +{ + int64_t peer; memcpy(&peer, arguments, 8); + int type = arguments[2]; + + ZipFile::Entry* entry = reinterpret_cast(peer); + if (entry->start) { + switch (type) { + case 0: { // name + unsigned nameLength = fileNameLength(entry->start); + object array = makeByteArray(t, nameLength + 1); + memcpy(&byteArrayBody(t, array, 0), fileName(entry->start), nameLength); + byteArrayBody(t, array, nameLength) = 0; + return reinterpret_cast(array); + } break; + + case 1: { // extra + return 0; + } break; + + case 2: { // comment + return 0; + } break; + + default: abort(t); + } + return compressedSize(entry->start); + } else { + return reinterpret_cast + (t->m->processor->invoke + (t, nativeInterceptOriginal + (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), + 0, entry->entry, type)); + } +} + int64_t JNICALL getNextZipFileEntry(Thread* t, object method, uintptr_t* arguments) { @@ -1703,6 +1723,11 @@ intercept(Thread* t, object c, const char* name, const char* spec, object runtimeData = getMethodRuntimeData(t, m); set(t, runtimeData, MethodRuntimeDataNative, native); + } else { + fprintf(stderr, "unable to find %s%s in %s\n", + name, spec, &byteArrayBody(t, className(t, c), 0)); + + abort(t); } } @@ -1770,60 +1795,6 @@ interceptFileOperations(Thread* t) } } - { object zipEntryClass = resolveClass - (t, root(t, Machine::BootLoader), "java/util/zip/ZipEntry", false); - - if (zipEntryClass) { - PROTECT(t, zipEntryClass); - - object zipEntryNameField = findFieldInClass2 - (t, zipEntryClass, "name", "Ljava/lang/String;"); - - if (zipEntryNameField) { - cp->zipEntryNameField = fieldOffset(t, zipEntryNameField); - - object zipEntryTimeField = findFieldInClass2 - (t, zipEntryClass, "time", "J"); - - if (zipEntryTimeField) { - cp->zipEntryTimeField = fieldOffset(t, zipEntryTimeField); - - object zipEntryCrcField = findFieldInClass2 - (t, zipEntryClass, "crc", "J"); - - if (zipEntryCrcField) { - cp->zipEntryCrcField = fieldOffset(t, zipEntryCrcField); - - object zipEntrySizeField = findFieldInClass2 - (t, zipEntryClass, "size", "J"); - - if (zipEntrySizeField) { - cp->zipEntrySizeField = fieldOffset(t, zipEntrySizeField); - - object zipEntryCsizeField = findFieldInClass2 - (t, zipEntryClass, "csize", "J"); - - if (zipEntryCsizeField) { - cp->zipEntryCsizeField = fieldOffset(t, zipEntryCsizeField); - - object zipEntryMethodField = findFieldInClass2 - (t, zipEntryClass, "method", "I"); - - if (zipEntryMethodField) { - cp->zipEntryMethodField = fieldOffset - (t, zipEntryMethodField); - - intercept(t, zipEntryClass, "initFields", "(J)V", - voidPointer(initializeZipEntryFields)); - } - } - } - } - } - } - } - } - { object zipFileClass = resolveClass (t, root(t, Machine::BootLoader), "java/util/zip/ZipFile", false); @@ -1836,19 +1807,22 @@ interceptFileOperations(Thread* t) if (zipFileJzfileField) { cp->zipFileJzfileField = fieldOffset(t, zipFileJzfileField); - intercept(t, zipFileClass, "open", "(Ljava/lang/String;IJ)J", + intercept(t, zipFileClass, "open", "(Ljava/lang/String;IJZ)J", voidPointer(openZipFile)); intercept(t, zipFileClass, "getTotal", "(J)I", voidPointer(getZipFileEntryCount)); - intercept(t, zipFileClass, "getEntry", "(JLjava/lang/String;Z)J", + intercept(t, zipFileClass, "getEntry", "(J[BZ)J", voidPointer(getZipFileEntry)); + intercept(t, zipFileClass, "getEntryBytes", "(JI)[B", + voidPointer(getZipFileEntryBytes)); + intercept(t, zipFileClass, "getNextEntry", "(JI)J", voidPointer(getNextZipFileEntry)); - intercept(t, zipFileClass, "getMethod", "(J)I", + intercept(t, zipFileClass, "getEntryMethod", "(J)I", voidPointer(getZipFileEntryMethod)); intercept(t, zipFileClass, "freeEntry", "(JJ)V", @@ -1857,10 +1831,10 @@ interceptFileOperations(Thread* t) intercept(t, zipFileClass, "read", "(JJJ[BII)I", voidPointer(readZipFileEntry)); - intercept(t, zipFileClass, "getCSize", "(J)J", + intercept(t, zipFileClass, "getEntryCSize", "(J)J", voidPointer(getZipFileEntryCompressedSize)); - intercept(t, zipFileClass, "getSize", "(J)J", + intercept(t, zipFileClass, "getEntrySize", "(J)J", voidPointer(getZipFileEntryUncompressedSize)); intercept(t, zipFileClass, "getZipMessage", "(J)Ljava/lang/String;", @@ -2560,6 +2534,13 @@ Avian_sun_misc_Unsafe_putObjectVolatile storeLoadMemoryBarrier(); } +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putOrderedObject +(Thread* t, object method, uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putObjectVolatile(t, method, arguments); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_compareAndSwapInt (Thread*, object, uintptr_t* arguments) @@ -2782,6 +2763,32 @@ Avian_sun_misc_Unsafe_park monitorRelease(t, local::interruptLock(t, t->javaThread)); } +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_copyMemory +(Thread* t, object, uintptr_t* arguments) +{ + object srcBase = reinterpret_cast(arguments[1]); + int64_t srcOffset; memcpy(&srcOffset, arguments + 2, 8); + object dstBase = reinterpret_cast(arguments[4]); + int64_t dstOffset; memcpy(&dstOffset, arguments + 5, 8); + int64_t count; memcpy(&count, arguments + 7, 8); + + PROTECT(t, srcBase); + PROTECT(t, dstBase); + + ACQUIRE(t, t->m->referenceLock); + + void* src = srcBase + ? &cast(srcBase, srcOffset) + : reinterpret_cast(srcOffset); + + void* dst = dstBase + ? &cast(dstBase, dstOffset) + : reinterpret_cast(dstOffset); + + memcpy(dst, src, count); +} + namespace { namespace local { @@ -3153,7 +3160,7 @@ jvmFillInStackTrace(Thread* t, uintptr_t* arguments) { jobject throwable = reinterpret_cast(arguments[0]); - object trace = getTrace(t, 1); + object trace = getTrace(t, 2); set(t, *throwable, ThrowableTrace, trace); return 1; @@ -3834,10 +3841,9 @@ EXPORT(JVM_FindClassFromClassLoader)(Thread* t, const char* name, } extern "C" JNIEXPORT jclass JNICALL -EXPORT(JVM_FindClassFromBootLoader)(Thread* t, const char* name, - jboolean throwError) +EXPORT(JVM_FindClassFromBootLoader)(Thread* t, const char* name) { - return EXPORT(JVM_FindClassFromClassLoader)(t, name, false, 0, throwError); + return EXPORT(JVM_FindClassFromClassLoader)(t, name, false, 0, false); } extern "C" JNIEXPORT jclass JNICALL @@ -4265,9 +4271,9 @@ jvmGetClassDeclaredMethods(Thread* t, uintptr_t* arguments) } object method = makeJmethod - (t, true, *c, i, name, returnType, parameterTypes, exceptionTypes, + (t, true, 0, *c, i, name, returnType, parameterTypes, exceptionTypes, methodFlags(t, vmMethod), signature, 0, annotationTable, 0, - annotationDefault, 0, 0, 0, 0, 0); + annotationDefault, 0, 0, 0); assert(t, ai < objectArrayLength(t, array)); @@ -4354,8 +4360,8 @@ jvmGetClassDeclaredFields(Thread* t, uintptr_t* arguments) } object field = makeJfield - (t, true, *c, i, name, type, fieldFlags - (t, vmField), signature, 0, annotationTable, 0, 0, 0, 0, 0, 0); + (t, true, 0, *c, i, name, type, fieldFlags + (t, vmField), signature, 0, annotationTable, 0, 0, 0, 0); assert(t, ai < objectArrayLength(t, array)); @@ -4445,8 +4451,8 @@ jvmGetClassDeclaredConstructors(Thread* t, uintptr_t* arguments) } object method = makeJconstructor - (t, true, *c, i, parameterTypes, exceptionTypes, methodFlags - (t, vmMethod), signature, 0, annotationTable, 0, 0, 0, 0, 0); + (t, true, 0, *c, i, parameterTypes, exceptionTypes, methodFlags + (t, vmMethod), signature, 0, annotationTable, 0, 0, 0, 0); assert(t, ai < objectArrayLength(t, array)); @@ -5298,8 +5304,11 @@ extern "C" JNIEXPORT jobjectArray JNICALL EXPORT(JVM_GetThreadStateNames)(JNIEnv*, jint, jintArray) { abort(); } extern "C" JNIEXPORT void JNICALL -EXPORT(JVM_GetVersionInfo)(JNIEnv*, local::jvm_version_info*, size_t) -{ abort(); } +EXPORT(JVM_GetVersionInfo)(JNIEnv*, local::jvm_version_info* info, size_t size) +{ + memset(info, 0, size); + info->jvm_version = 0x01070000; +} extern "C" JNIEXPORT jboolean JNICALL EXPORT(JVM_CX8Field)(JNIEnv*, jobject*, jfieldID*, jlong, jlong) diff --git a/src/types.def b/src/types.def index c95ed03a0a..8bac2a7bce 100644 --- a/src/types.def +++ b/src/types.def @@ -219,6 +219,8 @@ (type negativeArraySizeException java/lang/NegativeArraySizeException) +(type reflectiveOperationException java/lang/ReflectiveOperationException) + (type classCastException java/lang/ClassCastException) (type classNotFoundException java/lang/ClassNotFoundException) From 3111f0743090e2094afe94d362c7583badd6a288 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 20 Feb 2012 17:23:18 -0700 Subject: [PATCH 009/140] add "throws IOException" to java.io.File.createTempFile --- classpath/java/io/File.java | 9 +++++++-- test/Files.java | 6 ++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index bfae0da9b6..a77502c041 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -35,11 +35,16 @@ public class File implements Serializable { this(parent.getPath() + FileSeparator + child); } - public static File createTempFile(String prefix, String suffix) { + public static File createTempFile(String prefix, String suffix) + throws IOException + { return createTempFile(prefix, suffix, null); } - public static File createTempFile(String prefix, String suffix, File directory) { + public static File createTempFile(String prefix, String suffix, + File directory) + throws IOException + { if(directory == null) { directory = new File(System.getProperty("java.io.tmpdir")); } diff --git a/test/Files.java b/test/Files.java index 7661e79018..f3d1988f31 100644 --- a/test/Files.java +++ b/test/Files.java @@ -21,7 +21,9 @@ public class Files { } - private static void setExecutableTestWithPermissions(boolean executable) { + private static void setExecutableTestWithPermissions(boolean executable) + throws Exception + { File file = File.createTempFile("avian.", null); file.setExecutable(executable); if (executable) { @@ -33,7 +35,7 @@ public class Files { } } - public static void main(String[] args) { + public static void main(String[] args) throws Exception { isAbsoluteTest(true); isAbsoluteTest(false); setExecutableTestWithPermissions(true); From d94fd952e99901df7e96f70b76168170c714cf92 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 20 Feb 2012 17:38:41 -0700 Subject: [PATCH 010/140] fix some OpenJDK update regressions --- src/classpath-openjdk.cpp | 70 ++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index a7f8539e79..055b2f1350 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -551,12 +551,61 @@ class MyClasspath : public Classpath { expect(t, loadLibrary(t, libraryPath, "java", true, true)); #endif // not AVIAN_OPENJDK_SRC - object assertionLock = resolveField - (t, type(t, Machine::ClassLoaderType), "assertionLock", - "Ljava/lang/Object;"); + { object class_ = resolveClass + (t, root(t, Machine::BootLoader), "java/util/Properties", true, + Machine::NoClassDefFoundErrorType); - set(t, root(t, Machine::BootLoader), fieldOffset(t, assertionLock), - root(t, Machine::BootLoader)); + PROTECT(t, class_); + + object instance = makeNew(t, class_); + + PROTECT(t, instance); + + object constructor = resolveMethod(t, class_, "", "()V"); + + t->m->processor->invoke(t, constructor, instance); + + t->m->processor->invoke + (t, root(t, Machine::BootLoader), "java/lang/System", + "setProperties", "(Ljava/util/Properties;)V", 0, instance); + } + + { object constructor = resolveMethod + (t, type(t, Machine::ClassLoaderType), "", + "(Ljava/lang/ClassLoader;)V"); + + PROTECT(t, constructor); + + t->m->processor->invoke(t, constructor, root(t, Machine::BootLoader), 0); + + t->m->processor->invoke + (t, constructor, root(t, Machine::AppLoader), + root(t, Machine::BootLoader)); + } + + { object assertionLock = resolveField + (t, type(t, Machine::ClassLoaderType), "assertionLock", + "Ljava/lang/Object;"); + + set(t, root(t, Machine::BootLoader), fieldOffset(t, assertionLock), + root(t, Machine::BootLoader)); + } + + { object scl = resolveField + (t, type(t, Machine::ClassLoaderType), "scl", + "Ljava/lang/ClassLoader;"); + + PROTECT(t, scl); + + object sclSet = resolveField + (t, type(t, Machine::ClassLoaderType), "sclSet", "Z"); + + set(t, classStaticTable(t, type(t, Machine::ClassLoaderType)), + fieldOffset(t, scl), root(t, Machine::AppLoader)); + + cast(classStaticTable(t, type(t, Machine::ClassLoaderType)), + fieldOffset(t, sclSet)) = true; + } t->m->processor->invoke (t, root(t, Machine::BootLoader), "java/lang/System", @@ -2622,11 +2671,14 @@ extern "C" JNIEXPORT void JNICALL Avian_sun_misc_Unsafe_setMemory (Thread*, object, uintptr_t* arguments) { - int64_t p; memcpy(&p, arguments + 1, 8); - int64_t count; memcpy(&count, arguments + 3, 8); - int8_t v = arguments[5]; + object base = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + int64_t count; memcpy(&count, arguments + 4, 8); + int8_t v = arguments[6]; - memset(reinterpret_cast(p), v, count); + memset(base + ? &cast(base, offset) + : reinterpret_cast(offset), v, count); } extern "C" JNIEXPORT void JNICALL From 747f22115f872fb03cb9242684ba99a99da07b84 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 21 Feb 2012 17:32:20 -0700 Subject: [PATCH 011/140] handle JMM_THREAD_ALLOCATED_MEMORY in JMX GetBoolAttribute implementation --- src/classpath-openjdk.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 055b2f1350..ea7012e921 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -5271,9 +5271,11 @@ jboolean JNICALL GetBoolAttribute(Thread* t, jmmBoolAttribute attribute) { const unsigned JMM_THREAD_CPU_TIME = 24; + const unsigned JMM_THREAD_ALLOCATED_MEMORY = 25; switch (attribute) { case JMM_THREAD_CPU_TIME: + case JMM_THREAD_ALLOCATED_MEMORY: return false; default: From c3b72a3dd544b9362bbed58de0d0207b52ddaeca Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 29 Feb 2012 11:46:50 -0700 Subject: [PATCH 012/140] set sun.boot.class.path property in jvmInitProperties --- src/classpath-openjdk.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index ea7012e921..e1fde3ba5d 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -3015,22 +3015,22 @@ jvmInitProperties(Thread* t, uintptr_t* arguments) GetCurrentDirectory(MAX_PATH, buffer); local::setProperty(t, method, *properties, "user.dir", buffer); -#else +#else // not PLATFORM_WINDOWS local::setProperty(t, method, *properties, "line.separator", "\n"); local::setProperty(t, method, *properties, "file.separator", "/"); local::setProperty(t, method, *properties, "path.separator", ":"); # ifdef __APPLE__ local::setProperty(t, method, *properties, "os.name", "Mac OS X"); -# else +# else // not __APPLE__ local::setProperty(t, method, *properties, "os.name", "Linux"); -# endif +# endif // not __APPLE__ local::setProperty(t, method, *properties, "java.io.tmpdir", "/tmp"); local::setProperty(t, method, *properties, "user.home", getenv("HOME")); char buffer[PATH_MAX]; local::setProperty(t, method, *properties, "user.dir", getcwd(buffer, PATH_MAX)); -#endif +#endif // not PLATFORM_WINDOWS local::setProperty(t, method, *properties, "java.protocol.handler.pkgs", "avian"); @@ -3046,6 +3046,11 @@ jvmInitProperties(Thread* t, uintptr_t* arguments) (t, method, *properties, "sun.boot.library.path", static_cast(t->m->classpath)->libraryPath); + local::setProperty + (t, method, *properties, "sun.boot.class.path", + static_cast + (systemClassLoaderFinder(t, root(t, Machine::BootLoader)))->path()); + local::setProperty(t, method, *properties, "file.encoding", "ASCII"); #ifdef ARCH_x86_32 local::setProperty(t, method, *properties, "os.arch", "x86"); From 0be731863798d6015d60c4686616e1239fea301a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 29 Feb 2012 11:48:06 -0700 Subject: [PATCH 013/140] minor whitespace change --- src/jnienv.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 34f82efc65..a4460689ed 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3358,8 +3358,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) *(argumentPointer++) = a->options[i].optionString; } - *m = new (h->allocate(sizeof(Machine))) - Machine + *m = new (h->allocate(sizeof(Machine))) Machine (s, h, bf, af, p, c, properties, propertyCount, arguments, a->nOptions); *t = p->makeThread(*m, 0, 0); From 6c9a1e1643638de61da539aa77ed851c47b447c6 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 20 Feb 2012 17:23:18 -0700 Subject: [PATCH 014/140] add "throws IOException" to java.io.File.createTempFile --- classpath/java/io/File.java | 9 +++++++-- test/Files.java | 6 ++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index bfae0da9b6..a77502c041 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -35,11 +35,16 @@ public class File implements Serializable { this(parent.getPath() + FileSeparator + child); } - public static File createTempFile(String prefix, String suffix) { + public static File createTempFile(String prefix, String suffix) + throws IOException + { return createTempFile(prefix, suffix, null); } - public static File createTempFile(String prefix, String suffix, File directory) { + public static File createTempFile(String prefix, String suffix, + File directory) + throws IOException + { if(directory == null) { directory = new File(System.getProperty("java.io.tmpdir")); } diff --git a/test/Files.java b/test/Files.java index 7661e79018..f3d1988f31 100644 --- a/test/Files.java +++ b/test/Files.java @@ -21,7 +21,9 @@ public class Files { } - private static void setExecutableTestWithPermissions(boolean executable) { + private static void setExecutableTestWithPermissions(boolean executable) + throws Exception + { File file = File.createTempFile("avian.", null); file.setExecutable(executable); if (executable) { @@ -33,7 +35,7 @@ public class Files { } } - public static void main(String[] args) { + public static void main(String[] args) throws Exception { isAbsoluteTest(true); isAbsoluteTest(false); setExecutableTestWithPermissions(true); From 71295e54c71feb28736aaa27e454171f95b3eec1 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 11 Mar 2012 04:58:15 -0600 Subject: [PATCH 015/140] handle constants larger than 8 bits in subtractBorrowCR --- src/x86.cpp | 3 ++- test/Longs.java | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/x86.cpp b/src/x86.cpp index 28c6dc2bc7..42f6ccf8de 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1478,7 +1478,8 @@ subtractBorrowCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, opcode(c, 0x83, 0xd8 + regCode(b)); c->code.append(v); } else { - abort(c); + opcode(c, 0x81, 0xd8 + regCode(b)); + c->code.append4(v); } } diff --git a/test/Longs.java b/test/Longs.java index 434ee908c9..0472536f60 100644 --- a/test/Longs.java +++ b/test/Longs.java @@ -234,6 +234,54 @@ public class Longs { expect((a ^ 25214903884L) == (2L ^ 25214903884L)); } + { long b = 2; + expect((-281474976710656L) >> b == -281474976710656L >> 2); + expect((-281474976710656L) >>> b == -281474976710656L >>> 2); + expect((-281474976710656L) << b == -281474976710656L << 2); + expect((-281474976710656L) + b == -281474976710656L + 2L); + expect((-281474976710656L) - b == -281474976710656L - 2L); + expect((-281474976710656L) * b == -281474976710656L * 2L); + expect((-281474976710656L) / b == -281474976710656L / 2L); + expect((-281474976710656L) % b == -281474976710656L % 2L); + expect(((-281474976710656L) & b) == (-281474976710656L & 2L)); + expect(((-281474976710656L) | b) == (-281474976710656L | 2L)); + expect(((-281474976710656L) ^ b) == (-281474976710656L ^ 2L)); + + b = 2; + expect(281474976710656L >> b == 281474976710656L >> 2); + expect(281474976710656L >>> b == 281474976710656L >>> 2); + expect(281474976710656L << b == 281474976710656L << 2); + expect(281474976710656L + b == 281474976710656L + 2L); + expect(281474976710656L - b == 281474976710656L - 2L); + expect(281474976710656L * b == 281474976710656L * 2L); + expect(281474976710656L / b == 281474976710656L / 2L); + expect(281474976710656L % b == 281474976710656L % 2L); + expect((281474976710656L & b) == (281474976710656L & 2L)); + expect((281474976710656L | b) == (281474976710656L | 2L)); + expect((281474976710656L ^ b) == (281474976710656L ^ 2L)); + } + + { long a = 2L; + expect(a + (-281474976710656L) == 2L + (-281474976710656L)); + expect(a - (-281474976710656L) == 2L - (-281474976710656L)); + expect(a * (-281474976710656L) == 2L * (-281474976710656L)); + expect(a / (-281474976710656L) == 2L / (-281474976710656L)); + expect(a % (-281474976710656L) == 2L % (-281474976710656L)); + expect((a & (-281474976710656L)) == (2L & (-281474976710656L))); + expect((a | (-281474976710656L)) == (2L | (-281474976710656L))); + expect((a ^ (-281474976710656L)) == (2L ^ (-281474976710656L))); + + a = 2L; + expect(a + 281474976710656L == 2L + 281474976710656L); + expect(a - 281474976710656L == 2L - 281474976710656L); + expect(a * 281474976710656L == 2L * 281474976710656L); + expect(a / 281474976710656L == 2L / 281474976710656L); + expect(a % 281474976710656L == 2L % 281474976710656L); + expect((a & 281474976710656L) == (2L & 281474976710656L)); + expect((a | 281474976710656L) == (2L | 281474976710656L)); + expect((a ^ 281474976710656L) == (2L ^ 281474976710656L)); + } + { long x = 231; expect((x >> 32) == 0); expect((x >>> 32) == 0); From 8590695f2d30e2ff1ccfca4decf48d17dc88f397 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 11 Mar 2012 05:00:08 -0600 Subject: [PATCH 016/140] constrain exception handler bounds to bytecode length Scala occasionally generates exception handler tables with interval bounds which fall outside the range of valid bytecode indexes, so we must clamp them or risk out-of-bounds array accesses. --- src/compile.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/compile.cpp b/src/compile.cpp index 4963212feb..2b415588db 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -6172,6 +6172,10 @@ logCompile(MyThread* t, const void* code, unsigned size, const char* class_, int resolveIpForwards(Context* context, int start, int end) { + if (start < 0) { + start = 0; + } + while (start < end and context->visitTable[start] == 0) { ++ start; } @@ -6186,6 +6190,13 @@ resolveIpForwards(Context* context, int start, int end) int resolveIpBackwards(Context* context, int start, int end) { + Thread* t = context->thread; + if (start >= static_cast + (codeLength(t, methodCode(t, context->method)))) + { + start = codeLength(t, methodCode(t, context->method)) - 1; + } + while (start >= end and context->visitTable[start] == 0) { -- start; } @@ -6269,11 +6280,16 @@ translateExceptionHandlerTable(MyThread* t, Context* context, intptr_t start) exceptionHandlerEnd(oldHandler)); if (LIKELY(handlerStart >= 0)) { + assert(t, handlerStart < static_cast + (codeLength(t, methodCode(t, context->method)))); + int handlerEnd = resolveIpBackwards (context, exceptionHandlerEnd(oldHandler), exceptionHandlerStart(oldHandler)); assert(t, handlerEnd >= 0); + assert(t, handlerEnd < static_cast + (codeLength(t, methodCode(t, context->method)))); intArrayBody(t, newIndex, ni * 3) = c->machineIp(handlerStart)->value() - start; From 3e38628ad6e40b726d3264e6a9ccd2afcb31edf4 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 11 Mar 2012 05:04:12 -0600 Subject: [PATCH 017/140] check superclasses in fieldForOffset, not just immediate class --- src/classpath-openjdk.cpp | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 977d466c6d..bf6d16b5c0 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2207,19 +2207,40 @@ pipeAvailable(int fd, int* available) } object -fieldForOffset(Thread* t, object o, unsigned offset) +fieldForOffsetInClass(Thread* t, object c, unsigned offset) { - object table = classFieldTable(t, objectClass(t, o)); - for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { - object field = objectArrayBody(t, table, i); - if ((fieldFlags(t, field) & ACC_STATIC) == 0 - and fieldOffset(t, field) == offset) - { + object super = classSuper(t, c); + if (super) { + object field = fieldForOffsetInClass(t, super, offset); + if (field) { return field; } } - - abort(t); + + object table = classFieldTable(t, c); + if (table) { + for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { + object field = objectArrayBody(t, table, i); + if ((fieldFlags(t, field) & ACC_STATIC) == 0 + and fieldOffset(t, field) == offset) + { + return field; + } + } + } + + return 0; +} + +object +fieldForOffset(Thread* t, object o, unsigned offset) +{ + object field = fieldForOffsetInClass(t, objectClass(t, o), offset); + if (field) { + return field; + } else { + abort(t); + } } } // namespace local From 04a34a75ed04cd8d947d57919622913d45d0d681 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 11 Mar 2012 05:05:14 -0600 Subject: [PATCH 018/140] implement sun.misc.Unsafe.monitorEnter and monitorExit --- src/classpath-openjdk.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index bf6d16b5c0..5ff044d49f 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2694,6 +2694,20 @@ Avian_sun_misc_Unsafe_park monitorRelease(t, local::interruptLock(t, t->javaThread)); } +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_monitorEnter +(Thread* t, object, uintptr_t* arguments) +{ + acquire(t, reinterpret_cast(arguments[1])); +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_monitorExit +(Thread* t, object, uintptr_t* arguments) +{ + release(t, reinterpret_cast(arguments[1])); +} + namespace { namespace local { From 6cc0ddda7c59e9c1f283bd9f20115268eeb81726 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 11 Mar 2012 05:06:08 -0600 Subject: [PATCH 019/140] implement JVM_HoldsLock --- src/classpath-openjdk.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 5ff044d49f..2866b6072b 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -3289,8 +3289,21 @@ EXPORT(JVM_IsInterrupted)(Thread* t, jobject thread, jboolean clear) return run(t, jvmIsInterrupted, arguments); } +uint64_t +jvmHoldsLock(Thread* t, uintptr_t* arguments) +{ + object m = objectMonitor(t, *reinterpret_cast(arguments[0]), false); + + return m and monitorOwner(t, m) == t; +} + extern "C" JNIEXPORT jboolean JNICALL -EXPORT(JVM_HoldsLock)(Thread*, jclass, jobject) { abort(); } +EXPORT(JVM_HoldsLock)(Thread* t, jclass, jobject o) +{ + uintptr_t arguments[] = { reinterpret_cast(o) }; + + return run(t, jvmHoldsLock, arguments); +} extern "C" JNIEXPORT void JNICALL EXPORT(JVM_DumpAllStacks)(Thread*, jclass) { abort(); } From 3820fec9d75b5312f2898dad82ac8f6b839c7081 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 11 Mar 2012 16:26:46 -0600 Subject: [PATCH 020/140] fix OS X OpenJDK 7 build --- makefile | 3 ++- openjdk-src.mk | 46 +++++++++++++++++++++++++-------------- src/classpath-openjdk.cpp | 31 ++++++++++++++++++++++++-- 3 files changed, 61 insertions(+), 19 deletions(-) diff --git a/makefile b/makefile index 9408df6d9c..636bbf2147 100755 --- a/makefile +++ b/makefile @@ -310,7 +310,8 @@ ifeq ($(platform),darwin) version-script-flag = lflags = $(common-lflags) -ldl -framework CoreFoundation ifneq ($(arch),arm) - lflags += -framework CoreServices + lflags += -framework CoreServices -framework SystemConfiguration \ + -framework Security endif ifeq ($(bootimage),true) bootimage-lflags = -Wl,-segprot,__RWX,rwx,rwx diff --git a/openjdk-src.mk b/openjdk-src.mk index a2dd051cce..dfe455b4bb 100644 --- a/openjdk-src.mk +++ b/openjdk-src.mk @@ -236,9 +236,6 @@ else openjdk-sources += \ $(openjdk-src)/solaris/native/common/jdk_util_md.c \ $(openjdk-src)/solaris/native/common/jni_util_md.c \ - $(openjdk-src)/solaris/native/common/deps/syscalls_fp.c \ - $(openjdk-src)/solaris/native/common/deps/gconf2/gconf_fp.c \ - $(openjdk-src)/solaris/native/common/deps/glib2/gio_fp.c \ $(openjdk-src)/solaris/native/java/io/canonicalize_md.c \ $(openjdk-src)/solaris/native/java/io/Console_md.c \ $(openjdk-src)/solaris/native/java/io/FileDescriptor_md.c \ @@ -276,25 +273,19 @@ else $(openjdk-src)/solaris/native/sun/nio/ch/ServerSocketChannelImpl.c \ $(openjdk-src)/solaris/native/sun/nio/ch/SocketChannelImpl.c \ $(openjdk-src)/solaris/native/sun/nio/ch/SocketDispatcher.c \ - $(openjdk-src)/solaris/native/sun/nio/ch/EPollArrayWrapper.c \ $(openjdk-src)/solaris/native/sun/nio/ch/PollArrayWrapper.c \ $(openjdk-src)/solaris/native/sun/nio/ch/InheritedChannel.c \ $(openjdk-src)/solaris/native/sun/nio/ch/NativeThread.c \ $(openjdk-src)/solaris/native/sun/nio/fs/UnixNativeDispatcher.c \ - ifeq ($(platform),linux) - openjdk-sources += \ - $(openjdk-src)/solaris/native/java/net/linux_close.c - endif - openjdk-headers-classes += \ java.net.PlainDatagramSocketImpl \ java.io.UnixFileSystem \ sun.nio.ch.InheritedChannel \ - sun.nio.ch.EPollArrayWrapper \ sun.nio.fs.UnixNativeDispatcher \ - openjdk-cflags += "-I$(openjdk-src)/solaris/javavm/export" \ + openjdk-cflags += \ + "-I$(openjdk-src)/solaris/javavm/export" \ "-I$(openjdk-src)/solaris/native/common" \ "-I$(openjdk-src)/solaris/native/java/io" \ "-I$(openjdk-src)/solaris/native/java/lang" \ @@ -304,11 +295,34 @@ else "-I$(openjdk-src)/solaris/native/sun/nio/ch" \ "-I$(openjdk-src)/solaris/javavm/include" \ "-I$(openjdk-src)/solaris/hpi/include" \ - "-I$(openjdk-src)/solaris/native/common/deps" \ - "-I$(openjdk-src)/solaris/native/common/deps/glib2" \ - "-I$(openjdk-src)/solaris/native/common/deps/gconf2" \ - $(shell pkg-config --cflags glib-2.0) \ - $(shell pkg-config --cflags gconf-2.0) + "-I$(openjdk-src)/solaris/native/common/deps" + + ifeq ($(platform),linux) + openjdk-sources += \ + $(openjdk-src)/solaris/native/java/net/linux_close.c \ + $(openjdk-src)/solaris/native/common/deps/syscalls_fp.c \ + $(openjdk-src)/solaris/native/common/deps/gconf2/gconf_fp.c \ + $(openjdk-src)/solaris/native/common/deps/glib2/gio_fp.c \ + $(openjdk-src)/solaris/native/sun/nio/ch/EPollArrayWrapper.c + + openjdk-headers-classes += \ + sun.nio.ch.EPollArrayWrapper + + openjdk-cflags += \ + "-I$(openjdk-src)/solaris/native/common/deps/glib2" \ + "-I$(openjdk-src)/solaris/native/common/deps/gconf2" \ + $(shell pkg-config --cflags glib-2.0) \ + $(shell pkg-config --cflags gconf-2.0) + endif + + ifeq ($(platform),darwin) + openjdk-sources += \ + $(openjdk-src)/solaris/native/java/lang/java_props_macosx.c \ + $(openjdk-src)/solaris/native/java/net/bsd_close.c + + openjdk-cflags += \ + -DMACOSX + endif endif openjdk-local-sources = \ diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 713bea71ec..184fd81667 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -440,9 +440,14 @@ class MyClasspath : public Classpath { PROTECT(t, class_); object name = makeClassNameString(t, getClassName(t, class_)); + PROTECT(t, name); - return vm::makeJclass - (t, 0, 0, name, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, class_); + object c = allocate(t, FixedSizeOfJclass, true); + setObjectClass(t, c, type(t, Machine::JclassType)); + set(t, c, JclassName, name); + set(t, c, JclassVmClass, class_); + + return c; } virtual object @@ -2299,6 +2304,24 @@ Avian_sun_misc_Unsafe_registerNatives // ignore } +extern "C" JNIEXPORT void +Avian_sun_misc_Perf_registerNatives +(Thread*, object, uintptr_t*) +{ + // ignore +} + +extern "C" JNIEXPORT int64_t +Avian_sun_misc_Perf_createLong +(Thread* t, object, uintptr_t*) +{ + return reinterpret_cast + (t->m->processor->invoke + (t, resolveMethod + (t, root(t, Machine::BootLoader), "java/nio/ByteBuffer", "allocate", + "(I)Ljava/nio/ByteBuffer;"), 0, 8)); +} + extern "C" JNIEXPORT int64_t Avian_sun_misc_Unsafe_addressSize (Thread*, object, uintptr_t*) @@ -2750,6 +2773,7 @@ Avian_sun_misc_Unsafe_copyMemory memcpy(dst, src, count); } +extern "C" JNIEXPORT void JNICALL Avian_sun_misc_Unsafe_monitorEnter (Thread* t, object, uintptr_t* arguments) { @@ -5308,6 +5332,9 @@ extern "C" JNIEXPORT jboolean JNICALL EXPORT(JVM_CX8Field)(JNIEnv*, jobject*, jfieldID*, jlong, jlong) { abort(); } +extern "C" JNIEXPORT void JNICALL +JVM_SetNativeThreadName(JNIEnv*, jobject, jstring) { abort(); } + } // namespace local } // namespace From 3817bc280e583bcd21c894879ab23cc75c8fe87f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 11 Mar 2012 17:46:36 -0600 Subject: [PATCH 021/140] heretofore untested iOS OpenJDK support --- makefile | 48 ++++++++++++++++++++++++++++++ openjdk-src.mk | 11 +++++-- src/openjdk/my_java_props_macosx.c | 28 +++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 src/openjdk/my_java_props_macosx.c diff --git a/makefile b/makefile index 636bbf2147..64429c1725 100755 --- a/makefile +++ b/makefile @@ -990,6 +990,18 @@ $(openjdk-objects): $(build)/openjdk/%-openjdk.o: $(openjdk-src)/%.c \ @echo "compiling $(@)" @mkdir -p $(dir $(@)) sed 's/^static jclass ia_class;//' < $(<) > $(build)/openjdk/$(notdir $(<)) +ifeq ($(ios),true) + sed \ + -e 's/^#ifndef __APPLE__/#if 1/' \ + -e 's/^#ifdef __APPLE__/#if 0/' \ + < "$(openjdk-src)/solaris/native/java/lang/ProcessEnvironment_md.c" \ + > $(build)/openjdk/ProcessEnvironment_md.c + sed \ + -e 's/^#ifndef __APPLE__/#if 1/' \ + -e 's/^#ifdef __APPLE__/#if 0/' \ + < "$(openjdk-src)/solaris/native/java/lang/UNIXProcess_md.c" \ + > $(build)/openjdk/UNIXProcess_md.c +endif $(cc) -fPIC $(openjdk-extra-cflags) $(openjdk-cflags) \ $(optimization-cflags) -w -c $(build)/openjdk/$(notdir $(<)) \ $(call output,$(@)) @@ -1020,6 +1032,42 @@ ifeq ($(platform),windows) < "$(openjdk-src)/windows/native/java/net/NetworkInterface.h" \ > $(build)/openjdk/NetworkInterface.h echo 'static int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP);' >> $(build)/openjdk/NetworkInterface.h +endif +ifeq ($(platform),darwin) + mkdir -p $(build)/openjdk/netinet + for file in \ + /usr/include/netinet/ip.h \ + /usr/include/netinet/in_systm.h \ + /usr/include/netinet/ip_icmp.h \ + /usr/include/netinet/in_var.h \ + /usr/include/netinet/icmp6.h \ + /usr/include/netinet/ip_var.h; do \ + if [ ! -f "$(build)/openjdk/netinet/$$(basename $${file})" ]; then \ + ln "$${file}" "$(build)/openjdk/netinet/$$(basename $${file})"; \ + fi; \ + done + mkdir -p $(build)/openjdk/netinet6 + for file in \ + /usr/include/netinet6/in6_var.h; do \ + if [ ! -f "$(build)/openjdk/netinet6/$$(basename $${file})" ]; then \ + ln "$${file}" "$(build)/openjdk/netinet6/$$(basename $${file})"; \ + fi; \ + done + mkdir -p $(build)/openjdk/net + for file in \ + /usr/include/net/if_arp.h; do \ + if [ ! -f "$(build)/openjdk/net/$$(basename $${file})" ]; then \ + ln "$${file}" "$(build)/openjdk/net/$$(basename $${file})"; \ + fi; \ + done + mkdir -p $(build)/openjdk/sys + for file in \ + /usr/include/sys/kern_event.h \ + /usr/include/sys/sys_domain.h; do \ + if [ ! -f "$(build)/openjdk/sys/$$(basename $${file})" ]; then \ + ln "$${file}" "$(build)/openjdk/sys/$$(basename $${file})"; \ + fi; \ + done endif @touch $(@) diff --git a/openjdk-src.mk b/openjdk-src.mk index dfe455b4bb..6735471fea 100644 --- a/openjdk-src.mk +++ b/openjdk-src.mk @@ -317,15 +317,22 @@ else ifeq ($(platform),darwin) openjdk-sources += \ - $(openjdk-src)/solaris/native/java/lang/java_props_macosx.c \ $(openjdk-src)/solaris/native/java/net/bsd_close.c + ifeq ($(ios),true) + openjdk-local-sources += \ + $(src)/openjdk/my_java_props_macosx.c + else + openjdk-sources += \ + $(openjdk-src)/solaris/native/java/lang/java_props_macosx.c + endif + openjdk-cflags += \ -DMACOSX endif endif -openjdk-local-sources = \ +openjdk-local-sources += \ $(src)/openjdk/my_net_util.c \ $(src)/openjdk/my_management.c diff --git a/src/openjdk/my_java_props_macosx.c b/src/openjdk/my_java_props_macosx.c new file mode 100644 index 0000000000..8a1850010f --- /dev/null +++ b/src/openjdk/my_java_props_macosx.c @@ -0,0 +1,28 @@ +#include "java_props_macosx.h" + +PreferredToolkit +getPreferredToolkit() +{ + return unset; +} + +void +setOSNameAndVersion(java_props_t* props) +{ + props->os_name = strdup("iOS"); + props->os_version = strdup("Unknown"); +} + +void +setProxyProperties(java_props_t* props) +{ + // ignore +} + +char* +setupMacOSXLocale(int cat) +{ + return 0; +} + +char* environ[0]; From 4aefa211a3e0f7a578e3664f97fcd109068b2608 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 13 Mar 2012 08:26:51 -0600 Subject: [PATCH 022/140] File.createNewFile should return false if the file already exists --- classpath/java-io.cpp | 21 ++++++++++----------- classpath/java/io/File.java | 11 +++-------- src/classpath-openjdk.cpp | 16 ++++++++-------- test/Files.java | 6 ++++++ 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 5b723114ae..c1373a3c58 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -48,7 +48,6 @@ # define R_OK 4 # else # define OPEN _wopen -# define CREAT _wcreat # endif # define GET_CHARS GetStringChars @@ -71,7 +70,6 @@ typedef wchar_t char_t; # define STRUCT_STAT struct stat # define MKDIR mkdir # define CHMOD chmod -# define CREAT creat # define UNLINK unlink # define RENAME rename # define OPEN_MASK 0 @@ -102,12 +100,6 @@ OPEN(string_t path, int mask, int mode) return -1; } } - -inline int -CREAT(string_t path, int mode) -{ - return OPEN(path, _O_CREAT, mode); -} #endif inline bool @@ -407,21 +399,28 @@ Java_java_io_File_mkdir(JNIEnv* e, jclass, jstring path) } } -extern "C" JNIEXPORT void JNICALL +extern "C" JNIEXPORT jboolean JNICALL Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path) { + bool result = false; string_t chars = getChars(e, path); if (chars) { + fprintf(stderr, "create file \"%s\"\n", chars); if (not exists(chars)) { - int fd = CREAT(chars, 0600); + int fd = OPEN(chars, O_CREAT | O_WRONLY | O_EXCL, 0600); if (fd == -1) { - throwNewErrno(e, "java/io/IOException"); + fprintf(stderr, "errno %d\n", errno); + if (errno != EEXIST) { + throwNewErrno(e, "java/io/IOException"); + } } else { + result = true; doClose(e, fd); } } releaseChars(e, path, chars); } + return result; } extern "C" JNIEXPORT void JNICALL diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index a77502c041..59c7da8d16 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -204,15 +204,10 @@ public class File implements Serializable { } } - private static native void createNewFile(String path) throws IOException; + private static native boolean createNewFile(String path) throws IOException; - public boolean createNewFile() { - try { - createNewFile(path); - return true; - } catch (IOException e) { - return false; - } + public boolean createNewFile() throws IOException { + return createNewFile(path); } public static native void delete(String path) throws IOException; diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 2866b6072b..bfa759d63d 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -42,7 +42,6 @@ # define S_IWUSR _S_IWRITE # else # define OPEN _open -# define CREAT _creat # endif # define O_RDONLY _O_RDONLY @@ -82,6 +81,8 @@ typedef int socklen_t; #endif // not PLATFORM_WINDOWS +#define JVM_EEXIST -100 + using namespace vm; namespace { @@ -97,12 +98,6 @@ OPEN(string_t path, int mask, int mode) return -1; } } - -inline int -CREAT(string_t path, int mode) -{ - return OPEN(path, _O_CREAT, mode); -} #endif namespace local { @@ -4819,7 +4814,12 @@ EXPORT(JVM_NativePath)(char* path) extern "C" JNIEXPORT jint JNICALL EXPORT(JVM_Open)(const char* path, jint flags, jint mode) { - return OPEN(path, flags, mode); + int r = OPEN(path, flags, mode); + if (r == -1) { + return errno == EEXIST ? JVM_EEXIST : -1; + } else { + return r; + } } extern "C" JNIEXPORT jint JNICALL diff --git a/test/Files.java b/test/Files.java index f3d1988f31..b5484462cf 100644 --- a/test/Files.java +++ b/test/Files.java @@ -40,6 +40,12 @@ public class Files { isAbsoluteTest(false); setExecutableTestWithPermissions(true); setExecutableTestWithPermissions(false); + + { File f = new File("test.txt"); + f.createNewFile(); + expect(! f.createNewFile()); + f.delete(); + } } } From 756f58210aa35591a6140a545cf23eeae8d94978 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 13 Mar 2012 08:28:33 -0600 Subject: [PATCH 023/140] add test for sun.misc.Unsafe functionality --- classpath/avian/Machine.java | 8 +++++ classpath/sun/misc/Unsafe.java | 49 +++++++++++++++++++++++++ test/UnsafeTest.java | 65 ++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 classpath/sun/misc/Unsafe.java create mode 100644 test/UnsafeTest.java diff --git a/classpath/avian/Machine.java b/classpath/avian/Machine.java index cbc62efae6..a17cbff9d7 100644 --- a/classpath/avian/Machine.java +++ b/classpath/avian/Machine.java @@ -10,8 +10,16 @@ package avian; +import sun.misc.Unsafe; + public abstract class Machine { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + public static native void dumpHeap(String outputFile); + public static Unsafe getUnsafe() { + return unsafe; + } + } diff --git a/classpath/sun/misc/Unsafe.java b/classpath/sun/misc/Unsafe.java new file mode 100644 index 0000000000..84f22b88db --- /dev/null +++ b/classpath/sun/misc/Unsafe.java @@ -0,0 +1,49 @@ +package sun.misc; + +public final class Unsafe { + private void Unsafe() { } + + private static final Unsafe Instance = new Unsafe(); + + public static Unsafe getUnsafe() { + return Instance; + } + + public native long allocateMemory(long bytes); + + public native void setMemory(long address, long count, byte value); + + public native void freeMemory(long address); + + public native byte getByte(long address); + + public native void putByte(long address, byte x); + + public native short getShort(long address); + + public native void putShort(long address, short x); + + public native char getChar(long address); + + public native void putChar(long address, char x); + + public native int getInt(long address); + + public native void putInt(long address, int x); + + public native long getLong(long address); + + public native void putLong(long address, long x); + + public native float getFloat(long address); + + public native void putFloat(long address, float x); + + public native double getDouble(long address); + + public native void putDouble(long address, double x); + + public native long getAddress(long address); + + public native void putAddress(long address, long x); +} diff --git a/test/UnsafeTest.java b/test/UnsafeTest.java new file mode 100644 index 0000000000..5167526c3b --- /dev/null +++ b/test/UnsafeTest.java @@ -0,0 +1,65 @@ +import sun.misc.Unsafe; + +public class UnsafeTest { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void main(String[] args) { + Unsafe u = avian.Machine.getUnsafe(); + + final long size = 64; + long memory = u.allocateMemory(size); + try { + for (int i = 0; i < size; ++i) + u.putByte(memory + i, (byte) 42); + + for (int i = 0; i < size; ++i) + expect(u.getByte(memory + i) == 42); + + for (int i = 0; i < size / 2; ++i) + u.putShort(memory + (i * 2), (short) -12345); + + for (int i = 0; i < size / 2; ++i) + expect(u.getShort(memory + (i * 2)) == -12345); + + for (int i = 0; i < size / 2; ++i) + u.putChar(memory + (i * 2), (char) 23456); + + for (int i = 0; i < size / 2; ++i) + expect(u.getChar(memory + (i * 2)) == 23456); + + for (int i = 0; i < size / 4; ++i) + u.putInt(memory + (i * 4), 0x12345678); + + for (int i = 0; i < size / 4; ++i) + expect(u.getInt(memory + (i * 4)) == 0x12345678); + + for (int i = 0; i < size / 4; ++i) + u.putFloat(memory + (i * 4), 1.2345678F); + + for (int i = 0; i < size / 4; ++i) + expect(u.getFloat(memory + (i * 4)) == 1.2345678F); + + for (int i = 0; i < size / 8; ++i) + u.putLong(memory + (i * 8), 0x1234567890ABCDEFL); + + for (int i = 0; i < size / 8; ++i) + expect(u.getLong(memory + (i * 8)) == 0x1234567890ABCDEFL); + + for (int i = 0; i < size / 8; ++i) + u.putDouble(memory + (i * 8), 1.23456789012345D); + + for (int i = 0; i < size / 8; ++i) + expect(u.getDouble(memory + (i * 8)) == 1.23456789012345D); + + for (int i = 0; i < size / 8; ++i) + u.putAddress(memory + (i * 8), 0x12345678); + + for (int i = 0; i < size / 8; ++i) + expect(u.getAddress(memory + (i * 8)) == 0x12345678); + } finally { + u.freeMemory(memory); + } + } +} From 58dc32382d196a393740b77e0dfbbf03810ad552 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 13 Mar 2012 10:30:41 -0600 Subject: [PATCH 024/140] fix memory management bugs in finder.cpp --- src/finder.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/finder.cpp b/src/finder.cpp index f53738e9f4..6d9136a991 100644 --- a/src/finder.cpp +++ b/src/finder.cpp @@ -448,6 +448,7 @@ class JarElement: public Element { unsigned jarLength): s(s), allocator(allocator), + originalName(0), name(0), urlPrefix_(name ? append(allocator, "jar:file:", name, "!/") : 0), sourceUrl_(name ? append(allocator, "file:", name) : 0), @@ -517,12 +518,14 @@ class JarElement: public Element { } virtual void dispose(unsigned size) { - if (originalName != name) { - allocator->free(originalName, strlen(originalName) + 1); + if (name) { + if (originalName != name) { + allocator->free(originalName, strlen(originalName) + 1); + } + allocator->free(name, strlen(name) + 1); + allocator->free(urlPrefix_, strlen(urlPrefix_) + 1); + allocator->free(sourceUrl_, strlen(sourceUrl_) + 1); } - allocator->free(name, strlen(name) + 1); - allocator->free(urlPrefix_, strlen(urlPrefix_) + 1); - allocator->free(sourceUrl_, strlen(sourceUrl_) + 1); if (index) { index->dispose(); } @@ -906,7 +909,9 @@ class MyFinder: public Finder { e = e->next; t->dispose(); } - allocator->free(pathString, strlen(pathString) + 1); + if (pathString) { + allocator->free(pathString, strlen(pathString) + 1); + } allocator->free(this, sizeof(*this)); } From 37044236d44f338bdaad1d248247e6151fad09d2 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 13 Mar 2012 10:31:08 -0600 Subject: [PATCH 025/140] provide dummy implementation of JVM_GetThreadInterruptEvent --- src/classpath-openjdk.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index bfa759d63d..72c9750fd5 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -5263,7 +5263,17 @@ jio_vfprintf(FILE* stream, const char* format, va_list a) #ifdef PLATFORM_WINDOWS extern "C" JNIEXPORT void* JNICALL EXPORT(JVM_GetThreadInterruptEvent)() -{ abort(); } +{ + // hack: We don't want to expose thread interruption implementation + // details, so we give the class library a fake event to play with. + // This means that threads won't be interruptable when blocked in + // Process.waitFor. + static HANDLE fake = 0; + if (fake == 0) { + fake = CreateEvent(0, true, false, 0); + } + return fake; +} namespace { HMODULE jvmHandle = 0; } From f2e26791a4ade61345849a98111eaf27be1d3c4e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 13 Mar 2012 17:00:47 -0600 Subject: [PATCH 026/140] handle constant-to-register "zero-extend" moves in x86.cpp We've already been handling this case in arm.cpp and powerpc.cpp, but apparently we've never hit this code path in x86.cpp before. Indeed, I've been unable to come up with a Java source code test that hits it; it's only come up in Scala-generated bytecode. --- src/x86.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/x86.cpp b/src/x86.cpp index 42f6ccf8de..bd6c418417 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -2678,6 +2678,7 @@ populateTables(ArchitectureContext* c) bo[index(c, MoveZ, R, R)] = CAST2(moveZRR); bo[index(c, MoveZ, M, R)] = CAST2(moveZMR); + bo[index(c, MoveZ, C, R)] = CAST2(moveCR); bo[index(c, Add, R, R)] = CAST2(addRR); bo[index(c, Add, C, R)] = CAST2(addCR); From f8934b2c9df5e4137c33e9f47950bcfce6988367 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 Mar 2012 11:38:20 -0600 Subject: [PATCH 027/140] fix race condition in System::Monitor::wait If we clear Thread::flags before releasing the thread mutex and re-acquiring the monitor mutex, it's possible that we will be notified between the release and re-acquire, which will confuse us later if we try to wait on the same monitor again such that we well not remove ourselves from the wait list because we think we've been removed by the notifier. The solution is to wait until we've acquired both mutexes before we clear Thread::flags. --- src/posix.cpp | 34 ++++++++++++++++++++++++++++------ src/windows.cpp | 27 +++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/posix.cpp b/src/posix.cpp index 074c6b379c..35d2d6b7b1 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -122,8 +122,7 @@ pathOfExecutable(System* s, const char** retBuf, unsigned* size) const bool Verbose = false; -const unsigned Waiting = 1 << 0; -const unsigned Notified = 1 << 1; +const unsigned Notified = 1 << 0; class MySystem: public System { public: @@ -256,7 +255,14 @@ class MySystem: public System { } void append(Thread* t) { +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif + if (last) { + expect(s, t != last); last->next = t; last = t; } else { @@ -271,6 +277,7 @@ class MySystem: public System { if (current == first) { first = t->next; } else { + expect(s, previous != t->next); previous->next = t->next; } @@ -286,6 +293,12 @@ class MySystem: public System { current = current->next; } } + +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif } virtual void wait(System::Thread* context, int64_t time) { @@ -308,13 +321,13 @@ class MySystem: public System { { ACQUIRE(t->mutex); + expect(s, (t->flags & Notified) == 0); + interrupted = t->r->interrupted(); if (interrupted and clearInterrupted) { t->r->setInterrupted(false); } - t->flags |= Waiting; - append(t); depth = this->depth; @@ -343,14 +356,22 @@ class MySystem: public System { } notified = ((t->flags & Notified) != 0); - - t->flags = 0; } pthread_mutex_lock(&mutex); + { ACQUIRE(t->mutex); + t->flags = 0; + } + if (not notified) { remove(t); + } else { +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif } t->next = 0; @@ -380,6 +401,7 @@ class MySystem: public System { Thread* t = first; first = first->next; if (t == last) { + expect(s, first == 0); last = 0; } diff --git a/src/windows.cpp b/src/windows.cpp index 42a79d3024..37c9251726 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -215,6 +215,12 @@ class MySystem: public System { } void append(Thread* t) { +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif + if (last) { last->next = t; last = t; @@ -245,6 +251,12 @@ class MySystem: public System { current = current->next; } } + +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif } virtual void wait(System::Thread* context, int64_t time) { @@ -270,6 +282,8 @@ class MySystem: public System { { ACQUIRE(s, t->mutex); + expect(s, (t->flags & Notified) == 0); + interrupted = t->r->interrupted(); if (interrupted and clearInterrupted) { t->r->setInterrupted(false); @@ -306,15 +320,23 @@ class MySystem: public System { } notified = ((t->flags & Notified) != 0); - - t->flags = 0; } r = WaitForSingleObject(mutex, INFINITE); assert(s, r == WAIT_OBJECT_0); + { ACQUIRE(s, t->mutex); + t->flags = 0; + } + if (not notified) { remove(t); + } else { +#ifndef NDEBUG + for (Thread* x = first; x; x = x->next) { + expect(s, t != x); + } +#endif } t->next = 0; @@ -346,6 +368,7 @@ class MySystem: public System { Thread* t = first; first = first->next; if (t == last) { + expect(s, first == 0); last = 0; } From c4722fa843b0902d73a1a206f0771e5fe9e7a433 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 Mar 2012 11:54:03 -0600 Subject: [PATCH 028/140] update Unsafe.setMemory to reflect new OpenJDK 7 signature and semantics --- classpath/sun/misc/Unsafe.java | 3 ++- src/builtin.cpp | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/classpath/sun/misc/Unsafe.java b/classpath/sun/misc/Unsafe.java index 84f22b88db..b7613d2559 100644 --- a/classpath/sun/misc/Unsafe.java +++ b/classpath/sun/misc/Unsafe.java @@ -11,7 +11,8 @@ public final class Unsafe { public native long allocateMemory(long bytes); - public native void setMemory(long address, long count, byte value); + public native void setMemory + (Object base, long offset, long count, byte value); public native void freeMemory(long address); diff --git a/src/builtin.cpp b/src/builtin.cpp index f7f2c12d29..0efc8fbbd2 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -352,13 +352,24 @@ Avian_sun_misc_Unsafe_freeMemory extern "C" JNIEXPORT void JNICALL Avian_sun_misc_Unsafe_setMemory -(Thread*, object, uintptr_t* arguments) +(Thread* t, object, uintptr_t* arguments) { - int64_t p; memcpy(&p, arguments + 1, 8); - int64_t count; memcpy(&count, arguments + 3, 8); - int8_t v = arguments[5]; + object base = reinterpret_cast(arguments[1]); + int64_t offset; memcpy(&offset, arguments + 2, 8); + int64_t count; memcpy(&count, arguments + 4, 8); + int8_t value = arguments[6]; - memset(reinterpret_cast(p), v, count); + fprintf(stderr, "base %p offset %p count %ld value %d\n", base, reinterpret_cast(offset), count, value); + + PROTECT(t, base); + + ACQUIRE(t, t->m->referenceLock); + + if (base) { + memset(&cast(base, offset), value, count); + } else { + memset(reinterpret_cast(offset), value, count); + } } // NB: The following primitive get/put methods are only used by the From b6cdf4efcb55afe5893e3f9590241f4fb3792dad Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 Mar 2012 12:08:14 -0600 Subject: [PATCH 029/140] remove debug logging --- src/builtin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/builtin.cpp b/src/builtin.cpp index 0efc8fbbd2..6988dcf8eb 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -359,8 +359,6 @@ Avian_sun_misc_Unsafe_setMemory int64_t count; memcpy(&count, arguments + 4, 8); int8_t value = arguments[6]; - fprintf(stderr, "base %p offset %p count %ld value %d\n", base, reinterpret_cast(offset), count, value); - PROTECT(t, base); ACQUIRE(t, t->m->referenceLock); From d718bbf8335e4ede4e9e1568a63da4feeb9955df Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 Mar 2012 12:35:22 -0600 Subject: [PATCH 030/140] implement Unsafe.getByte(Object, long) --- src/classpath-openjdk.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index d767522803..9c6b2e191d 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2566,13 +2566,20 @@ Avian_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF } extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_getBoolean +Avian_sun_misc_Unsafe_getByte (Thread*, object, uintptr_t* arguments) { object o = reinterpret_cast(arguments[1]); int64_t offset; memcpy(&offset, arguments + 2, 8); - return cast(o, offset); + return cast(o, offset); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getBoolean +(Thread* t, object method, uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getByte(t, method, arguments); } extern "C" JNIEXPORT void JNICALL From d78247ab9a5659f98b51ed249cb85cf897186f21 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 14 Mar 2012 12:36:42 -0600 Subject: [PATCH 031/140] implement -Xss command line option --- src/compile.cpp | 2 +- src/interpret.cpp | 22 +++++++++++----------- src/jnienv.cpp | 8 +++++++- src/machine.cpp | 4 +++- src/machine.h | 12 ++++++++---- src/main.cpp | 1 + 6 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 2b415588db..1f5f82d852 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -8303,7 +8303,7 @@ invoke(Thread* thread, object method, ArgumentList* arguments) uintptr_t stackLimit = t->stackLimit; uintptr_t stackPosition = reinterpret_cast(&t); if (stackLimit == 0) { - t->stackLimit = stackPosition - StackSizeInBytes; + t->stackLimit = stackPosition - t->m->stackSizeInBytes; } else if (stackPosition < stackLimit) { throwNew(t, Machine::StackOverflowErrorType); } diff --git a/src/interpret.cpp b/src/interpret.cpp index 6f3c853ec6..57b2e9836b 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -40,7 +40,7 @@ class Thread: public vm::Thread { unsigned sp; int frame; object code; - uintptr_t stack[StackSizeInWords]; + uintptr_t stack[0]; }; inline void @@ -50,7 +50,7 @@ pushObject(Thread* t, object o) fprintf(stderr, "push object %p at %d\n", o, t->sp); } - assert(t, t->sp + 1 < StackSizeInWords / 2); + assert(t, t->sp + 1 < stackSizeInWords(t) / 2); t->stack[(t->sp * 2) ] = ObjectTag; t->stack[(t->sp * 2) + 1] = reinterpret_cast(o); ++ t->sp; @@ -63,7 +63,7 @@ pushInt(Thread* t, uint32_t v) fprintf(stderr, "push int %d at %d\n", v, t->sp); } - assert(t, t->sp + 1 < StackSizeInWords / 2); + assert(t, t->sp + 1 < stackSizeInWords(t) / 2); t->stack[(t->sp * 2) ] = IntTag; t->stack[(t->sp * 2) + 1] = v; ++ t->sp; @@ -156,7 +156,7 @@ peekObject(Thread* t, unsigned index) index); } - assert(t, index < StackSizeInWords / 2); + assert(t, index < stackSizeInWords(t) / 2); assert(t, t->stack[index * 2] == ObjectTag); return *reinterpret_cast(t->stack + (index * 2) + 1); } @@ -170,7 +170,7 @@ peekInt(Thread* t, unsigned index) index); } - assert(t, index < StackSizeInWords / 2); + assert(t, index < stackSizeInWords(t) / 2); assert(t, t->stack[index * 2] == IntTag); return t->stack[(index * 2) + 1]; } @@ -226,7 +226,7 @@ inline object* pushReference(Thread* t, object o) { if (o) { - expect(t, t->sp + 1 < StackSizeInWords / 2); + expect(t, t->sp + 1 < stackSizeInWords(t) / 2); pushObject(t, o); return reinterpret_cast(t->stack + ((t->sp - 1) * 2) + 1); } else { @@ -405,7 +405,7 @@ checkStack(Thread* t, object method) + codeMaxLocals(t, methodCode(t, method)) + FrameFootprint + codeMaxStack(t, methodCode(t, method)) - > StackSizeInWords / 2)) + > stackSizeInWords(t) / 2)) { throwNew(t, Machine::StackOverflowErrorType); } @@ -2879,7 +2879,7 @@ class MyProcessor: public Processor { virtual vm::Thread* makeThread(Machine* m, object javaThread, vm::Thread* parent) { - Thread* t = new (m->heap->allocate(sizeof(Thread))) + Thread* t = new (m->heap->allocate(sizeof(Thread) + m->stackSizeInBytes)) Thread(m, javaThread, parent); t->init(); return t; @@ -2996,7 +2996,7 @@ class MyProcessor: public Processor { assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1 - > StackSizeInWords / 2)) + > stackSizeInWords(t) / 2)) { throwNew(t, Machine::StackOverflowErrorType); } @@ -3020,7 +3020,7 @@ class MyProcessor: public Processor { assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1 - > StackSizeInWords / 2)) + > stackSizeInWords(t) / 2)) { throwNew(t, Machine::StackOverflowErrorType); } @@ -3043,7 +3043,7 @@ class MyProcessor: public Processor { or t->state == Thread::ExclusiveState); if (UNLIKELY(t->sp + parameterFootprint(vmt, methodSpec, false) - > StackSizeInWords / 2)) + > stackSizeInWords(t) / 2)) { throwNew(t, Machine::StackOverflowErrorType); } diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 52106c3085..ffc0937789 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3269,6 +3269,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) local::JavaVMInitArgs* a = static_cast(args); unsigned heapLimit = 0; + unsigned stackLimit = 0; const char* bootLibrary = 0; const char* classpath = 0; const char* javaHome = AVIAN_JAVA_HOME; @@ -3285,6 +3286,8 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) const char* p = a->options[i].optionString + 2; if (strncmp(p, "mx", 2) == 0) { heapLimit = local::parseSize(p + 2); + } else if (strncmp(p, "ss", 2) == 0) { + stackLimit = local::parseSize(p + 2); } else if (strncmp(p, BOOTCLASSPATH_PREPEND_OPTION ":", sizeof(BOOTCLASSPATH_PREPEND_OPTION)) == 0) { @@ -3327,6 +3330,8 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) } if (heapLimit == 0) heapLimit = 128 * 1024 * 1024; + + if (stackLimit == 0) stackLimit = 128 * 1024; if (classpath == 0) classpath = "."; @@ -3378,7 +3383,8 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args) } *m = new (h->allocate(sizeof(Machine))) Machine - (s, h, bf, af, p, c, properties, propertyCount, arguments, a->nOptions); + (s, h, bf, af, p, c, properties, propertyCount, arguments, a->nOptions, + stackLimit); *t = p->makeThread(*m, 0, 0); diff --git a/src/machine.cpp b/src/machine.cpp index 47b53dccbf..e4dcf2ad2c 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2425,7 +2425,8 @@ namespace vm { Machine::Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder, Processor* processor, Classpath* classpath, const char** properties, unsigned propertyCount, - const char** arguments, unsigned argumentCount): + const char** arguments, unsigned argumentCount, + unsigned stackSizeInBytes): vtable(&javaVMVTable), system(system), heapClient(new (heap->allocate(sizeof(HeapClient))) @@ -2448,6 +2449,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, liveCount(0), daemonCount(0), fixedFootprint(0), + stackSizeInBytes(stackSizeInBytes), localThread(0), stateLock(0), heapLock(0), diff --git a/src/machine.h b/src/machine.h index a52cf30a73..08884e40d0 100644 --- a/src/machine.h +++ b/src/machine.h @@ -112,9 +112,6 @@ const unsigned ThreadBackupHeapSizeInBytes = 2 * 1024; const unsigned ThreadBackupHeapSizeInWords = ThreadBackupHeapSizeInBytes / BytesPerWord; -const unsigned StackSizeInBytes = 128 * 1024; -const unsigned StackSizeInWords = StackSizeInBytes / BytesPerWord; - const unsigned ThreadHeapPoolSize = 64; const unsigned FixedFootprintThresholdInBytes @@ -1281,7 +1278,7 @@ class Machine { Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder, Processor* processor, Classpath* classpath, const char** properties, unsigned propertyCount, const char** arguments, - unsigned argumentCount); + unsigned argumentCount, unsigned stackSizeInBytes); ~Machine() { dispose(); @@ -1310,6 +1307,7 @@ class Machine { unsigned liveCount; unsigned daemonCount; unsigned fixedFootprint; + unsigned stackSizeInBytes; System::Local* localThread; System::Monitor* stateLock; System::Monitor* heapLock; @@ -1639,6 +1637,12 @@ objectClass(Thread*, object o) return mask(cast(o, 0)); } +inline unsigned +stackSizeInWords(Thread* t) +{ + return t->m->stackSizeInBytes / BytesPerWord; +} + void enter(Thread* t, Thread::State state); diff --git a/src/main.cpp b/src/main.cpp index a84630b68c..f5358e985c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -143,6 +143,7 @@ usageAndExit(const char* name) (stderr, "usage: %s\n" "\t[{-cp|-classpath} ]\n" "\t[-Xmx]\n" + "\t[-Xss]\n" "\t[-Xbootclasspath/p:]\n" "\t[-Xbootclasspath:]\n" "\t[-Xbootclasspath/a:]\n" From 333b6c59d46e79d6083ff65af0ec5ae5770cfe5d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 16 Mar 2012 11:01:20 -0600 Subject: [PATCH 032/140] fix non-embedded openjdk build on OS X The JRE lib dir for OpenJDK 7 on OS X seems to be just "lib", not e.g. "lib/amd64" by default, so we use that now. Also, the default library compatibility version for libjvm.dylib is 0.0.0, but OpenJDK wants 1.0.0, so we set it explicitly. --- makefile | 12 +++++++++--- src/classpath-openjdk.cpp | 2 ++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index 64429c1725..c0b0d320dc 100755 --- a/makefile +++ b/makefile @@ -113,8 +113,13 @@ ifneq ($(openjdk),) else options := $(options)-openjdk test-executable = $(shell pwd)/$(executable-dynamic) - library-path = \ - $(library-path-variable)=$(build):$(openjdk)/jre/lib/$(openjdk-arch) + ifeq ($(build-platform),darwin) + library-path = \ + $(library-path-variable)=$(build):$(openjdk)/jre/lib + else + library-path = \ + $(library-path-variable)=$(build):$(openjdk)/jre/lib/$(openjdk-arch) + endif javahome = "$$($(native-path) "$(openjdk)/jre")" endif @@ -308,7 +313,8 @@ ifeq ($(platform),darwin) endif version-script-flag = - lflags = $(common-lflags) -ldl -framework CoreFoundation + lflags = $(common-lflags) -ldl -framework CoreFoundation \ + -Wl,-compatibility_version,1.0.0 ifneq ($(arch),arm) lflags += -framework CoreServices -framework SystemConfiguration \ -framework Security diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 9c6b2e191d..6959abafec 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -410,6 +410,8 @@ class MyClasspath : public Classpath { sb.append(javaHome); #ifdef PLATFORM_WINDOWS sb.append("/bin"); +#elif defined __APPLE__ + sb.append("/lib"); #elif defined ARCH_x86_64 sb.append("/lib/amd64"); #else From 8cb6446bec95dba05052280f3e536628e7190840 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 17 Mar 2012 12:57:59 -0600 Subject: [PATCH 033/140] handle zero-length arrays in truncate functions --- src/compile.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index 1f5f82d852..6b1a63f414 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -6216,8 +6216,10 @@ truncateIntArray(Thread* t, object array, unsigned length) PROTECT(t, array); object newArray = makeIntArray(t, length); - memcpy(&intArrayBody(t, newArray, 0), &intArrayBody(t, array, 0), - length * 4); + if (length) { + memcpy(&intArrayBody(t, newArray, 0), &intArrayBody(t, array, 0), + length * 4); + } return newArray; } @@ -6230,8 +6232,10 @@ truncateArray(Thread* t, object array, unsigned length) PROTECT(t, array); object newArray = makeArray(t, length); - memcpy(&arrayBody(t, newArray, 0), &arrayBody(t, array, 0), - length * BytesPerWord); + if (length) { + memcpy(&arrayBody(t, newArray, 0), &arrayBody(t, array, 0), + length * BytesPerWord); + } return newArray; } @@ -6244,9 +6248,11 @@ truncateLineNumberTable(Thread* t, object table, unsigned length) PROTECT(t, table); object newTable = makeLineNumberTable(t, length); - memcpy(&lineNumberTableBody(t, newTable, 0), - &lineNumberTableBody(t, table, 0), - length * sizeof(uint64_t)); + if (length) { + memcpy(&lineNumberTableBody(t, newTable, 0), + &lineNumberTableBody(t, table, 0), + length * sizeof(uint64_t)); + } return newTable; } From 8abe9bf469b60c45bd7dea5ba045f30138928ef2 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 17 Mar 2012 12:58:41 -0600 Subject: [PATCH 034/140] fix memory leak in freeZipFileEntry --- src/classpath-openjdk.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 6959abafec..813870ad10 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -1538,6 +1538,8 @@ freeZipFileEntry(Thread* t, object method, uintptr_t* arguments) (t, methodRuntimeDataNative(t, getMethodRuntimeData(t, method))), 0, file->file, entry->entry); } + + t->m->heap->free(entry, sizeof(ZipFile::Entry)); } int64_t JNICALL From 75b5d3df4aa827ead558fd02f8cba123364ccf20 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 17 Mar 2012 12:59:22 -0600 Subject: [PATCH 035/140] fix Windows OpenJDK 7 build --- makefile | 2 +- openjdk-src.mk | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index c0b0d320dc..efa44b1769 100755 --- a/makefile +++ b/makefile @@ -384,7 +384,7 @@ ifeq ($(platform),windows) so-suffix = .dll exe-suffix = .exe - lflags = -L$(lib) $(common-lflags) -lws2_32 -mwindows -mconsole + lflags = -L$(lib) $(common-lflags) -lws2_32 -liphlpapi -mwindows -mconsole cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 -DTARGET_PLATFORM_WINDOWS diff --git a/openjdk-src.mk b/openjdk-src.mk index 6735471fea..0c16a86a21 100644 --- a/openjdk-src.mk +++ b/openjdk-src.mk @@ -173,6 +173,7 @@ endif ifeq ($(platform),windows) openjdk-sources += \ + $(openjdk-src)/windows/native/common/jni_util_md.c \ $(openjdk-src)/windows/native/java/io/canonicalize_md.c \ $(openjdk-src)/windows/native/java/io/Console_md.c \ $(openjdk-src)/windows/native/java/io/FileDescriptor_md.c \ @@ -193,7 +194,6 @@ ifeq ($(platform),windows) $(openjdk-src)/windows/native/java/net/Inet6AddressImpl.c \ $(openjdk-src)/windows/native/java/net/NetworkInterface.c \ $(openjdk-src)/windows/native/java/net/NetworkInterface_winXP.c \ - $(openjdk-src)/windows/native/java/net/NetworkInterface_win9x.c \ $(openjdk-src)/windows/native/java/net/SocketInputStream.c \ $(openjdk-src)/windows/native/java/net/SocketOutputStream.c \ $(openjdk-src)/windows/native/java/util/WindowsPreferences.c \ @@ -203,7 +203,6 @@ ifeq ($(platform),windows) $(openjdk-src)/windows/native/sun/nio/ch/DatagramChannelImpl.c \ $(openjdk-src)/windows/native/sun/nio/ch/DatagramDispatcher.c \ $(openjdk-src)/windows/native/sun/nio/ch/FileChannelImpl.c \ - $(openjdk-src)/windows/native/sun/nio/ch/FileDispatcher.c \ $(openjdk-src)/windows/native/sun/nio/ch/FileKey.c \ $(openjdk-src)/windows/native/sun/nio/ch/IOUtil.c \ $(openjdk-src)/windows/native/sun/nio/ch/Net.c \ @@ -211,6 +210,7 @@ ifeq ($(platform),windows) $(openjdk-src)/windows/native/sun/nio/ch/SocketChannelImpl.c \ $(openjdk-src)/windows/native/sun/nio/ch/SocketDispatcher.c \ $(openjdk-src)/windows/native/sun/nio/ch/WindowsSelectorImpl.c \ + $(openjdk-src)/windows/native/sun/nio/fs/WindowsNativeDispatcher.c \ $(openjdk-src)/windows/native/sun/security/provider/WinCAPISeedGenerator.c openjdk-headers-classes += \ @@ -218,6 +218,7 @@ ifeq ($(platform),windows) java.lang.ProcessImpl \ sun.io.Win32ErrorMode \ sun.nio.ch.WindowsSelectorImpl \ + sun.nio.fs.WindowsNativeDispatcher \ openjdk-cflags += \ "-I$(openjdk-src)/windows/javavm/export" \ @@ -228,6 +229,9 @@ ifeq ($(platform),windows) "-I$(openjdk-src)/windows/native/sun/nio/ch" \ "-I$(openjdk-src)/windows/javavm/include" \ "-I$(root)/win32/include" \ + -DLOCALE_SNAME=0x0000005c \ + -DLOCALE_SISO3166CTRYNAME2=0x00000068 \ + -DLOCALE_SISO639LANGNAME2=0x00000067 \ -D_JNI_IMPLEMENTATION_ \ -D_JAVASOFT_WIN32_TYPEDEF_MD_H_ \ -Ds6_words=_s6_words \ From 0167868797bad47505512e413a886f77a8d63be6 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 17 Mar 2012 18:47:22 -0600 Subject: [PATCH 036/140] various Windows OpenJDK 7 fixes --- makefile | 3 ++- openjdk-src.mk | 1 + src/classpath-openjdk.cpp | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index efa44b1769..53ca635f7f 100755 --- a/makefile +++ b/makefile @@ -387,7 +387,6 @@ ifeq ($(platform),windows) lflags = -L$(lib) $(common-lflags) -lws2_32 -liphlpapi -mwindows -mconsole cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 -DTARGET_PLATFORM_WINDOWS - ifeq (,$(filter mingw32 cygwin,$(build-platform))) openjdk-extra-cflags += -I$(src)/openjdk/caseSensitive cxx = x86_64-w64-mingw32-g++ -m32 @@ -425,6 +424,8 @@ ifeq ($(platform),windows) strip = x86_64-w64-mingw32-strip inc = "$(win64)/include" lib = "$(win64)/lib" + else + shared += -Wl,--add-stdcall-alias endif endif diff --git a/openjdk-src.mk b/openjdk-src.mk index 0c16a86a21..027b6a79b5 100644 --- a/openjdk-src.mk +++ b/openjdk-src.mk @@ -203,6 +203,7 @@ ifeq ($(platform),windows) $(openjdk-src)/windows/native/sun/nio/ch/DatagramChannelImpl.c \ $(openjdk-src)/windows/native/sun/nio/ch/DatagramDispatcher.c \ $(openjdk-src)/windows/native/sun/nio/ch/FileChannelImpl.c \ + $(openjdk-src)/windows/native/sun/nio/ch/FileDispatcherImpl.c \ $(openjdk-src)/windows/native/sun/nio/ch/FileKey.c \ $(openjdk-src)/windows/native/sun/nio/ch/IOUtil.c \ $(openjdk-src)/windows/native/sun/nio/ch/Net.c \ diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 813870ad10..feb468b083 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -3863,7 +3863,7 @@ EXPORT(JVM_FindClassFromClassLoader)(Thread* t, const char* name, } extern "C" JNIEXPORT jclass JNICALL -EXPORT(JVM_FindClassFromBootLoader)(Thread* t, const char* name) +JVM_FindClassFromBootLoader(Thread* t, const char* name) { return EXPORT(JVM_FindClassFromClassLoader)(t, name, false, 0, false); } @@ -5344,7 +5344,7 @@ EXPORT(JVM_CX8Field)(JNIEnv*, jobject*, jfieldID*, jlong, jlong) { abort(); } extern "C" JNIEXPORT void JNICALL -JVM_SetNativeThreadName(JNIEnv*, jobject, jstring) { abort(); } +EXPORT(JVM_SetNativeThreadName)(JNIEnv*, jobject, jstring) { abort(); } } // namespace local From 9a50e6958790e85956a553c9f8f66d52f0064312 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 17 Mar 2012 22:42:15 -0600 Subject: [PATCH 037/140] remove debug logging --- classpath/java-io.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index c1373a3c58..d08601a465 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -405,11 +405,9 @@ Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path) bool result = false; string_t chars = getChars(e, path); if (chars) { - fprintf(stderr, "create file \"%s\"\n", chars); if (not exists(chars)) { int fd = OPEN(chars, O_CREAT | O_WRONLY | O_EXCL, 0600); if (fd == -1) { - fprintf(stderr, "errno %d\n", errno); if (errno != EEXIST) { throwNewErrno(e, "java/io/IOException"); } From 674c5604945848ee62b3d8ca77b8d065a2f50e93 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 17 Mar 2012 22:45:35 -0600 Subject: [PATCH 038/140] fix static field alignment calculation The previous code caused overlap between 64-bit fields and subsequent fields under certain circumstances on 32-bit systems. --- src/bootimage.cpp | 6 ++---- src/machine.cpp | 10 ++++------ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 3d75f4401c..dd408705e2 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -502,10 +502,8 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, } if (fieldFlags(t, field) & ACC_STATIC) { - unsigned excess = (targetStaticOffset % targetSize) - % TargetBytesPerWord; - if (excess) { - targetStaticOffset += TargetBytesPerWord - excess; + while (targetStaticOffset % targetSize) { + ++ targetStaticOffset; } buildStaticOffset = fieldOffset(t, field); diff --git a/src/machine.cpp b/src/machine.cpp index e4dcf2ad2c..182308f8d4 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1164,9 +1164,8 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) unsigned size = fieldSize(t, code); if (flags & ACC_STATIC) { - unsigned excess = (staticOffset % size) % BytesPerWord; - if (excess) { - staticOffset += BytesPerWord - excess; + while (staticOffset % size) { + ++ staticOffset; } fieldOffset(t, field) = staticOffset; @@ -1205,9 +1204,8 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) for (unsigned i = 0, offset = 0; i < staticCount; ++i) { unsigned size = fieldSize(t, RUNTIME_ARRAY_BODY(staticTypes)[i]); - unsigned excess = offset % size; - if (excess) { - offset += BytesPerWord - excess; + while (offset % size) { + ++ offset; } unsigned value = intArrayBody(t, staticValueTable, i); From 4f0d275e133f51ba8e949191f2b3b069a008c82f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 18 Mar 2012 20:10:42 -0600 Subject: [PATCH 039/140] run JNI_OnLoad if found in ClassLoader.loadLibrary --- src/classpath-common.h | 10 ++++++++++ src/classpath-openjdk.cpp | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/classpath-common.h b/src/classpath-common.h index 99e042162c..5f769ae00f 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -120,6 +120,16 @@ void runOnLoadIfFound(Thread* t, System::Library* library) { void* p = library->resolve("JNI_OnLoad"); + +#ifdef PLATFORM_WINDOWS + if (p == 0) { + p = library->resolve("_JNI_OnLoad@8"); + if (p == 0) { + p = library->resolve("JNI_OnLoad@8"); + } + } +#endif + if (p) { jint (JNICALL * JNI_OnLoad)(Machine*, void*); memcpy(&JNI_OnLoad, &p, sizeof(void*)); diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index feb468b083..cbb705d8d9 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -1747,7 +1747,7 @@ loadLibrary(Thread* t, object, uintptr_t* arguments) loadLibrary (t, static_cast(t->m->classpath)->libraryPath, - RUNTIME_ARRAY_BODY(n), not absolute, false); + RUNTIME_ARRAY_BODY(n), not absolute, true); } // only safe to call during bootstrap when there's only one thread From 8e6f5ac6e3324f9dd76019de070b035ef0b5b3cd Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 21 Mar 2012 10:38:30 -0600 Subject: [PATCH 040/140] add ZipEntry.isDirectory (trivial implementation) --- classpath/java/util/zip/ZipEntry.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/classpath/java/util/zip/ZipEntry.java b/classpath/java/util/zip/ZipEntry.java index 9f18369c52..ffa8a1a82e 100644 --- a/classpath/java/util/zip/ZipEntry.java +++ b/classpath/java/util/zip/ZipEntry.java @@ -14,4 +14,8 @@ public abstract class ZipEntry { public abstract String getName(); public abstract int getCompressedSize(); public abstract int getSize(); + + public boolean isDirectory() { + return getName().endsWith("/"); + } } From a10ce99302d8060f97a90e181a1ce84a21669793 Mon Sep 17 00:00:00 2001 From: Vaughn Dice Date: Mon, 26 Mar 2012 11:12:07 -0600 Subject: [PATCH 041/140] Use latest iOS SDK found on local machine --- makefile | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index 53ca635f7f..3c96d2edca 100755 --- a/makefile +++ b/makefile @@ -327,12 +327,24 @@ ifeq ($(platform),darwin) so-suffix = .dylib shared = -dynamiclib + sdk-dir = $(developer-dir)/Platforms/iPhoneOS.platform/Developer/SDKs + + ios-version := $(shell if test -d $(sdk-dir)/iPhoneOS5.1.sdk; then echo 5.1; \ + elif test -d $(sdk-dir)/iPhoneOS5.0.sdk; then echo 5.0; \ + elif test -d $(sdk-dir)/iPhoneOS4.3.sdk; then echo 4.3; \ + elif test -d $(sdk-dir)/iPhoneOS4.2.sdk; then echo 4.2; \ + else echo; fi) + + ifeq ($(ios-version),) + x := $(error "couldn't find SDK for iOS version") + endif + ifeq ($(arch),arm) ifeq ($(build-arch),powerpc) converter-cflags += -DOPPOSITE_ENDIAN endif flags = -arch armv7 -isysroot \ - $(developer-dir)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/ + $(sdk-dir)/iPhoneOS$(ios-version).sdk/ openjdk-extra-cflags += $(flags) cflags += $(flags) asmflags += $(flags) From 5be0edd628cf49f4a16c0a5139ef4bc61e34fb3d Mon Sep 17 00:00:00 2001 From: Vaughn Dice Date: Mon, 26 Mar 2012 11:12:07 -0600 Subject: [PATCH 042/140] Use latest iOS SDK found on local machine --- makefile | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index 9408df6d9c..5bfcd04ca9 100755 --- a/makefile +++ b/makefile @@ -320,12 +320,24 @@ ifeq ($(platform),darwin) so-suffix = .dylib shared = -dynamiclib + sdk-dir = $(developer-dir)/Platforms/iPhoneOS.platform/Developer/SDKs + + ios-version := $(shell if test -d $(sdk-dir)/iPhoneOS5.1.sdk; then echo 5.1; \ + elif test -d $(sdk-dir)/iPhoneOS5.0.sdk; then echo 5.0; \ + elif test -d $(sdk-dir)/iPhoneOS4.3.sdk; then echo 4.3; \ + elif test -d $(sdk-dir)/iPhoneOS4.2.sdk; then echo 4.2; \ + else echo; fi) + + ifeq ($(ios-version),) + x := $(error "couldn't find SDK for iOS version") + endif + ifeq ($(arch),arm) ifeq ($(build-arch),powerpc) converter-cflags += -DOPPOSITE_ENDIAN endif flags = -arch armv7 -isysroot \ - $(developer-dir)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/ + $(sdk-dir)/iPhoneOS$(ios-version).sdk/ openjdk-extra-cflags += $(flags) cflags += $(flags) asmflags += $(flags) From 031852daec60100e741d06c918cce16f0d542468 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 26 Mar 2012 18:02:43 -0600 Subject: [PATCH 043/140] add -march=i586 to lflags as well as cflags where appropriate When link time optimization is enabled, we need to remind the compiler that we're targeting i586 when linking so it can resolve atomic operations like __sync_bool_compare_and_swap. --- makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/makefile b/makefile index 53ca635f7f..635fb052c9 100755 --- a/makefile +++ b/makefile @@ -472,6 +472,7 @@ ifneq ($(platform),darwin) ifeq ($(arch),i386) # this is necessary to support __sync_bool_compare_and_swap: cflags += -march=i586 + lflags += -march=i586 endif endif From 2ee377112599facd0571e168660182331c486004 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 26 Mar 2012 18:06:16 -0600 Subject: [PATCH 044/140] make find[Field|Method]InClass non-inline functions It seems that GCC 4.6.1 gets confused at LTO time when we take the address of inline functions, so I'm switching them to non-inline linkage to make it happy. --- src/machine.cpp | 68 +++++++++++++++++++++++++++++-------------------- src/machine.h | 19 +++----------- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index 182308f8d4..744d6d2a46 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2416,6 +2416,38 @@ isInitializing(Thread* t, object c) return false; } +object +findInTable(Thread* t, object table, object name, object spec, + object& (*getName)(Thread*, object), + object& (*getSpec)(Thread*, object)) +{ + if (table) { + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + object o = arrayBody(t, table, i); + if (vm::strcmp(&byteArrayBody(t, getName(t, o), 0), + &byteArrayBody(t, name, 0)) == 0 and + vm::strcmp(&byteArrayBody(t, getSpec(t, o), 0), + &byteArrayBody(t, spec, 0)) == 0) + { + return o; + } + } + +// fprintf(stderr, "%s %s not in\n", +// &byteArrayBody(t, name, 0), +// &byteArrayBody(t, spec, 0)); + +// for (unsigned i = 0; i < arrayLength(t, table); ++i) { +// object o = arrayBody(t, table, i); +// fprintf(stderr, "\t%s %s\n", +// &byteArrayBody(t, getName(t, o), 0), +// &byteArrayBody(t, getSpec(t, o), 0)); +// } + } + + return 0; +} + } // namespace namespace vm { @@ -3884,35 +3916,17 @@ makeObjectArray(Thread* t, object elementClass, unsigned count) } object -findInTable(Thread* t, object table, object name, object spec, - object& (*getName)(Thread*, object), - object& (*getSpec)(Thread*, object)) +findFieldInClass(Thread* t, object class_, object name, object spec) { - if (table) { - for (unsigned i = 0; i < arrayLength(t, table); ++i) { - object o = arrayBody(t, table, i); - if (vm::strcmp(&byteArrayBody(t, getName(t, o), 0), - &byteArrayBody(t, name, 0)) == 0 and - vm::strcmp(&byteArrayBody(t, getSpec(t, o), 0), - &byteArrayBody(t, spec, 0)) == 0) - { - return o; - } - } + return findInTable + (t, classFieldTable(t, class_), name, spec, fieldName, fieldSpec); +} -// fprintf(stderr, "%s %s not in\n", -// &byteArrayBody(t, name, 0), -// &byteArrayBody(t, spec, 0)); - -// for (unsigned i = 0; i < arrayLength(t, table); ++i) { -// object o = arrayBody(t, table, i); -// fprintf(stderr, "\t%s %s\n", -// &byteArrayBody(t, getName(t, o), 0), -// &byteArrayBody(t, getSpec(t, o), 0)); -// } - } - - return 0; +object +findMethodInClass(Thread* t, object class_, object name, object spec) +{ + return findInTable + (t, classMethodTable(t, class_), name, spec, methodName, methodSpec); } object diff --git a/src/machine.h b/src/machine.h index 08884e40d0..cdb3ecf039 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2595,16 +2595,7 @@ makeObjectArray(Thread* t, unsigned count) } object -findInTable(Thread* t, object table, object name, object spec, - object& (*getName)(Thread*, object), - object& (*getSpec)(Thread*, object)); - -inline object -findFieldInClass(Thread* t, object class_, object name, object spec) -{ - return findInTable - (t, classFieldTable(t, class_), name, spec, fieldName, fieldSpec); -} +findFieldInClass(Thread* t, object class_, object name, object spec); inline object findFieldInClass2(Thread* t, object class_, const char* name, const char* spec) @@ -2616,12 +2607,8 @@ findFieldInClass2(Thread* t, object class_, const char* name, const char* spec) return findFieldInClass(t, class_, n, s); } -inline object -findMethodInClass(Thread* t, object class_, object name, object spec) -{ - return findInTable - (t, classMethodTable(t, class_), name, spec, methodName, methodSpec); -} +object +findMethodInClass(Thread* t, object class_, object name, object spec); inline object makeThrowable From 1be6fe6f152e22e569610ec261892efbb3167ab0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 26 Mar 2012 18:02:43 -0600 Subject: [PATCH 045/140] add -march=i586 to lflags as well as cflags where appropriate When link time optimization is enabled, we need to remind the compiler that we're targeting i586 when linking so it can resolve atomic operations like __sync_bool_compare_and_swap. --- makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/makefile b/makefile index 5bfcd04ca9..49a2bf0ff6 100755 --- a/makefile +++ b/makefile @@ -476,6 +476,7 @@ ifneq ($(platform),darwin) ifeq ($(arch),i386) # this is necessary to support __sync_bool_compare_and_swap: cflags += -march=i586 + lflags += -march=i586 endif endif From 994098baf13347f801e03166deeb908541869094 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 26 Mar 2012 18:06:16 -0600 Subject: [PATCH 046/140] make find[Field|Method]InClass non-inline functions It seems that GCC 4.6.1 gets confused at LTO time when we take the address of inline functions, so I'm switching them to non-inline linkage to make it happy. --- src/machine.cpp | 68 +++++++++++++++++++++++++++++-------------------- src/machine.h | 19 +++----------- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index 47b53dccbf..ac2c5bdd51 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2418,6 +2418,38 @@ isInitializing(Thread* t, object c) return false; } +object +findInTable(Thread* t, object table, object name, object spec, + object& (*getName)(Thread*, object), + object& (*getSpec)(Thread*, object)) +{ + if (table) { + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + object o = arrayBody(t, table, i); + if (vm::strcmp(&byteArrayBody(t, getName(t, o), 0), + &byteArrayBody(t, name, 0)) == 0 and + vm::strcmp(&byteArrayBody(t, getSpec(t, o), 0), + &byteArrayBody(t, spec, 0)) == 0) + { + return o; + } + } + +// fprintf(stderr, "%s %s not in\n", +// &byteArrayBody(t, name, 0), +// &byteArrayBody(t, spec, 0)); + +// for (unsigned i = 0; i < arrayLength(t, table); ++i) { +// object o = arrayBody(t, table, i); +// fprintf(stderr, "\t%s %s\n", +// &byteArrayBody(t, getName(t, o), 0), +// &byteArrayBody(t, getSpec(t, o), 0)); +// } + } + + return 0; +} + } // namespace namespace vm { @@ -3884,35 +3916,17 @@ makeObjectArray(Thread* t, object elementClass, unsigned count) } object -findInTable(Thread* t, object table, object name, object spec, - object& (*getName)(Thread*, object), - object& (*getSpec)(Thread*, object)) +findFieldInClass(Thread* t, object class_, object name, object spec) { - if (table) { - for (unsigned i = 0; i < arrayLength(t, table); ++i) { - object o = arrayBody(t, table, i); - if (vm::strcmp(&byteArrayBody(t, getName(t, o), 0), - &byteArrayBody(t, name, 0)) == 0 and - vm::strcmp(&byteArrayBody(t, getSpec(t, o), 0), - &byteArrayBody(t, spec, 0)) == 0) - { - return o; - } - } + return findInTable + (t, classFieldTable(t, class_), name, spec, fieldName, fieldSpec); +} -// fprintf(stderr, "%s %s not in\n", -// &byteArrayBody(t, name, 0), -// &byteArrayBody(t, spec, 0)); - -// for (unsigned i = 0; i < arrayLength(t, table); ++i) { -// object o = arrayBody(t, table, i); -// fprintf(stderr, "\t%s %s\n", -// &byteArrayBody(t, getName(t, o), 0), -// &byteArrayBody(t, getSpec(t, o), 0)); -// } - } - - return 0; +object +findMethodInClass(Thread* t, object class_, object name, object spec) +{ + return findInTable + (t, classMethodTable(t, class_), name, spec, methodName, methodSpec); } object diff --git a/src/machine.h b/src/machine.h index a52cf30a73..f163214917 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2591,16 +2591,7 @@ makeObjectArray(Thread* t, unsigned count) } object -findInTable(Thread* t, object table, object name, object spec, - object& (*getName)(Thread*, object), - object& (*getSpec)(Thread*, object)); - -inline object -findFieldInClass(Thread* t, object class_, object name, object spec) -{ - return findInTable - (t, classFieldTable(t, class_), name, spec, fieldName, fieldSpec); -} +findFieldInClass(Thread* t, object class_, object name, object spec); inline object findFieldInClass2(Thread* t, object class_, const char* name, const char* spec) @@ -2612,12 +2603,8 @@ findFieldInClass2(Thread* t, object class_, const char* name, const char* spec) return findFieldInClass(t, class_, n, s); } -inline object -findMethodInClass(Thread* t, object class_, object name, object spec) -{ - return findInTable - (t, classMethodTable(t, class_), name, spec, methodName, methodSpec); -} +object +findMethodInClass(Thread* t, object class_, object name, object spec); inline object makeThrowable From 382f01641506700d7757af22324a070ce6be959d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 26 Mar 2012 18:12:58 -0600 Subject: [PATCH 047/140] remove debug logging --- classpath/java-io.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index c1373a3c58..9b7f83286f 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -405,7 +405,6 @@ Java_java_io_File_createNewFile(JNIEnv* e, jclass, jstring path) bool result = false; string_t chars = getChars(e, path); if (chars) { - fprintf(stderr, "create file \"%s\"\n", chars); if (not exists(chars)) { int fd = OPEN(chars, O_CREAT | O_WRONLY | O_EXCL, 0600); if (fd == -1) { From 4800518a316613c9f8ec990b51e2b5c86594e29a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 27 Mar 2012 08:22:35 -0600 Subject: [PATCH 048/140] fix bootimage.cpp build regression I forgot to update bootimage.cpp when I added a parameter to Machine's constructor in d78247a. --- src/bootimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index dd408705e2..6ece510972 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1671,7 +1671,7 @@ main(int ac, const char** av) p->initialize(&image, code, CodeCapacity); Machine* m = new (h->allocate(sizeof(Machine))) Machine - (s, h, f, 0, p, c, 0, 0, 0, 0); + (s, h, f, 0, p, c, 0, 0, 0, 0, 128 * 1024); Thread* t = p->makeThread(m, 0, 0); enter(t, Thread::ActiveState); From a2e0151728e443f2b901f830092fbc68de702312 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 27 Mar 2012 17:57:11 -0600 Subject: [PATCH 049/140] initialize Machine::OutOfMemoryError in writeBootImage2 If we don't initialize that at our first opportunity, it's possible we'll run out of memory later and exit silently instead of printing the error and returning a nonzero exit code. --- src/bootimage.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 6ece510972..834431f7b4 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1287,6 +1287,9 @@ writeBootImage2(Thread* t, FILE* bootimageOutput, FILE* codeOutput, BootImage* image, uint8_t* code, const char* className, const char* methodName, const char* methodSpec) { + setRoot(t, Machine::OutOfMemoryError, + make(t, type(t, Machine::OutOfMemoryErrorType))); + Zone zone(t->m->system, t->m->heap, 64 * 1024); object classPoolMap; From 48bb1e4f41e976c61f2197421e025811af2d1d3e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 27 Mar 2012 17:58:52 -0600 Subject: [PATCH 050/140] include charsets.jar in openjdk-src build The other JARs we were including refer to classes in this jar, so we need to include it as well. --- makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/makefile b/makefile index 635fb052c9..3c1f98bfb2 100755 --- a/makefile +++ b/makefile @@ -1087,6 +1087,7 @@ $(openjdk-jar-dep): $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/rt.jar")" && \ $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/jsse.jar")" && \ $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/jce.jar")" && \ + $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/charsets.jar")" && \ $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/ext/sunjce_provider.jar")" && \ $(jar) xf "$$($(native-path) "$(openjdk)/jre/lib/resources.jar")") @touch $(@) From ae2b58ee40424e84dd7d656d5a221c4feee88fcd Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 27 Mar 2012 18:14:29 -0600 Subject: [PATCH 051/140] increase bootimage.cpp heap and code size limits OpenJDK is huge, so building a bootimage out of the whole thing (as opposed to an app shrunk using ProGuard) requires a lot of space. Note that we still can't handle this on ARM or PowerPC due to a limitation in the compiler, but we don't expect people to ship binaries with the entire OpenJDK class library anyway, so it shouldn't be a problem in practice. --- src/bootimage.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 834431f7b4..3447dff69a 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -25,7 +25,7 @@ using namespace vm; namespace { -const unsigned HeapCapacity = 256 * 1024 * 1024; +const unsigned HeapCapacity = 512 * 1024 * 1024; const unsigned TargetFixieSizeInBytes = 8 + (TargetBytesPerWord * 2); const unsigned TargetFixieSizeInWords = ceiling @@ -1667,7 +1667,11 @@ main(int ac, const char** av) // in a branch instruction for the target architecture (~32MB on // PowerPC and ARM). When that limitation is removed, we'll be able // to specify a capacity as large as we like here: +#if (defined ARCH_x86_64) || (defined ARCH_x86_32) + const unsigned CodeCapacity = 128 * 1024 * 1024; +#else const unsigned CodeCapacity = 30 * 1024 * 1024; +#endif uint8_t* code = static_cast(h->allocate(CodeCapacity)); BootImage image; From 9b1b07bd88d24a085f114c126740816bfdfd04fb Mon Sep 17 00:00:00 2001 From: JET Date: Mon, 2 Apr 2012 12:55:23 -0600 Subject: [PATCH 052/140] Debugging VFP support on ARM. --- src/arm.cpp | 85 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index a2f628857c..07c8df1cea 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -230,9 +230,11 @@ inline int ble(int offset) { return SETCOND(b(offset), LE); } inline int bge(int offset) { return SETCOND(b(offset), GE); } inline int blo(int offset) { return SETCOND(b(offset), CC); } inline int bhs(int offset) { return SETCOND(b(offset), CS); } +inline int bpl(int offset) { return SETCOND(b(offset), PL); } +inline int fmstat() { return fmrx(15, FPSCR); } // HARDWARE FLAGS bool vfpSupported() { - return false; // TODO + return true; // TODO } } @@ -1107,8 +1109,10 @@ void floatAbsoluteRR(Context* con, unsigned size, Assembler::Register* a, unsign void floatNegateRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { if (size == 8) { + /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> invalid 64-bit Scheiße\n"); emit(con, fnegd(b->low, a->low)); } else { + /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> %d <- -%d\n", b->low, a->low); emit(con, fnegs(b->low, a->low)); } } @@ -1282,7 +1286,7 @@ store(Context* con, unsigned size, Assembler::Register* src, or (size != 2 and abs(offset) == (abs(offset) & 0xFFF))) { if (isFpr(src)) { - /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> fpr store offset -> %d\n", src->low); + /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> [%d + 0x%x] <- %d\n", base, offset, src->low); if (size == 4) emit(con, fsts(toFpr(src), base, offset)); else abort(con); } else { @@ -1415,7 +1419,7 @@ load(Context* con, unsigned srcSize, int base, int offset, int index, and abs(offset) == (abs(offset) & 0xFFF))) { if (isFpr(dst)) { - /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> fpr load offset <- %d\n", dst->low); + /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> %d <- [%d + 0x%x]\n", dst->low, base, offset); if (srcSize == 4) emit(con, flds(toFpr(dst), base, offset)); else abort(con); } else { @@ -1583,8 +1587,13 @@ compareRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, { assert(c, aSize == 4 and bSize == 4); assert(c, b->low != a->low); + assert(c, !(isFpr(a) ^ isFpr(b))); - emit(c, cmp(b->low, a->low)); + if (isFpr(a)) { + emit(c, fcmps(toFpr(b), toFpr(a))); + emit(c, fmstat()); + } + else emit(c, cmp(b->low, a->low)); } void @@ -1593,7 +1602,8 @@ compareCR(Context* c, unsigned aSize, Assembler::Constant* a, { assert(c, aSize == 4 and bSize == 4); - if (a->value->resolved() and isOfWidth(a->value->value(), 8)) { + if (!isFpr(b) && a->value->resolved() && + isOfWidth(a->value->value(), 8)) { emit(c, cmpi(b->low, a->value->value())); } else { Assembler::Register tmp(c->client->acquireTemporary()); @@ -1632,23 +1642,37 @@ branch(Context* c, TernaryOperation op) { switch (op) { case JumpIfEqual: + case JumpIfFloatEqual: return beq(0); - + case JumpIfNotEqual: + case JumpIfFloatNotEqual: return bne(0); - + case JumpIfLess: + case JumpIfFloatLess: + case JumpIfFloatLessOrUnordered: return blt(0); - + case JumpIfGreater: + case JumpIfFloatGreater: return bgt(0); - + case JumpIfLessOrEqual: + case JumpIfFloatLessOrEqual: + case JumpIfFloatLessOrEqualOrUnordered: return ble(0); - + case JumpIfGreaterOrEqual: + case JumpIfFloatGreaterOrEqual: return bge(0); - + + case JumpIfFloatGreaterOrUnordered: + return bhi(0); + + case JumpIfFloatGreaterOrEqualOrUnordered: + return bpl(0); + default: abort(c); } @@ -1763,10 +1787,12 @@ branchRR(Context* c, TernaryOperation op, unsigned size, } void -branchCR(Context* c, TernaryOperation op, unsigned size, +branchCR(Context* con, TernaryOperation op, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Constant* target) { + assert(con, !isFloatBranch(op)); + if (size > TargetBytesPerWord) { int64_t v = a->value->value(); @@ -1778,34 +1804,36 @@ branchCR(Context* c, TernaryOperation op, unsigned size, Assembler::Register bh(b->high); - branchLong(c, op, &al, &ah, b, &bh, target, CAST2(compareCR), + branchLong(con, op, &al, &ah, b, &bh, target, CAST2(compareCR), CAST2(compareCR)); } else { - compareCR(c, size, a, size, b); - branch(c, op, target); + compareCR(con, size, a, size, b); + branch(con, op, target); } } void -branchRM(Context* c, TernaryOperation op, unsigned size, +branchRM(Context* con, TernaryOperation op, unsigned size, Assembler::Register* a, Assembler::Memory* b, Assembler::Constant* target) { - assert(c, size <= TargetBytesPerWord); + assert(con, !isFloatBranch(op)); + assert(con, size <= TargetBytesPerWord); - compareRM(c, size, a, size, b); - branch(c, op, target); + compareRM(con, size, a, size, b); + branch(con, op, target); } void -branchCM(Context* c, TernaryOperation op, unsigned size, +branchCM(Context* con, TernaryOperation op, unsigned size, Assembler::Constant* a, Assembler::Memory* b, Assembler::Constant* target) { - assert(c, size <= TargetBytesPerWord); + assert(con, !isFloatBranch(op)); + assert(con, size <= TargetBytesPerWord); - compareCM(c, size, a, size, b); - branch(c, op, target); + compareCM(con, size, a, size, b); + branch(con, op, target); } ShiftMaskPromise* @@ -2304,7 +2332,6 @@ class MyArchitecture: public Assembler::Architecture { if (vfpSupported()) { *aTypeMask = (1 << RegisterOperand); *aRegisterMask = FPR_MASK; - *thunk = true; } else { *thunk = true; } @@ -2314,7 +2341,6 @@ class MyArchitecture: public Assembler::Architecture { if (vfpSupported() && bSize == 4 && aSize == 4) { *aTypeMask = (1 << RegisterOperand); *aRegisterMask = FPR_MASK; - *thunk = true; } else { *thunk = true; } @@ -2324,7 +2350,6 @@ class MyArchitecture: public Assembler::Architecture { if (vfpSupported() && aSize == 4 && bSize == 4) { *aTypeMask = (1 << RegisterOperand); *aRegisterMask = FPR_MASK; - *thunk = true; } else { *thunk = true; } @@ -2421,8 +2446,12 @@ class MyArchitecture: public Assembler::Architecture { case JumpIfFloatGreaterOrUnordered: case JumpIfFloatLessOrEqualOrUnordered: case JumpIfFloatGreaterOrEqualOrUnordered: - if (vfpSupported()) *thunk = true; - else *thunk = true; + if (vfpSupported()) { + *aTypeMask = *bTypeMask = (1 << RegisterOperand); + *aRegisterMask = *bRegisterMask = FPR_MASK; + } else { + *thunk = true; + } break; default: From 2f225795fc1e4a28a1bc5bf7d7fd7159320df1cf Mon Sep 17 00:00:00 2001 From: JET Date: Mon, 2 Apr 2012 22:15:02 -0600 Subject: [PATCH 053/140] added RuntimePermission and System.getenv() --- classpath/java-lang.cpp | 29 +++++++++++++++++ classpath/java/lang/RuntimePermission.java | 21 +++++++++++++ classpath/java/lang/System.java | 36 ++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 classpath/java/lang/RuntimePermission.java diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index bb087560fe..9e99dda6cf 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -631,6 +631,35 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, return r; } +// System.getEnvironment() implementation +// TODO: For Win32, replace usage of deprecated _wenviron +#ifndef PLATFORM_WINDOWS +extern char** environ; +# else +extern wchar_t** _wenviron; +const wchar_t** environ = _wenviron; +#endif +extern "C" JNIEXPORT jobjectArray JNICALL +Java_java_lang_System_getEnvironment(JNIEnv* env, jclass) { + int length; + for (length = 0; environ[length] != 0; ++length); + + jobjectArray stringArray = + env->NewObjectArray(length, env->FindClass("java/lang/String"), + env->NewStringUTF("")); + + for (int i = 0; i < length; i++) { +#ifndef PLATFORM_WINDOWS + jobject varString = env->NewStringUTF(environ[i]); // UTF-8 +#else + jobject varString = env->NewString(environ[i]); // UTF-16 +#endif + env->SetObjectArrayElement(stringArray, i, varString); + } + + return stringArray; +} + extern "C" JNIEXPORT jlong JNICALL Java_java_lang_System_currentTimeMillis(JNIEnv*, jclass) { diff --git a/classpath/java/lang/RuntimePermission.java b/classpath/java/lang/RuntimePermission.java new file mode 100644 index 0000000000..a737444a6f --- /dev/null +++ b/classpath/java/lang/RuntimePermission.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang; + +import java.security.BasicPermission; + +public class RuntimePermission extends BasicPermission { + + public RuntimePermission(String name) { + super(name); + } + +} diff --git a/classpath/java/lang/System.java b/classpath/java/lang/System.java index 9506fb3457..827f357e8b 100644 --- a/classpath/java/lang/System.java +++ b/classpath/java/lang/System.java @@ -17,12 +17,15 @@ import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileDescriptor; +import java.util.Map; +import java.util.Hashtable; import java.util.Properties; public abstract class System { private static final long NanoTimeBaseInMillis = currentTimeMillis(); private static Property properties; + private static Map environment; private static SecurityManager securityManager; // static { @@ -145,4 +148,37 @@ public abstract class System { this.next = next; } } + + public static String getenv(String name) throws NullPointerException, + SecurityException { + if (getSecurityManager() != null) { // is this allowed? + getSecurityManager(). + checkPermission(new RuntimePermission("getenv." + name)); + } + return getenv().get(name); + } + + public static Map getenv() throws SecurityException { + if (getSecurityManager() != null) { // is this allowed? + getSecurityManager().checkPermission(new RuntimePermission("getenv.*")); + } + + if (environment == null) { // build environment table + String[] vars = getEnvironment(); + environment = new Hashtable(vars.length); + for (String var : vars) { // parse name-value pairs + int equalsIndex = var.indexOf('='); + // null names and values are forbidden + if (equalsIndex != -1 && equalsIndex < var.length() - 1) { + environment.put(var.substring(0, equalsIndex), + var.substring(equalsIndex + 1)); + } + } + } + + return environment; + } + + /** Returns the native process environment. */ + private static native String[] getEnvironment(); } From 57092ece0d0e23e4aaccecaee7da80f3e957b05c Mon Sep 17 00:00:00 2001 From: JET Date: Tue, 3 Apr 2012 10:38:48 -0600 Subject: [PATCH 054/140] fixed Win32 getenv implementation --- classpath/java-lang.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 9e99dda6cf..ed422d901b 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -632,13 +632,9 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, } // System.getEnvironment() implementation -// TODO: For Win32, replace usage of deprecated _wenviron -#ifndef PLATFORM_WINDOWS +// TODO: For Win32, replace usage of deprecated _environ and add Unicode +// support (neither of which is likely to be of great importance). extern char** environ; -# else -extern wchar_t** _wenviron; -const wchar_t** environ = _wenviron; -#endif extern "C" JNIEXPORT jobjectArray JNICALL Java_java_lang_System_getEnvironment(JNIEnv* env, jclass) { int length; @@ -649,11 +645,7 @@ Java_java_lang_System_getEnvironment(JNIEnv* env, jclass) { env->NewStringUTF("")); for (int i = 0; i < length; i++) { -#ifndef PLATFORM_WINDOWS - jobject varString = env->NewStringUTF(environ[i]); // UTF-8 -#else - jobject varString = env->NewString(environ[i]); // UTF-16 -#endif + jobject varString = env->NewStringUTF(environ[i]); env->SetObjectArrayElement(stringArray, i, varString); } From 6323c76540f9256bc45cc065634757ddea7015d2 Mon Sep 17 00:00:00 2001 From: JET Date: Wed, 4 Apr 2012 13:13:06 -0600 Subject: [PATCH 055/140] added space before ';' in empty for loop to make Apple happy --- classpath/java-lang.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index ed422d901b..973bd8f89c 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -638,7 +638,7 @@ extern char** environ; extern "C" JNIEXPORT jobjectArray JNICALL Java_java_lang_System_getEnvironment(JNIEnv* env, jclass) { int length; - for (length = 0; environ[length] != 0; ++length); + for (length = 0; environ[length] != 0; ++length) ; jobjectArray stringArray = env->NewObjectArray(length, env->FindClass("java/lang/String"), From 2b4407a962bd6584759f33f4feb25652890c0fdc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 5 Apr 2012 10:04:53 -0600 Subject: [PATCH 056/140] fix iOS build regression --- classpath/java-lang.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 973bd8f89c..bc09cd89fe 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -634,7 +634,13 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, // System.getEnvironment() implementation // TODO: For Win32, replace usage of deprecated _environ and add Unicode // support (neither of which is likely to be of great importance). +#ifdef AVIAN_IOS +namespace { + const char* environ[] = { 0 }; +} +#else extern char** environ; +#endif extern "C" JNIEXPORT jobjectArray JNICALL Java_java_lang_System_getEnvironment(JNIEnv* env, jclass) { int length; From 2fedfdea5be13dfeebf0c615e41b2f15c90834ce Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 6 Apr 2012 16:52:24 -0600 Subject: [PATCH 057/140] fix OS X build regression --- classpath/java-lang.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index bc09cd89fe..855e6b5c60 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -638,6 +638,9 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, namespace { const char* environ[] = { 0 }; } +#elif defined __APPLE__ +# include +# define environ (*_NSGetEnviron()) #else extern char** environ; #endif From ba1f8aa68ec552a7b07d3aa90541b61ff7233f9c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 7 Apr 2012 17:15:59 -0600 Subject: [PATCH 058/140] don't fail build on missing iOS SDK unless actually building for iOS --- makefile | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/makefile b/makefile index 49a2bf0ff6..4a481f9c7b 100755 --- a/makefile +++ b/makefile @@ -322,17 +322,18 @@ ifeq ($(platform),darwin) sdk-dir = $(developer-dir)/Platforms/iPhoneOS.platform/Developer/SDKs - ios-version := $(shell if test -d $(sdk-dir)/iPhoneOS5.1.sdk; then echo 5.1; \ - elif test -d $(sdk-dir)/iPhoneOS5.0.sdk; then echo 5.0; \ - elif test -d $(sdk-dir)/iPhoneOS4.3.sdk; then echo 4.3; \ - elif test -d $(sdk-dir)/iPhoneOS4.2.sdk; then echo 4.2; \ - else echo; fi) - - ifeq ($(ios-version),) - x := $(error "couldn't find SDK for iOS version") - endif - ifeq ($(arch),arm) + ios-version := \ + $(shell if test -d $(sdk-dir)/iPhoneOS5.1.sdk; then echo 5.1; \ + elif test -d $(sdk-dir)/iPhoneOS5.0.sdk; then echo 5.0; \ + elif test -d $(sdk-dir)/iPhoneOS4.3.sdk; then echo 4.3; \ + elif test -d $(sdk-dir)/iPhoneOS4.2.sdk; then echo 4.2; \ + else echo; fi) + + ifeq ($(ios-version),) + x := $(error "couldn't find SDK for iOS version") + endif + ifeq ($(build-arch),powerpc) converter-cflags += -DOPPOSITE_ENDIAN endif From 1120d8f91d976fb89b5b6de50d7ca61f757a403c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 10 Apr 2012 08:18:52 -0600 Subject: [PATCH 059/140] fix ProGuarded openjdk-src build This makes a simple "hello, world!" app work, at least. Further changes may be needed for more sophisticated apps. --- openjdk.pro | 6 ++++++ src/classpath-openjdk.cpp | 10 +++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/openjdk.pro b/openjdk.pro index dd9e07a910..953b5e205b 100644 --- a/openjdk.pro +++ b/openjdk.pro @@ -11,6 +11,7 @@ -keep class java.lang.System { private static void initializeSystemClass(); + public static void setProperties(java.util.Properties); } -keep class java.lang.ClassLoader { @@ -33,6 +34,11 @@ -keep class java.util.Properties { public java.lang.Object setProperty(java.lang.String, java.lang.String); + public java.lang.String getProperty(java.lang.String); + } + +-keep class java.util.Hashtable { + public java.lang.Object remove(java.lang.Object); } -keep class avian.OpenJDK { diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index cbb705d8d9..5b23b4019f 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -1777,10 +1777,14 @@ intercept(Thread* t, object c, const char* name, const char* spec, set(t, runtimeData, MethodRuntimeDataNative, native); } else { - fprintf(stderr, "unable to find %s%s in %s\n", - name, spec, &byteArrayBody(t, className(t, c), 0)); + // If we can't find the method, just ignore it, since ProGuard may + // have stripped it out as unused. Otherwise, the code below can + // be uncommented for debugging purposes. - abort(t); + // fprintf(stderr, "unable to find %s%s in %s\n", + // name, spec, &byteArrayBody(t, className(t, c), 0)); + + // abort(t); } } From 01aa1e2bfdbccf89a3fe220a3603ee6bbc8d47a3 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 11 Apr 2012 11:29:10 -0600 Subject: [PATCH 060/140] add note to readme.txt about using ProGuard with an OpenJDK build --- readme.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index a81b6b2693..03b3b28d04 100644 --- a/readme.txt +++ b/readme.txt @@ -550,7 +550,12 @@ Step 5: Run ProGuard with stage1 as input and stage2 as output. -injars stage1 -outjars stage2 @../vm.pro @hello.pro (note: pass -dontusemixedcaseclassnames to ProGuard when building on -systems with case-insensitive filesystems such as Windows and OS X) +systems with case-insensitive filesystems such as Windows and OS X. +Also, you'll need to add -ignorewarnings if you use the OpenJDK class +library since the openjdk-src build does not include all the JARs from +OpenJDK, and thus ProGuard will not be able to resolve all referenced +classes. If you actually plan to use such classes at runtime, you'll +need to add them to stage1 before running ProGuard.) Step 6: Build the boot and code images. From 07f330967ffde70f01e591dc9d45e734a2b3e9e0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 20 Apr 2012 16:05:04 -0600 Subject: [PATCH 061/140] update readme.txt based on recent feedback from the mailing list This clarifies the need to include both openjdk.pro and vm.pro when building with OpenJDK and ProGuard. It also makes -dontusemixedcaseclassnames the default in the ProGuard command and gives different names to the C++ files used in the embedding and bootimage examples to avoid confusion. --- readme.txt | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/readme.txt b/readme.txt index 03b3b28d04..9b0c1d28e1 100644 --- a/readme.txt +++ b/readme.txt @@ -260,7 +260,9 @@ an LZMA-enabled version: You can reduce the size futher for embedded builds by using ProGuard and the supplied openjdk.pro configuration file (see "Embedding with -ProGuard and a Boot Image" below). Also see app.mk in +ProGuard and a Boot Image" below). Note that you'll still need to use +vm.pro in that case -- openjdk.pro just adds additional constraints +specific to the OpenJDK port. Also see app.mk in git://oss.readytalk.com/avian-swt-examples.git for an example of using Avian, OpenJDK, ProGuard, and UPX in concert. @@ -364,7 +366,7 @@ method. Note the bootJar function, which will be called by the VM to get a handle to the embedded jar. We tell the VM about this jar by setting the boot classpath to "[bootJar]". - $ cat >main.cpp <embedded-jar-main.cpp <main.cpp <bootimage-main.cpp < Date: Tue, 24 Apr 2012 16:17:52 -0600 Subject: [PATCH 062/140] refactor binaryToObject, to better support (eventually) putting symbols for compiled code in objects --- makefile | 34 +- src/binaryToObject/elf.cpp | 606 ++++++++++++++++---------------- src/binaryToObject/endianness.h | 106 ++++-- src/binaryToObject/mach-o.cpp | 568 ++++++++++++++---------------- src/binaryToObject/main.cpp | 117 ++---- src/binaryToObject/pe.cpp | 148 ++++---- src/binaryToObject/tools.cpp | 62 ++++ src/binaryToObject/tools.h | 90 +++++ 8 files changed, 932 insertions(+), 799 deletions(-) create mode 100644 src/binaryToObject/tools.cpp create mode 100644 src/binaryToObject/tools.h diff --git a/makefile b/makefile index 4a481f9c7b..7389967ddb 100755 --- a/makefile +++ b/makefile @@ -334,9 +334,6 @@ ifeq ($(platform),darwin) x := $(error "couldn't find SDK for iOS version") endif - ifeq ($(build-arch),powerpc) - converter-cflags += -DOPPOSITE_ENDIAN - endif flags = -arch armv7 -isysroot \ $(sdk-dir)/iPhoneOS$(ios-version).sdk/ openjdk-extra-cflags += $(flags) @@ -345,10 +342,11 @@ ifeq ($(platform),darwin) lflags += $(flags) endif + ifeq ($(build-arch),powerpc) + converter-cflags += -DBIG_ENDIAN + endif + ifeq ($(arch),powerpc) - ifneq (,$(filter i386 x86_64 arm,$(build-arch))) - converter-cflags += -DOPPOSITE_ENDIAN - endif openjdk-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} asmflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} @@ -356,9 +354,6 @@ ifeq ($(platform),darwin) endif ifeq ($(arch),i386) - ifeq ($(build-arch),powerpc) - converter-cflags += -DOPPOSITE_ENDIAN - endif openjdk-extra-cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} cflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} asmflags += -arch i386 -mmacosx-version-min=${OSX_SDK_VERSION} @@ -366,9 +361,6 @@ ifeq ($(platform),darwin) endif ifeq ($(arch),x86_64) - ifeq ($(build-arch),powerpc) - converter-cflags += -DOPPOSITE_ENDIAN - endif openjdk-extra-cflags += -arch x86_64 cflags += -arch x86_64 asmflags += -arch x86_64 @@ -614,6 +606,9 @@ driver-object = $(build)/main.o driver-dynamic-objects = \ $(build)/main-dynamic.o +gdb-plugin-object = $(build)/gdb-plugin.o +gdb-plugin-source = $(src)/gdb-plugin.cpp + boot-source = $(src)/boot.cpp boot-object = $(build)/boot.o @@ -630,8 +625,8 @@ generator = $(build)/generator converter-objects = \ $(build)/binaryToObject-main.o \ - $(build)/binaryToObject-elf64.o \ - $(build)/binaryToObject-elf32.o \ + $(build)/binaryToObject-tools.o \ + $(build)/binaryToObject-elf.o \ $(build)/binaryToObject-mach-o64.o \ $(build)/binaryToObject-mach-o32.o \ $(build)/binaryToObject-pe.o @@ -828,6 +823,9 @@ $(heapwalk-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) $(driver-object): $(driver-source) $(compile-object) +$(gdb-plugin-object): $(gdb-plugin-source) + $(compile-object) + $(build)/main-dynamic.o: $(driver-source) @echo "compiling $(@)" @mkdir -p $(dir $(@)) @@ -843,11 +841,11 @@ $(boot-javahome-object): $(src)/boot-javahome.cpp $(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp $(build-cxx) $(converter-cflags) -c $(^) -o $(@) -$(build)/binaryToObject-elf64.o: $(src)/binaryToObject/elf.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) +$(build)/binaryToObject-tools.o: $(src)/binaryToObject/tools.cpp + $(build-cxx) $(converter-cflags) -c $(^) -o $(@) -$(build)/binaryToObject-elf32.o: $(src)/binaryToObject/elf.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@) +$(build)/binaryToObject-elf.o: $(src)/binaryToObject/elf.cpp + $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) $(build)/binaryToObject-mach-o64.o: $(src)/binaryToObject/mach-o.cpp $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) diff --git a/src/binaryToObject/elf.cpp b/src/binaryToObject/elf.cpp index bdfdce51c3..51c7d7c587 100644 --- a/src/binaryToObject/elf.cpp +++ b/src/binaryToObject/elf.cpp @@ -8,12 +8,14 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "stdint.h" -#include "stdio.h" -#include "string.h" +#include +#include +#include #include "endianness.h" +#include "tools.h" + #define EI_NIDENT 16 #define EI_MAG0 0 @@ -62,344 +64,340 @@ #define STV_DEFAULT 0 -#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) -#define ELF32_ST_INFO(bind, type) ELF64_ST_INFO((bind), (type)) - -#if (BITS_PER_WORD == 64) -# define FileHeader Elf64_Ehdr -# define SectionHeader Elf64_Shdr -# define Symbol Elf64_Sym -# define Class ELFCLASS64 -# define SYMBOL_INFO ELF64_ST_INFO -#elif (BITS_PER_WORD == 32) -# define FileHeader Elf32_Ehdr -# define SectionHeader Elf32_Shdr -# define Symbol Elf32_Sym -# define Class ELFCLASS32 -# define SYMBOL_INFO ELF32_ST_INFO -#else -# error -#endif +#define SYMBOL_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) #define OSABI ELFOSABI_SYSV namespace { -typedef uint16_t Elf64_Half; -typedef uint32_t Elf64_Word; -typedef uint64_t Elf64_Addr; -typedef uint64_t Elf64_Xword; -typedef uint16_t Elf64_Section; -typedef uint64_t Elf64_Off; +using namespace avian::tools; -struct Elf64_Ehdr { - unsigned char e_ident[EI_NIDENT]; - Elf64_Half e_type; - Elf64_Half e_machine; - Elf64_Word e_version; - Elf64_Addr e_entry; - Elf64_Off e_phoff; - Elf64_Off e_shoff; - Elf64_Word e_flags; - Elf64_Half e_ehsize; - Elf64_Half e_phentsize; - Elf64_Half e_phnum; - Elf64_Half e_shentsize; - Elf64_Half e_shnum; - Elf64_Half e_shstrndx; +template +struct ElfTypes { + typedef uint16_t Half; + typedef uint32_t Word; + typedef AddrTy Addr; + typedef uint64_t Xword; + typedef uint16_t Section; + typedef AddrTy Off; + typedef AddrTy XFlags; + static const unsigned BytesPerWord = sizeof(AddrTy); }; -struct Elf64_Shdr { - Elf64_Word sh_name; - Elf64_Word sh_type; - Elf64_Xword sh_flags; - Elf64_Addr sh_addr; - Elf64_Off sh_offset; - Elf64_Xword sh_size; - Elf64_Word sh_link; - Elf64_Word sh_info; - Elf64_Xword sh_addralign; - Elf64_Xword sh_entsize; -}; +template +struct Symbol_Ty; -struct Elf64_Sym { - Elf64_Word st_name; +template<> +struct Symbol_Ty { + typedef ElfTypes Elf; + + Elf::Word st_name; unsigned char st_info; unsigned char st_other; - Elf64_Section st_shndx; - Elf64_Addr st_value; - Elf64_Xword st_size; + Elf::Section st_shndx; + Elf::Addr st_value; + Elf::Xword st_size; }; -typedef uint16_t Elf32_Half; -typedef uint32_t Elf32_Word; -typedef uint32_t Elf32_Addr; -typedef uint64_t Elf32_Xword; -typedef uint16_t Elf32_Section; -typedef uint32_t Elf32_Off; +template<> +struct Symbol_Ty { + typedef ElfTypes Elf; -struct Elf32_Ehdr { - unsigned char e_ident[EI_NIDENT]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -}; - -struct Elf32_Shdr { - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -}; - -struct Elf32_Sym { - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; + Elf::Word st_name; + Elf::Addr st_value; + Elf::Word st_size; unsigned char st_info; unsigned char st_other; - Elf32_Section st_shndx; + Elf::Section st_shndx; }; -void -writeObject(const uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* sectionName, unsigned sectionFlags, - unsigned alignment, int machine, int encoding) -{ - const unsigned sectionCount = 5; - const unsigned symbolCount = 2; +using avian::endian::Endianness; - const unsigned sectionNameLength = strlen(sectionName) + 1; - const unsigned startNameLength = strlen(startName) + 1; - const unsigned endNameLength = strlen(endName) + 1; +#define V1 Endianness::v1 +#define V2 Endianness::v2 +#define V3 Endianness::v3 +#define V4 Endianness::v4 +#define VANY Endianness::vAny - const char* const sectionStringTableName = ".shstrtab"; - const char* const stringTableName = ".strtab"; - const char* const symbolTableName = ".symtab"; +template +class ElfPlatform : public Platform { +public: - const unsigned sectionStringTableNameLength - = strlen(sectionStringTableName) + 1; - const unsigned stringTableNameLength = strlen(stringTableName) + 1; - const unsigned symbolTableNameLength = strlen(symbolTableName) + 1; + typedef ElfTypes Elf; + static const unsigned Class = Elf::BytesPerWord / 4; - const unsigned nullStringOffset = 0; + struct FileHeader { + unsigned char e_ident[EI_NIDENT]; + typename Elf::Half e_type; + typename Elf::Half e_machine; + typename Elf::Word e_version; + typename Elf::Addr e_entry; + typename Elf::Off e_phoff; + typename Elf::Off e_shoff; + typename Elf::Word e_flags; + typename Elf::Half e_ehsize; + typename Elf::Half e_phentsize; + typename Elf::Half e_phnum; + typename Elf::Half e_shentsize; + typename Elf::Half e_shnum; + typename Elf::Half e_shstrndx; + }; - const unsigned sectionStringTableNameOffset = nullStringOffset + 1; - const unsigned stringTableNameOffset - = sectionStringTableNameOffset + sectionStringTableNameLength; - const unsigned symbolTableNameOffset - = stringTableNameOffset + stringTableNameLength; - const unsigned sectionNameOffset - = symbolTableNameOffset + symbolTableNameLength; - const unsigned sectionStringTableLength - = sectionNameOffset + sectionNameLength; + struct SectionHeader { + typename Elf::Word sh_name; + typename Elf::Word sh_type; + typename Elf::XFlags sh_flags; + typename Elf::Addr sh_addr; + typename Elf::Off sh_offset; + typename Elf::Off sh_size; + typename Elf::Word sh_link; + typename Elf::Word sh_info; + typename Elf::Addr sh_addralign; + typename Elf::Off sh_entsize; + }; - const unsigned startNameOffset = nullStringOffset + 1; - const unsigned endNameOffset = startNameOffset + startNameLength; - const unsigned stringTableLength = endNameOffset + endNameLength; + typedef Symbol_Ty Symbol; - const unsigned bodySectionNumber = 1; - const unsigned sectionStringTableSectionNumber = 2; - const unsigned stringTableSectionNumber = 3; + class ElfObjectWriter : public ObjectWriter { + public: - FileHeader fileHeader; - memset(&fileHeader, 0, sizeof(FileHeader)); - fileHeader.e_ident[EI_MAG0] = V1(ELFMAG0); - fileHeader.e_ident[EI_MAG1] = V1(ELFMAG1); - fileHeader.e_ident[EI_MAG2] = V1(ELFMAG2); - fileHeader.e_ident[EI_MAG3] = V1(ELFMAG3); - fileHeader.e_ident[EI_CLASS] = V1(Class); - fileHeader.e_ident[EI_DATA] = V1(encoding); - fileHeader.e_ident[EI_VERSION] = V1(EV_CURRENT); - fileHeader.e_ident[EI_OSABI] = V1(OSABI); - fileHeader.e_ident[EI_ABIVERSION] = V1(0); - fileHeader.e_type = V2(ET_REL); - fileHeader.e_machine = V2(machine); - fileHeader.e_version = V4(EV_CURRENT); - fileHeader.e_entry = VW(0); - fileHeader.e_phoff = VW(0); - fileHeader.e_shoff = VW(sizeof(FileHeader)); - fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0); - fileHeader.e_ehsize = V2(sizeof(FileHeader)); - fileHeader.e_phentsize = V2(0); - fileHeader.e_phnum = V2(0); - fileHeader.e_shentsize = V2(sizeof(SectionHeader)); - fileHeader.e_shnum = V2(sectionCount); - fileHeader.e_shstrndx = V2(sectionStringTableSectionNumber); + PlatformInfo::Architecture arch; - SectionHeader nullSection; - memset(&nullSection, 0, sizeof(SectionHeader)); + ElfObjectWriter(PlatformInfo::Architecture arch): + arch(arch) {} - SectionHeader bodySection; - bodySection.sh_name = V4(sectionNameOffset); - bodySection.sh_type = V4(SHT_PROGBITS); - bodySection.sh_flags = VW(sectionFlags); - bodySection.sh_addr = VW(0); - unsigned bodySectionOffset - = sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount); - bodySection.sh_offset = VW(bodySectionOffset); - unsigned bodySectionSize = size; - bodySection.sh_size = VW(bodySectionSize); - bodySection.sh_link = V4(0); - bodySection.sh_info = V4(0); - bodySection.sh_addralign = VW(alignment); - bodySection.sh_entsize = VW(0); + void writeObject(const uint8_t* data, unsigned size, FILE* out, + const char* startName, const char* endName, + const char* sectionName, unsigned sectionFlags, + unsigned alignment, int machine, int encoding) + { + const unsigned sectionCount = 5; + const unsigned symbolCount = 2; - SectionHeader sectionStringTableSection; - sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset); - sectionStringTableSection.sh_type = V4(SHT_STRTAB); - sectionStringTableSection.sh_flags = VW(0); - sectionStringTableSection.sh_addr = VW(0); - unsigned sectionStringTableSectionOffset - = bodySectionOffset + bodySectionSize; - sectionStringTableSection.sh_offset = VW(sectionStringTableSectionOffset); - unsigned sectionStringTableSectionSize = sectionStringTableLength; - sectionStringTableSection.sh_size = VW(sectionStringTableSectionSize); - sectionStringTableSection.sh_link = V4(0); - sectionStringTableSection.sh_info = V4(0); - sectionStringTableSection.sh_addralign = VW(1); - sectionStringTableSection.sh_entsize = VW(0); + const unsigned sectionNameLength = strlen(sectionName) + 1; + const unsigned startNameLength = strlen(startName) + 1; + const unsigned endNameLength = strlen(endName) + 1; - SectionHeader stringTableSection; - stringTableSection.sh_name = V4(stringTableNameOffset); - stringTableSection.sh_type = V4(SHT_STRTAB); - stringTableSection.sh_flags = VW(0); - stringTableSection.sh_addr = VW(0); - unsigned stringTableSectionOffset - = sectionStringTableSectionOffset + sectionStringTableSectionSize; - stringTableSection.sh_offset = VW(stringTableSectionOffset); - unsigned stringTableSectionSize = stringTableLength; - stringTableSection.sh_size = VW(stringTableSectionSize); - stringTableSection.sh_link = V4(0); - stringTableSection.sh_info = V4(0); - stringTableSection.sh_addralign = VW(1); - stringTableSection.sh_entsize = VW(0); + const char* const sectionStringTableName = ".shstrtab"; + const char* const stringTableName = ".strtab"; + const char* const symbolTableName = ".symtab"; - SectionHeader symbolTableSection; - symbolTableSection.sh_name = V4(symbolTableNameOffset); - symbolTableSection.sh_type = V4(SHT_SYMTAB); - symbolTableSection.sh_flags = VW(0); - symbolTableSection.sh_addr = VW(0); - unsigned symbolTableSectionOffset - = stringTableSectionOffset + stringTableSectionSize; - symbolTableSection.sh_offset = VW(symbolTableSectionOffset); - unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount; - symbolTableSection.sh_size = VW(symbolTableSectionSize); - symbolTableSection.sh_link = V4(stringTableSectionNumber); - symbolTableSection.sh_info = V4(0); - symbolTableSection.sh_addralign = VW(BITS_PER_WORD / 8); - symbolTableSection.sh_entsize = VW(sizeof(Symbol)); + const unsigned sectionStringTableNameLength + = strlen(sectionStringTableName) + 1; + const unsigned stringTableNameLength = strlen(stringTableName) + 1; + const unsigned symbolTableNameLength = strlen(symbolTableName) + 1; - Symbol startSymbol; - startSymbol.st_name = V4(startNameOffset); - startSymbol.st_value = VW(0); - startSymbol.st_size = VW(0); - startSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); - startSymbol.st_other = V1(STV_DEFAULT); - startSymbol.st_shndx = V2(bodySectionNumber); + const unsigned nullStringOffset = 0; - Symbol endSymbol; - endSymbol.st_name = V4(endNameOffset); - endSymbol.st_value = VW(size); - endSymbol.st_size = VW(0); - endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); - endSymbol.st_other = V1(STV_DEFAULT); - endSymbol.st_shndx = V2(bodySectionNumber); + const unsigned sectionStringTableNameOffset = nullStringOffset + 1; + const unsigned stringTableNameOffset + = sectionStringTableNameOffset + sectionStringTableNameLength; + const unsigned symbolTableNameOffset + = stringTableNameOffset + stringTableNameLength; + const unsigned sectionNameOffset + = symbolTableNameOffset + symbolTableNameLength; + const unsigned sectionStringTableLength + = sectionNameOffset + sectionNameLength; - fwrite(&fileHeader, 1, sizeof(fileHeader), out); - fwrite(&nullSection, 1, sizeof(nullSection), out); - fwrite(&bodySection, 1, sizeof(bodySection), out); - fwrite(§ionStringTableSection, 1, sizeof(sectionStringTableSection), - out); - fwrite(&stringTableSection, 1, sizeof(stringTableSection), out); - fwrite(&symbolTableSection, 1, sizeof(symbolTableSection), out); + const unsigned startNameOffset = nullStringOffset + 1; + const unsigned endNameOffset = startNameOffset + startNameLength; + const unsigned stringTableLength = endNameOffset + endNameLength; - fwrite(data, 1, size, out); + const unsigned bodySectionNumber = 1; + const unsigned sectionStringTableSectionNumber = 2; + const unsigned stringTableSectionNumber = 3; - fputc(0, out); - fwrite(sectionStringTableName, 1, sectionStringTableNameLength, out); - fwrite(stringTableName, 1, stringTableNameLength, out); - fwrite(symbolTableName, 1, symbolTableNameLength, out); - fwrite(sectionName, 1, sectionNameLength, out); + FileHeader fileHeader; + memset(&fileHeader, 0, sizeof(FileHeader)); + fileHeader.e_ident[EI_MAG0] = V1(ELFMAG0); + fileHeader.e_ident[EI_MAG1] = V1(ELFMAG1); + fileHeader.e_ident[EI_MAG2] = V1(ELFMAG2); + fileHeader.e_ident[EI_MAG3] = V1(ELFMAG3); + fileHeader.e_ident[EI_CLASS] = V1(Class); + fileHeader.e_ident[EI_DATA] = V1(encoding); + fileHeader.e_ident[EI_VERSION] = V1(EV_CURRENT); + fileHeader.e_ident[EI_OSABI] = V1(OSABI); + fileHeader.e_ident[EI_ABIVERSION] = V1(0); + fileHeader.e_type = V2(ET_REL); + fileHeader.e_machine = V2(machine); + fileHeader.e_version = V4(EV_CURRENT); + fileHeader.e_entry = VANY(static_cast(0)); + fileHeader.e_phoff = VANY(static_cast(0)); + fileHeader.e_shoff = VANY(static_cast(sizeof(FileHeader))); + fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0); + fileHeader.e_ehsize = V2(sizeof(FileHeader)); + fileHeader.e_phentsize = V2(0); + fileHeader.e_phnum = V2(0); + fileHeader.e_shentsize = V2(sizeof(SectionHeader)); + fileHeader.e_shnum = V2(sectionCount); + fileHeader.e_shstrndx = V2(sectionStringTableSectionNumber); - fputc(0, out); - fwrite(startName, 1, startNameLength, out); - fwrite(endName, 1, endNameLength, out); + SectionHeader nullSection; + memset(&nullSection, 0, sizeof(SectionHeader)); + + SectionHeader bodySection; + bodySection.sh_name = V4(sectionNameOffset); + bodySection.sh_type = V4(SHT_PROGBITS); + bodySection.sh_flags = VANY(static_cast(sectionFlags)); + bodySection.sh_addr = VANY(static_cast(0)); + unsigned bodySectionOffset + = sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount); + bodySection.sh_offset = VANY(static_cast(bodySectionOffset)); + unsigned bodySectionSize = size; + bodySection.sh_size = VANY(static_cast(bodySectionSize)); + bodySection.sh_link = V4(0); + bodySection.sh_info = V4(0); + bodySection.sh_addralign = VANY(static_cast(alignment)); + bodySection.sh_entsize = VANY(static_cast(0)); + + SectionHeader sectionStringTableSection; + sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset); + sectionStringTableSection.sh_type = V4(SHT_STRTAB); + sectionStringTableSection.sh_flags = VANY(static_cast(0)); + sectionStringTableSection.sh_addr = VANY(static_cast(0)); + unsigned sectionStringTableSectionOffset + = bodySectionOffset + bodySectionSize; + sectionStringTableSection.sh_offset = VANY(static_cast(sectionStringTableSectionOffset)); + unsigned sectionStringTableSectionSize = sectionStringTableLength; + sectionStringTableSection.sh_size = VANY(static_cast(sectionStringTableSectionSize)); + sectionStringTableSection.sh_link = V4(0); + sectionStringTableSection.sh_info = V4(0); + sectionStringTableSection.sh_addralign = VANY(static_cast(1)); + sectionStringTableSection.sh_entsize = VANY(static_cast(0)); + + SectionHeader stringTableSection; + stringTableSection.sh_name = V4(stringTableNameOffset); + stringTableSection.sh_type = V4(SHT_STRTAB); + stringTableSection.sh_flags = VANY(static_cast(0)); + stringTableSection.sh_addr = VANY(static_cast(0)); + unsigned stringTableSectionOffset + = sectionStringTableSectionOffset + sectionStringTableSectionSize; + stringTableSection.sh_offset = VANY(static_cast(stringTableSectionOffset)); + unsigned stringTableSectionSize = stringTableLength; + stringTableSection.sh_size = VANY(static_cast(stringTableSectionSize)); + stringTableSection.sh_link = V4(0); + stringTableSection.sh_info = V4(0); + stringTableSection.sh_addralign = VANY(static_cast(1)); + stringTableSection.sh_entsize = VANY(static_cast(0)); + + SectionHeader symbolTableSection; + symbolTableSection.sh_name = V4(symbolTableNameOffset); + symbolTableSection.sh_type = V4(SHT_SYMTAB); + symbolTableSection.sh_flags = VANY(static_cast(0)); + symbolTableSection.sh_addr = VANY(static_cast(0)); + unsigned symbolTableSectionOffset + = stringTableSectionOffset + stringTableSectionSize; + symbolTableSection.sh_offset = VANY(static_cast(symbolTableSectionOffset)); + unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount; + symbolTableSection.sh_size = VANY(static_cast(symbolTableSectionSize)); + symbolTableSection.sh_link = V4(stringTableSectionNumber); + symbolTableSection.sh_info = V4(0); + symbolTableSection.sh_addralign = VANY(static_cast(Elf::BytesPerWord)); + symbolTableSection.sh_entsize = VANY(static_cast(sizeof(Symbol))); + + Symbol startSymbol; + startSymbol.st_name = V4(startNameOffset); + startSymbol.st_value = VANY(static_cast(0)); + startSymbol.st_size = VANY(static_cast(0)); + startSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); + startSymbol.st_other = V1(STV_DEFAULT); + startSymbol.st_shndx = V2(bodySectionNumber); + + Symbol endSymbol; + endSymbol.st_name = V4(endNameOffset); + endSymbol.st_value = VANY(static_cast(size)); + endSymbol.st_size = VANY(static_cast(0)); + endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); + endSymbol.st_other = V1(STV_DEFAULT); + endSymbol.st_shndx = V2(bodySectionNumber); + + fwrite(&fileHeader, 1, sizeof(fileHeader), out); + fwrite(&nullSection, 1, sizeof(nullSection), out); + fwrite(&bodySection, 1, sizeof(bodySection), out); + fwrite(§ionStringTableSection, 1, sizeof(sectionStringTableSection), + out); + fwrite(&stringTableSection, 1, sizeof(stringTableSection), out); + fwrite(&symbolTableSection, 1, sizeof(symbolTableSection), out); + + fwrite(data, 1, size, out); + + fputc(0, out); + fwrite(sectionStringTableName, 1, sectionStringTableNameLength, out); + fwrite(stringTableName, 1, stringTableNameLength, out); + fwrite(symbolTableName, 1, symbolTableNameLength, out); + fwrite(sectionName, 1, sectionNameLength, out); + + fputc(0, out); + fwrite(startName, 1, startNameLength, out); + fwrite(endName, 1, endNameLength, out); + + fwrite(&startSymbol, 1, sizeof(startSymbol), out); + fwrite(&endSymbol, 1, sizeof(endSymbol), out); + } + + virtual bool write(uint8_t* data, size_t size, FILE* out, + const char* startName, const char* endName, + unsigned alignment, unsigned accessFlags) + { + int machine; + int encoding; + if (arch == PlatformInfo::x86_64) { + machine = EM_X86_64; + encoding = ELFDATA2LSB; + } else if (arch == PlatformInfo::x86) { + machine = EM_386; + encoding = ELFDATA2LSB; + } else if (arch == PlatformInfo::Arm) { + machine = EM_ARM; + encoding = ELFDATA2LSB; + } else if (arch == PlatformInfo::PowerPC) { + machine = EM_PPC; + encoding = ELFDATA2MSB; + } else { + fprintf(stderr, "unsupported architecture: %s\n", arch); + return false; + } + + const char* sectionName; + unsigned sectionFlags = SHF_ALLOC; + if (accessFlags & Writable) { + if (accessFlags & Executable) { + sectionName = ".rwx"; + sectionFlags |= SHF_WRITE | SHF_EXECINSTR; + } else { + sectionName = ".data"; + sectionFlags |= SHF_WRITE; + } + } else if (accessFlags & Executable) { + sectionName = ".text"; + sectionFlags |= SHF_EXECINSTR; + } else { + sectionName = ".rodata"; + } + + writeObject(data, size, out, startName, endName, sectionName, sectionFlags, + alignment, machine, encoding); + + return true; + } + + virtual void dispose() { + delete this; + } + }; + + ElfPlatform(PlatformInfo::Architecture arch): + Platform(PlatformInfo(PlatformInfo::Linux, arch)) {} + + virtual ObjectWriter* makeObjectWriter() { + return new ElfObjectWriter(info.arch); + } +}; + +ElfPlatform elfx86Platform(PlatformInfo::x86); +ElfPlatform elfArmPlatform(PlatformInfo::Arm); +ElfPlatform elfPowerPCPlatform(PlatformInfo::PowerPC); +ElfPlatform elfx86_64Platform(PlatformInfo::x86_64); - fwrite(&startSymbol, 1, sizeof(startSymbol), out); - fwrite(&endSymbol, 1, sizeof(endSymbol), out); -} } // namespace - -#define MACRO_MAKE_NAME(a, b, c) a##b##c -#define MAKE_NAME(a, b, c) MACRO_MAKE_NAME(a, b, c) - -namespace binaryToObject { - -bool -MAKE_NAME(writeElf, BITS_PER_WORD, Object) - (uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* architecture, unsigned alignment, - bool writable, bool executable) -{ - int machine; - int encoding; - if (strcmp(architecture, "x86_64") == 0) { - machine = EM_X86_64; - encoding = ELFDATA2LSB; - } else if (strcmp(architecture, "i386") == 0) { - machine = EM_386; - encoding = ELFDATA2LSB; - } else if (strcmp(architecture, "arm") == 0) { - machine = EM_ARM; - encoding = ELFDATA2LSB; - } else if (strcmp(architecture, "powerpc") == 0) { - machine = EM_PPC; - encoding = ELFDATA2MSB; - } else { - fprintf(stderr, "unsupported architecture: %s\n", architecture); - return false; - } - - const char* sectionName; - unsigned sectionFlags = SHF_ALLOC; - if (writable) { - if (executable) { - sectionName = ".rwx"; - sectionFlags |= SHF_WRITE | SHF_EXECINSTR; - } else { - sectionName = ".data"; - sectionFlags |= SHF_WRITE; - } - } else if (executable) { - sectionName = ".text"; - sectionFlags |= SHF_EXECINSTR; - } else { - sectionName = ".rodata"; - } - - writeObject(data, size, out, startName, endName, sectionName, sectionFlags, - alignment, machine, encoding); - - return true; -} - -} // namespace binaryToObject diff --git a/src/binaryToObject/endianness.h b/src/binaryToObject/endianness.h index 46cfcd8b46..36c5675bac 100644 --- a/src/binaryToObject/endianness.h +++ b/src/binaryToObject/endianness.h @@ -1,38 +1,80 @@ -#ifndef ENDIANNESS_H -#define ENDIANNESS_H +/* Copyright (c) 2008-2011, Avian Contributors -#define V1(v) (v) + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. -#ifdef OPPOSITE_ENDIAN -# define V2(v) \ - ((((v) >> 8) & 0xFF) | \ - (((v) << 8))) -# define V4(v) \ - ((((v) >> 24) & 0x000000FF) | \ - (((v) >> 8) & 0x0000FF00) | \ - (((v) << 8) & 0x00FF0000) | \ - (((v) << 24))) -# define V8(v) \ - (((static_cast(v) >> 56) & UINT64_C(0x00000000000000FF)) | \ - ((static_cast(v) >> 40) & UINT64_C(0x000000000000FF00)) | \ - ((static_cast(v) >> 24) & UINT64_C(0x0000000000FF0000)) | \ - ((static_cast(v) >> 8) & UINT64_C(0x00000000FF000000)) | \ - ((static_cast(v) << 8) & UINT64_C(0x000000FF00000000)) | \ - ((static_cast(v) << 24) & UINT64_C(0x0000FF0000000000)) | \ - ((static_cast(v) << 40) & UINT64_C(0x00FF000000000000)) | \ - ((static_cast(v) << 56))) + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_ENDIANNESS_H +#define AVIAN_ENDIANNESS_H + +namespace avian { + +namespace endian { + +#ifndef BIG_ENDIAN +const bool LittleEndian = true; #else -# define V2(v) (v) -# define V4(v) (v) -# define V8(v) (v) +const bool LittleEndian = false; #endif -#if (BITS_PER_WORD == 64) -# define VW(v) V8(v) -#elif (BITS_PER_WORD == 32) -# define VW(v) V4(v) -#else -# error -#endif +template +class Endianness { +public: + static inline uint8_t v1(uint8_t v) { + return v; + } -#endif//ENDIANNESS_H + static inline uint16_t v2(uint16_t v) { + if(LittleEndian == TargetLittleEndian) { + return v; + } else { + return ((v >> 8) & 0xFF) | (v << 8); + } + } + + static inline uint32_t v4(uint32_t v) { + if(LittleEndian == TargetLittleEndian) { + return v; + } else { + return + ((v >> 24) & 0x000000FF) | + ((v >> 8) & 0x0000FF00) | + ((v << 8) & 0x00FF0000) | + ((v << 24)); + } + } + + static inline uint32_t vAny(uint32_t v) { + return v4(v); + } + + static inline uint64_t v8(uint64_t v) { + if(LittleEndian == TargetLittleEndian) { + return v; + } else { + return + ((static_cast(v) >> 56) & UINT64_C(0x00000000000000FF)) | + ((static_cast(v) >> 40) & UINT64_C(0x000000000000FF00)) | + ((static_cast(v) >> 24) & UINT64_C(0x0000000000FF0000)) | + ((static_cast(v) >> 8) & UINT64_C(0x00000000FF000000)) | + ((static_cast(v) << 8) & UINT64_C(0x000000FF00000000)) | + ((static_cast(v) << 24) & UINT64_C(0x0000FF0000000000)) | + ((static_cast(v) << 40) & UINT64_C(0x00FF000000000000)) | + ((static_cast(v) << 56)); + } + } + + static inline uint64_t vAny(uint64_t v) { + return v8(v); + } +}; + +} // namespace endian + +} // namespace avian + +#endif // AVIAN_ENDIANNESS_H diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index 8b37e85aaf..6aab90a0b1 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -8,19 +8,19 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "stdint.h" -#include "stdio.h" -#include "string.h" +#include +#include +#include #include "endianness.h" +#include "tools.h" + #define MH_MAGIC_64 0xfeedfacf #define MH_MAGIC 0xfeedface #define MH_OBJECT 1 -#define LC_SEGMENT_64 0x19 -#define LC_SEGMENT 1 #define LC_SYMTAB 2 #define S_REGULAR 0 @@ -40,322 +40,294 @@ #define CPU_SUBTYPE_POWERPC_ALL 0 #define CPU_SUBTYPE_ARM_V7 9 -#if (BITS_PER_WORD == 64) -# define Magic MH_MAGIC_64 -# define Segment LC_SEGMENT_64 -# define FileHeader mach_header_64 -# define SegmentCommand segment_command_64 -# define Section section_64 -# define NList struct nlist_64 -#elif (BITS_PER_WORD == 32) -# define Magic MH_MAGIC -# define Segment LC_SEGMENT -# define FileHeader mach_header -# define SegmentCommand segment_command -# define Section section -# define NList struct nlist -#else -# error -#endif - namespace { +using namespace avian::tools; + typedef int cpu_type_t; typedef int cpu_subtype_t; typedef int vm_prot_t; -struct mach_header_64 { - uint32_t magic; - cpu_type_t cputype; - cpu_subtype_t cpusubtype; - uint32_t filetype; - uint32_t ncmds; - uint32_t sizeofcmds; - uint32_t flags; - uint32_t reserved; -}; +using avian::endian::Endianness; -struct segment_command_64 { - uint32_t cmd; - uint32_t cmdsize; - char segname[16]; - uint64_t vmaddr; - uint64_t vmsize; - uint64_t fileoff; - uint64_t filesize; - vm_prot_t maxprot; - vm_prot_t initprot; - uint32_t nsects; - uint32_t flags; -}; +#define V1 Endianness::v1 +#define V2 Endianness::v2 +#define V3 Endianness::v3 +#define V4 Endianness::v4 +#define VANY Endianness::vAny -struct section_64 { - char sectname[16]; - char segname[16]; - uint64_t addr; - uint64_t size; - uint32_t offset; - uint32_t align; - uint32_t reloff; - uint32_t nreloc; - uint32_t flags; - uint32_t reserved1; - uint32_t reserved2; - uint32_t reserved3; -}; +template +class MachOPlatform : public Platform { +public: -struct nlist_64 { - union { - uint32_t n_strx; - } n_un; - uint8_t n_type; - uint8_t n_sect; - uint16_t n_desc; - uint64_t n_value; -}; + struct FileHeader { + uint32_t magic; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; -struct mach_header { - uint32_t magic; - cpu_type_t cputype; - cpu_subtype_t cpusubtype; - uint32_t filetype; - uint32_t ncmds; - uint32_t sizeofcmds; - uint32_t flags; -}; - -struct segment_command { - uint32_t cmd; - uint32_t cmdsize; - char segname[16]; - uint32_t vmaddr; - uint32_t vmsize; - uint32_t fileoff; - uint32_t filesize; - vm_prot_t maxprot; - vm_prot_t initprot; - uint32_t nsects; - uint32_t flags; -}; - -struct section { - char sectname[16]; - char segname[16]; - uint32_t addr; - uint32_t size; - uint32_t offset; - uint32_t align; - uint32_t reloff; - uint32_t nreloc; - uint32_t flags; - uint32_t reserved1; - uint32_t reserved2; -}; - -struct symtab_command { - uint32_t cmd; - uint32_t cmdsize; - uint32_t symoff; - uint32_t nsyms; - uint32_t stroff; - uint32_t strsize; -}; - -struct nlist { - union { - int32_t n_strx; - } n_un; - uint8_t n_type; - uint8_t n_sect; - int16_t n_desc; - uint32_t n_value; -}; - -inline unsigned -pad(unsigned n) -{ - return (n + ((BITS_PER_WORD / 8) - 1)) & ~((BITS_PER_WORD / 8) - 1); -} - -inline unsigned -log(unsigned n) -{ - unsigned r = 0; - for (unsigned i = 1; i < n; ++r) i <<= 1; - return r; -} - -void -writeObject(const uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* segmentName, const char* sectionName, - unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType) -{ - unsigned startNameLength = strlen(startName) + 1; - unsigned endNameLength = strlen(endName) + 1; - - FileHeader header = { - V4(Magic), // magic - V4(cpuType), - V4(cpuSubType), - V4(MH_OBJECT), // filetype, - V4(2), // ncmds - V4(sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command)), // sizeofcmds - V4(0) // flags + union { + uint32_t flags; + AddrTy flagsAndMaybeReserved; + }; }; - SegmentCommand segment = { - V4(Segment), // cmd - V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize - "", // segname - VW(0), // vmaddr - VW(pad(size)), // vmsize - VW(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command)), // fileoff - VW(pad(size)), // filesize - V4(7), // maxprot - V4(7), // initprot - V4(1), // nsects - V4(0) // flags + + struct SegmentCommand { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + AddrTy vmaddr; + AddrTy vmsize; + AddrTy fileoff; + AddrTy filesize; + vm_prot_t maxprot; + vm_prot_t initprot; + uint32_t nsects; + uint32_t flags; }; - strncpy(segment.segname, segmentName, sizeof(segment.segname)); - - Section sect = { - "", // sectname - "", // segname - VW(0), // addr - VW(pad(size)), // size - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command)), // offset - V4(log(alignment)), // align - V4(0), // reloff - V4(0), // nreloc - V4(S_REGULAR), // flags - V4(0), // reserved1 - V4(0), // reserved2 + struct Section { + char sectname[16]; + char segname[16]; + AddrTy addr; + AddrTy size; + uint32_t offset; + uint32_t align; + uint32_t reloff; + uint32_t nreloc; + uint32_t flags; + uint32_t reserved1; + AddrTy reserved2AndMaybe3; }; - strncpy(sect.segname, segmentName, sizeof(sect.segname)); - strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); - - symtab_command symbolTable = { - V4(LC_SYMTAB), // cmd - V4(sizeof(symtab_command)), // cmdsize - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command) - + pad(size)), // symoff - V4(2), // nsyms - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(symtab_command) - + pad(size) - + (sizeof(NList) * 2)), // stroff - V4(1 + startNameLength + endNameLength), // strsize + struct NList { + union { + uint32_t n_strx; + } n_un; + uint8_t n_type; + uint8_t n_sect; + uint16_t n_desc; + AddrTy n_value; }; - NList symbolList[] = { + struct SymtabCommand { + uint32_t cmd; + uint32_t cmdsize; + uint32_t symoff; + uint32_t nsyms; + uint32_t stroff; + uint32_t strsize; + }; + + static const unsigned BytesPerWord = sizeof(AddrTy); + static const unsigned Segment = BytesPerWord == 8 ? 0x19 : 1; + static const unsigned Magic = BytesPerWord == 8 ? 0xfeedfacf : 0xfeedface; + + static inline unsigned + pad(unsigned n) + { + return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1); + } + + static inline unsigned + log(unsigned n) + { + unsigned r = 0; + for (unsigned i = 1; i < n; ++r) i <<= 1; + return r; + } + + class MachOObjectWriter : public ObjectWriter { + public: + + PlatformInfo::Architecture arch; + + MachOObjectWriter(PlatformInfo::Architecture arch): + arch(arch) {} + + void writeObject(const uint8_t* data, unsigned size, FILE* out, + const char* startName, const char* endName, + const char* segmentName, const char* sectionName, + unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType) { - V4(1), // n_un - V1(N_SECT | N_EXT), // n_type - V1(1), // n_sect - V2(0), // n_desc - VW(0) // n_value - }, + unsigned startNameLength = strlen(startName) + 1; + unsigned endNameLength = strlen(endName) + 1; + + FileHeader header = { + V4(Magic), // magic + V4(cpuType), + V4(cpuSubType), + V4(MH_OBJECT), // filetype, + V4(2), // ncmds + V4(sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand)), // sizeofcmds + V4(0) // flags + }; + + SegmentCommand segment = { + V4(Segment), // cmd + V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize + "", // segname + VANY(static_cast(0)), // vmaddr + VANY(static_cast(pad(size))), // vmsize + VANY(static_cast(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand))), // fileoff + VANY(static_cast(pad(size))), // filesize + V4(7), // maxprot + V4(7), // initprot + V4(1), // nsects + V4(0) // flags + }; + + strncpy(segment.segname, segmentName, sizeof(segment.segname)); + + Section sect = { + "", // sectname + "", // segname + VANY(static_cast(0)), // addr + VANY(static_cast(pad(size))), // size + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand)), // offset + V4(log(alignment)), // align + V4(0), // reloff + V4(0), // nreloc + V4(S_REGULAR), // flags + V4(0), // reserved1 + V4(0), // reserved2 + }; + + strncpy(sect.segname, segmentName, sizeof(sect.segname)); + strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); + + SymtabCommand symbolTable = { + V4(LC_SYMTAB), // cmd + V4(sizeof(SymtabCommand)), // cmdsize + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand) + + pad(size)), // symoff + V4(2), // nsyms + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand) + + pad(size) + + (sizeof(NList) * 2)), // stroff + V4(1 + startNameLength + endNameLength), // strsize + }; + + NList symbolList[] = { + { + V4(1), // n_un + V1(N_SECT | N_EXT), // n_type + V1(1), // n_sect + V2(0), // n_desc + VANY(static_cast(0)) // n_value + }, + { + V4(1 + startNameLength), // n_un + V1(N_SECT | N_EXT), // n_type + V1(1), // n_sect + V2(0), // n_desc + VANY(static_cast(size)) // n_value + } + }; + + fwrite(&header, 1, sizeof(header), out); + fwrite(&segment, 1, sizeof(segment), out); + fwrite(§, 1, sizeof(sect), out); + fwrite(&symbolTable, 1, sizeof(symbolTable), out); + + fwrite(data, 1, size, out); + for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out); + + fwrite(&symbolList, 1, sizeof(symbolList), out); + + fputc(0, out); + fwrite(startName, 1, startNameLength, out); + fwrite(endName, 1, endNameLength, out); + } + + virtual bool write(uint8_t* data, size_t size, FILE* out, + const char* startName, const char* endName, + unsigned alignment, unsigned accessFlags) { - V4(1 + startNameLength), // n_un - V1(N_SECT | N_EXT), // n_type - V1(1), // n_sect - V2(0), // n_desc - VW(size) // n_value + + cpu_type_t cpuType; + cpu_subtype_t cpuSubType; + if (arch == PlatformInfo::x86_64) { + cpuType = CPU_TYPE_X86_64; + cpuSubType = CPU_SUBTYPE_X86_64_ALL; + } else if (arch == PlatformInfo::x86) { + cpuType = CPU_TYPE_I386; + cpuSubType = CPU_SUBTYPE_I386_ALL; + } else if (arch == PlatformInfo::PowerPC) { + cpuType = CPU_TYPE_POWERPC; + cpuSubType = CPU_SUBTYPE_POWERPC_ALL; + } else if (arch == PlatformInfo::Arm) { + cpuType = CPU_TYPE_ARM; + cpuSubType = CPU_SUBTYPE_ARM_V7; + } else { + fprintf(stderr, "unsupported architecture: %d\n", arch); + return false; + } + + const char* segmentName; + const char* sectionName; + if (accessFlags & Writable) { + if (accessFlags & Executable) { + segmentName = "__RWX"; + sectionName = "__rwx"; + } else { + segmentName = "__DATA"; + sectionName = "__data"; + } + } else { + segmentName = "__TEXT"; + sectionName = "__text"; + } + + unsigned startNameLength = strlen(startName); + char myStartName[startNameLength + 2]; + myStartName[0] = '_'; + memcpy(myStartName + 1, startName, startNameLength + 1); + + unsigned endNameLength = strlen(endName); + char myEndName[endNameLength + 2]; + myEndName[0] = '_'; + memcpy(myEndName + 1, endName, endNameLength + 1); + + writeObject(data, size, out, myStartName, myEndName, segmentName, + sectionName, alignment, cpuType, cpuSubType); + + return true; + } + + virtual void dispose() { + delete this; } }; + + MachOPlatform(PlatformInfo::Architecture arch): + Platform(PlatformInfo(PlatformInfo::Darwin, arch)) {} - fwrite(&header, 1, sizeof(header), out); - fwrite(&segment, 1, sizeof(segment), out); - fwrite(§, 1, sizeof(sect), out); - fwrite(&symbolTable, 1, sizeof(symbolTable), out); + virtual ObjectWriter* makeObjectWriter() { + return new MachOObjectWriter(info.arch); + } +}; - fwrite(data, 1, size, out); - for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out); - - fwrite(&symbolList, 1, sizeof(symbolList), out); - - fputc(0, out); - fwrite(startName, 1, startNameLength, out); - fwrite(endName, 1, endNameLength, out); -} +MachOPlatform darwinx86Platform(PlatformInfo::x86); +MachOPlatform darwinArmPlatform(PlatformInfo::Arm); +MachOPlatform darwinPowerPCPlatform(PlatformInfo::PowerPC); +MachOPlatform darwinx86_64Platform(PlatformInfo::x86_64); } // namespace - -#define MACRO_MAKE_NAME(a, b, c) a##b##c -#define MAKE_NAME(a, b, c) MACRO_MAKE_NAME(a, b, c) - -namespace binaryToObject { - -bool -MAKE_NAME(writeMachO, BITS_PER_WORD, Object) - (uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* architecture, unsigned alignment, - bool writable, bool executable) -{ - cpu_type_t cpuType; - cpu_subtype_t cpuSubType; - if (strcmp(architecture, "x86_64") == 0) { - cpuType = CPU_TYPE_X86_64; - cpuSubType = CPU_SUBTYPE_X86_64_ALL; - } else if (strcmp(architecture, "i386") == 0) { - cpuType = CPU_TYPE_I386; - cpuSubType = CPU_SUBTYPE_I386_ALL; - } else if (strcmp(architecture, "powerpc") == 0) { - cpuType = CPU_TYPE_POWERPC; - cpuSubType = CPU_SUBTYPE_POWERPC_ALL; - } else if (strcmp(architecture, "arm") == 0) { - cpuType = CPU_TYPE_ARM; - cpuSubType = CPU_SUBTYPE_ARM_V7; - } else { - fprintf(stderr, "unsupported architecture: %s\n", architecture); - return false; - } - - const char* segmentName; - const char* sectionName; - if (writable) { - if (executable) { - segmentName = "__RWX"; - sectionName = "__rwx"; - } else { - segmentName = "__DATA"; - sectionName = "__data"; - } - } else { - segmentName = "__TEXT"; - sectionName = "__text"; - } - - unsigned startNameLength = strlen(startName); - char myStartName[startNameLength + 2]; - myStartName[0] = '_'; - memcpy(myStartName + 1, startName, startNameLength + 1); - - unsigned endNameLength = strlen(endName); - char myEndName[endNameLength + 2]; - myEndName[0] = '_'; - memcpy(myEndName + 1, endName, endNameLength + 1); - - writeObject(data, size, out, myStartName, myEndName, segmentName, - sectionName, alignment, cpuType, cpuSubType); - - return true; -} - -} // namespace binaryToObject diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index ffc6f1e017..6dcdf9734d 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -8,110 +8,61 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "stdint.h" -#include "stdio.h" -#include "stdlib.h" -#include "string.h" +#include +#include +#include +#include -#include "sys/stat.h" +#include #ifdef WIN32 #include #else -#include "sys/mman.h" +#include #endif -#include "fcntl.h" -#include "unistd.h" +#include +#include -namespace binaryToObject { +#include "tools.h" -bool -writeElf64Object(uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* architecture, unsigned alignment, bool writable, - bool executable); +extern "C" +void __cxa_pure_virtual() { + abort(); +} -bool -writeElf32Object(uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* architecture, unsigned alignment, bool writable, - bool executable); +void* operator new(size_t size) { + return malloc(size); +} -bool -writeMachO64Object(uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* architecture, unsigned alignment, bool writable, - bool executable); - -bool -writeMachO32Object(uint8_t* data, unsigned size, FILE* out, - const char* startName, const char* endName, - const char* architecture, unsigned alignment, bool writable, - bool executable); - -bool -writePEObject(uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* architecture, - unsigned alignment, bool writable, bool executable); - -} // namespace binaryToObject +void operator delete(void* mem) { + if(mem) { + free(mem); + } +} namespace { +using namespace avian::tools; + bool writeObject(uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* platform, + const char* endName, const char* os, const char* architecture, unsigned alignment, bool writable, bool executable) { - using namespace binaryToObject; + Platform* platform = Platform::getPlatform(PlatformInfo(os, architecture)); - bool found = false; - bool success = false; - if (strcmp("linux", platform) == 0) { - if (strcmp("x86_64", architecture) == 0) { - found = true; - success = writeElf64Object - (data, size, out, startName, endName, architecture, alignment, - writable, executable); - } else if (strcmp("i386", architecture) == 0 - or strcmp("arm", architecture) == 0 - or strcmp("powerpc", architecture) == 0) - { - found = true; - success = writeElf32Object - (data, size, out, startName, endName, architecture, alignment, - writable, executable); - } - } else if (strcmp("darwin", platform) == 0) { - if (strcmp("x86_64", architecture) == 0) { - found = true; - success = writeMachO64Object - (data, size, out, startName, endName, architecture, alignment, - writable, executable); - } else if (strcmp("i386", architecture) == 0 - or strcmp("powerpc", architecture) == 0 - or strcmp("arm", architecture) == 0) - { - found = true; - success = writeMachO32Object - (data, size, out, startName, endName, architecture, alignment, - writable, executable); - } - } else if (strcmp("windows", platform) == 0 - and ((strcmp("x86_64", architecture) == 0 - or strcmp("i386", architecture) == 0))) - { - found = true; - success = writePEObject - (data, size, out, startName, endName, architecture, alignment, writable, - executable); - } - - if (not found) { - fprintf(stderr, "unsupported platform: %s/%s\n", platform, architecture); + if(!platform) { + fprintf(stderr, "unsupported platform: %s/%s\n", os, architecture); return false; } + ObjectWriter* writer = platform->makeObjectWriter(); + + bool success = writer->write(data, size, out, startName, endName, alignment, + ObjectWriter::Readable | (writable ? ObjectWriter::Writable : 0) | (executable ? ObjectWriter::Executable : 0)); + + writer->dispose(); + return success; } diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 45cc9556a9..67fe684153 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -8,16 +8,20 @@ There is NO WARRANTY for this software. See license.txt for details. */ -#include "stdint.h" -#include "stdio.h" -#include "string.h" +#include +#include +#include + +#include "tools.h" + +namespace { #define IMAGE_SIZEOF_SHORT_NAME 8 #define IMAGE_FILE_RELOCS_STRIPPED 1 #define IMAGE_FILE_LINE_NUMS_STRIPPED 4 #define IMAGE_FILE_MACHINE_AMD64 0x8664 -#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_I386 0x014c #define IMAGE_FILE_32BIT_MACHINE 256 #define IMAGE_SCN_ALIGN_1BYTES 0x100000 @@ -29,8 +33,6 @@ #define IMAGE_SCN_MEM_WRITE 0x80000000 #define IMAGE_SCN_CNT_CODE 32 -namespace { - struct IMAGE_FILE_HEADER { uint16_t Machine; uint16_t NumberOfSections; @@ -161,71 +163,89 @@ writeObject(const uint8_t* data, unsigned size, FILE* out, fwrite(endName, 1, endNameLength, out); } -} // namespace +using namespace avian::tools; -namespace binaryToObject { +template +class WindowsPlatform : public Platform { +public: -bool -writePEObject -(uint8_t* data, unsigned size, FILE* out, const char* startName, - const char* endName, const char* architecture, unsigned alignment, - bool writable, bool executable) -{ - int machine; - int machineMask; - if (strcmp(architecture, "x86_64") == 0) { - machine = IMAGE_FILE_MACHINE_AMD64; - machineMask = 0; - } else if (strcmp(architecture, "i386") == 0) { - machine = IMAGE_FILE_MACHINE_I386; - machineMask = IMAGE_FILE_32BIT_MACHINE; - } else { - fprintf(stderr, "unsupported architecture: %s\n", architecture); - return false; - } + class PEObjectWriter : public ObjectWriter { + public: - int sectionMask; - switch (alignment) { - case 0: - case 1: - sectionMask = IMAGE_SCN_ALIGN_1BYTES; - break; - case 2: - sectionMask = IMAGE_SCN_ALIGN_2BYTES; - break; - case 4: - sectionMask = IMAGE_SCN_ALIGN_4BYTES; - break; - case 8: - sectionMask = IMAGE_SCN_ALIGN_8BYTES; - break; - default: - fprintf(stderr, "unsupported alignment: %d\n", alignment); - return false; - } + virtual bool write(uint8_t* data, size_t size, FILE* out, + const char* startName, const char* endName, + unsigned alignment, unsigned accessFlags) + { + int machine; + int machineMask; - sectionMask |= IMAGE_SCN_MEM_READ; + if (BytesPerWord == 8) { + machine = IMAGE_FILE_MACHINE_AMD64; + machineMask = 0; + } else { // if (BytesPerWord == 8) + machine = IMAGE_FILE_MACHINE_I386; + machineMask = IMAGE_FILE_32BIT_MACHINE; + } - const char* sectionName; - if (writable) { - if (executable) { - sectionName = ".rwx"; - sectionMask |= IMAGE_SCN_MEM_WRITE - | IMAGE_SCN_MEM_EXECUTE - | IMAGE_SCN_CNT_CODE; - } else { - sectionName = ".data"; - sectionMask |= IMAGE_SCN_MEM_WRITE; + int sectionMask; + switch (alignment) { + case 0: + case 1: + sectionMask = IMAGE_SCN_ALIGN_1BYTES; + break; + case 2: + sectionMask = IMAGE_SCN_ALIGN_2BYTES; + break; + case 4: + sectionMask = IMAGE_SCN_ALIGN_4BYTES; + break; + case 8: + sectionMask = IMAGE_SCN_ALIGN_8BYTES; + break; + default: + fprintf(stderr, "unsupported alignment: %d\n", alignment); + return false; + } + + sectionMask |= IMAGE_SCN_MEM_READ; + + const char* sectionName; + if (accessFlags & ObjectWriter::Writable) { + if (accessFlags & ObjectWriter::Executable) { + sectionName = ".rwx"; + sectionMask |= IMAGE_SCN_MEM_WRITE + | IMAGE_SCN_MEM_EXECUTE + | IMAGE_SCN_CNT_CODE; + } else { + sectionName = ".data"; + sectionMask |= IMAGE_SCN_MEM_WRITE; + } + } else { + sectionName = ".text"; + sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; + } + + writeObject(data, size, out, startName, endName, sectionName, machine, + machineMask, sectionMask); + + return true; } - } else { - sectionName = ".text"; - sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; + + virtual void dispose() { + delete this; + } + + }; + + virtual ObjectWriter* makeObjectWriter() { + return new PEObjectWriter(); } - writeObject(data, size, out, startName, endName, sectionName, machine, - machineMask, sectionMask); + WindowsPlatform(): + Platform(PlatformInfo(PlatformInfo::Windows, BytesPerWord == 4 ? PlatformInfo::x86 : PlatformInfo::x86_64)) {} +}; + +WindowsPlatform<4> windows32Platform; +WindowsPlatform<8> windows64Platform; - return true; } - -} // namespace binaryToObject diff --git a/src/binaryToObject/tools.cpp b/src/binaryToObject/tools.cpp new file mode 100644 index 0000000000..531fd2f246 --- /dev/null +++ b/src/binaryToObject/tools.cpp @@ -0,0 +1,62 @@ +/* Copyright (c) 2009, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include +#include +#include +#include + +#include "tools.h" + +namespace avian { + +namespace tools { + + +Platform* Platform::first = 0; + +PlatformInfo::OperatingSystem PlatformInfo::osFromString(const char* os) { + if(strcmp(os, "linux") == 0) { + return Linux; + } else if(strcmp(os, "windows") == 0) { + return Windows; + } else if(strcmp(os, "darwin") == 0) { + return Darwin; + } else { + return UnknownOS; + } +} + +PlatformInfo::Architecture PlatformInfo::archFromString(const char* arch) { + if(strcmp(arch, "i386") == 0) { + return x86; + } else if(strcmp(arch, "x86_64") == 0) { + return x86_64; + } else if(strcmp(arch, "powerpc") == 0) { + return PowerPC; + } else if(strcmp(arch, "arm") == 0) { + return Arm; + } else { + return UnknownArch; + } +} + +Platform* Platform::getPlatform(PlatformInfo info) { + for(Platform* p = first; p; p = p->next) { + if(p->info == info) { + return p; + } + } + return 0; +} + +} // namespace tools + +} // namespace avian \ No newline at end of file diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h new file mode 100644 index 0000000000..1d1b2d2a34 --- /dev/null +++ b/src/binaryToObject/tools.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2009, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_TOOLS_H_ +#define AVIAN_TOOLS_H_ + +namespace avian { + +namespace tools { + +class ObjectWriter { +public: + + enum AccessFlags { + Readable = 1 << 0, + Writable = 1 << 1, + Executable = 1 << 2 + }; + + virtual bool write(uint8_t* data, size_t size, FILE* out, + const char* startName, const char* endName, + unsigned alignment, unsigned accessFlags) = 0; + + virtual void dispose() = 0; +}; + +class PlatformInfo { +public: + enum OperatingSystem { + Linux, Windows, Darwin, UnknownOS + }; + + enum Architecture { + x86, x86_64, PowerPC, Arm, UnknownArch + }; + + const OperatingSystem os; + const Architecture arch; + + static OperatingSystem osFromString(const char* os); + static Architecture archFromString(const char* arch); + + inline PlatformInfo(OperatingSystem os, Architecture arch): + os(os), + arch(arch) {} + + inline PlatformInfo(const char* os, const char* arch): + os(osFromString(os)), + arch(archFromString(arch)) {} + + inline bool operator == (const PlatformInfo& other) { + return os == other.os && arch == other.arch; + } + + inline bool isLittleEndian() { + return arch != PowerPC; + } +}; + +class Platform { +private: + Platform* next; + static Platform* first; +public: + PlatformInfo info; + + inline Platform(PlatformInfo info): + next(first), + info(info) + { + first = this; + } + + virtual ObjectWriter* makeObjectWriter() = 0; + + static Platform* getPlatform(PlatformInfo info); +}; + +} // namespace tools + +} // namespace avian + +#endif \ No newline at end of file From 175db9ec5413e5d17cdf8bf7a6e0adda9e5ea456 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 25 Apr 2012 08:43:51 -0600 Subject: [PATCH 063/140] allow streaming to more than just files in binaryToObject --- src/binaryToObject/elf.cpp | 39 +++++++++++++++++------------------ src/binaryToObject/mach-o.cpp | 25 +++++++++++----------- src/binaryToObject/main.cpp | 10 ++++----- src/binaryToObject/pe.cpp | 26 +++++++++++------------ src/binaryToObject/tools.cpp | 31 ++++++++++++++++++++++++++++ src/binaryToObject/tools.h | 22 +++++++++++++++++++- 6 files changed, 101 insertions(+), 52 deletions(-) diff --git a/src/binaryToObject/elf.cpp b/src/binaryToObject/elf.cpp index 51c7d7c587..5235c8f0a7 100644 --- a/src/binaryToObject/elf.cpp +++ b/src/binaryToObject/elf.cpp @@ -166,7 +166,7 @@ public: ElfObjectWriter(PlatformInfo::Architecture arch): arch(arch) {} - void writeObject(const uint8_t* data, unsigned size, FILE* out, + void writeObject(const uint8_t* data, unsigned size, OutputStream* out, const char* startName, const char* endName, const char* sectionName, unsigned sectionFlags, unsigned alignment, int machine, int encoding) @@ -311,31 +311,30 @@ public: endSymbol.st_other = V1(STV_DEFAULT); endSymbol.st_shndx = V2(bodySectionNumber); - fwrite(&fileHeader, 1, sizeof(fileHeader), out); - fwrite(&nullSection, 1, sizeof(nullSection), out); - fwrite(&bodySection, 1, sizeof(bodySection), out); - fwrite(§ionStringTableSection, 1, sizeof(sectionStringTableSection), - out); - fwrite(&stringTableSection, 1, sizeof(stringTableSection), out); - fwrite(&symbolTableSection, 1, sizeof(symbolTableSection), out); + out->writeChunk(&fileHeader, sizeof(fileHeader)); + out->writeChunk(&nullSection, sizeof(nullSection)); + out->writeChunk(&bodySection, sizeof(bodySection)); + out->writeChunk(§ionStringTableSection, sizeof(sectionStringTableSection)); + out->writeChunk(&stringTableSection, sizeof(stringTableSection)); + out->writeChunk(&symbolTableSection, sizeof(symbolTableSection)); - fwrite(data, 1, size, out); + out->writeChunk(data, size); - fputc(0, out); - fwrite(sectionStringTableName, 1, sectionStringTableNameLength, out); - fwrite(stringTableName, 1, stringTableNameLength, out); - fwrite(symbolTableName, 1, symbolTableNameLength, out); - fwrite(sectionName, 1, sectionNameLength, out); + out->write(0); + out->writeChunk(sectionStringTableName, sectionStringTableNameLength); + out->writeChunk(stringTableName, stringTableNameLength); + out->writeChunk(symbolTableName, symbolTableNameLength); + out->writeChunk(sectionName, sectionNameLength); - fputc(0, out); - fwrite(startName, 1, startNameLength, out); - fwrite(endName, 1, endNameLength, out); + out->write(0); + out->writeChunk(startName, startNameLength); + out->writeChunk(endName, endNameLength); - fwrite(&startSymbol, 1, sizeof(startSymbol), out); - fwrite(&endSymbol, 1, sizeof(endSymbol), out); + out->writeChunk(&startSymbol, sizeof(startSymbol)); + out->writeChunk(&endSymbol, sizeof(endSymbol)); } - virtual bool write(uint8_t* data, size_t size, FILE* out, + virtual bool write(uint8_t* data, size_t size, OutputStream* out, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) { diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index 6aab90a0b1..e040569212 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -148,7 +148,7 @@ public: MachOObjectWriter(PlatformInfo::Architecture arch): arch(arch) {} - void writeObject(const uint8_t* data, unsigned size, FILE* out, + void writeObject(const uint8_t* data, unsigned size, OutputStream* out, const char* startName, const char* endName, const char* segmentName, const char* sectionName, unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType) @@ -242,22 +242,23 @@ public: } }; - fwrite(&header, 1, sizeof(header), out); - fwrite(&segment, 1, sizeof(segment), out); - fwrite(§, 1, sizeof(sect), out); - fwrite(&symbolTable, 1, sizeof(symbolTable), out); + out->writeChunk(&header, sizeof(header)); + out->writeChunk(&segment, sizeof(segment)); + out->writeChunk(§, sizeof(sect)); + out->writeChunk(&symbolTable, sizeof(symbolTable)); - fwrite(data, 1, size, out); - for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out); + out->writeChunk(data, size); + out->writeRepeat(0, pad(size) - size); - fwrite(&symbolList, 1, sizeof(symbolList), out); + out->writeChunk(&symbolList, sizeof(symbolList)); - fputc(0, out); - fwrite(startName, 1, startNameLength, out); - fwrite(endName, 1, endNameLength, out); + out->write(0); + + out->writeChunk(startName, startNameLength); + out->writeChunk(endName, endNameLength); } - virtual bool write(uint8_t* data, size_t size, FILE* out, + virtual bool write(uint8_t* data, size_t size, OutputStream* out, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) { diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index 6dcdf9734d..197bcbf0f6 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -44,7 +44,7 @@ namespace { using namespace avian::tools; bool -writeObject(uint8_t* data, unsigned size, FILE* out, const char* startName, +writeObject(uint8_t* data, unsigned size, OutputStream* out, const char* startName, const char* endName, const char* os, const char* architecture, unsigned alignment, bool writable, bool executable) @@ -142,13 +142,11 @@ main(int argc, const char** argv) bool success = false; if (data) { - FILE* out = fopen(argv[2], "wb"); - if (out) { + FileOutputStream out(argv[2]); + if (out.isValid()) { success = writeObject - (data, size, out, argv[3], argv[4], argv[5], argv[6], alignment, + (data, size, &out, argv[3], argv[4], argv[5], argv[6], alignment, writable, executable); - - fclose(out); } else { fprintf(stderr, "unable to open %s\n", argv[2]); } diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 67fe684153..9fcdbe8949 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -79,8 +79,10 @@ pad(unsigned n) return (n + (4 - 1)) & ~(4 - 1); } +using namespace avian::tools; + void -writeObject(const uint8_t* data, unsigned size, FILE* out, +writeObject(const uint8_t* data, unsigned size, OutputStream* out, const char* startName, const char* endName, const char* sectionName, int machine, int machineMask, int sectionMask) @@ -147,24 +149,22 @@ writeObject(const uint8_t* data, unsigned size, FILE* out, }; endSymbol.N.Name.Long = endNameOffset; - fwrite(&fileHeader, 1, sizeof(fileHeader), out); - fwrite(§ionHeader, 1, sizeof(sectionHeader), out); + out->writeChunk(&fileHeader, sizeof(fileHeader)); + out->writeChunk(§ionHeader, sizeof(sectionHeader)); - fwrite(data, 1, size, out); - for (unsigned i = 0; i < pad(size) - size; ++i) fputc(0, out); + out->writeChunk(data, size); + out->writeRepeat(0, pad(size) - size); - fwrite(&startSymbol, 1, sizeof(startSymbol), out); - fwrite(&endSymbol, 1, sizeof(endSymbol), out); + out->writeChunk(&startSymbol, sizeof(startSymbol)); + out->writeChunk(&endSymbol, sizeof(endSymbol)); uint32_t symbolTableSize = endNameOffset + endNameLength; - fwrite(&symbolTableSize, 1, 4, out); + out->writeChunk(&symbolTableSize, 4); - fwrite(startName, 1, startNameLength, out); - fwrite(endName, 1, endNameLength, out); + out->writeChunk(startName, startNameLength); + out->writeChunk(endName, endNameLength); } -using namespace avian::tools; - template class WindowsPlatform : public Platform { public: @@ -172,7 +172,7 @@ public: class PEObjectWriter : public ObjectWriter { public: - virtual bool write(uint8_t* data, size_t size, FILE* out, + virtual bool write(uint8_t* data, size_t size, OutputStream* out, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) { diff --git a/src/binaryToObject/tools.cpp b/src/binaryToObject/tools.cpp index 531fd2f246..0768e8a24b 100644 --- a/src/binaryToObject/tools.cpp +++ b/src/binaryToObject/tools.cpp @@ -19,6 +19,37 @@ namespace avian { namespace tools { +void OutputStream::write(uint8_t byte) { + writeChunk(&byte, 1); +} + +void OutputStream::writeRepeat(uint8_t byte, size_t size) { + for(size_t i = 0; i < size; i++) { + write(byte); + } +} + +FileOutputStream::FileOutputStream(const char* name): + file(fopen(name, "wb")) {} + +FileOutputStream::~FileOutputStream() { + if(file) { + fclose(file); + } +} + +bool FileOutputStream::isValid() { + return file; +} + +void FileOutputStream::writeChunk(const void* data, size_t size) { + fwrite(data, size, 1, file); +} + +void FileOutputStream::write(uint8_t byte) { + fputc(byte, file); +} + Platform* Platform::first = 0; diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h index 1d1b2d2a34..359068fe4d 100644 --- a/src/binaryToObject/tools.h +++ b/src/binaryToObject/tools.h @@ -15,6 +15,26 @@ namespace avian { namespace tools { +class OutputStream { +public: + virtual void writeChunk(const void* data, size_t size) = 0; + virtual void write(uint8_t byte); + virtual void writeRepeat(uint8_t byte, size_t size); +}; + +class FileOutputStream : public OutputStream { +private: + FILE* file; +public: + FileOutputStream(const char* name); + ~FileOutputStream(); + + bool isValid(); + + virtual void writeChunk(const void* data, size_t size); + virtual void write(uint8_t byte); +}; + class ObjectWriter { public: @@ -24,7 +44,7 @@ public: Executable = 1 << 2 }; - virtual bool write(uint8_t* data, size_t size, FILE* out, + virtual bool write(uint8_t* data, size_t size, OutputStream* out, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) = 0; From a9ba4782ef8e261c30da2b19cf26968bec0436d2 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 25 Apr 2012 09:09:26 -0600 Subject: [PATCH 064/140] improve build for binaryToObject --- makefile | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/makefile b/makefile index 7389967ddb..1705b53986 100755 --- a/makefile +++ b/makefile @@ -623,14 +623,17 @@ generator-objects = \ $(call generator-cpp-objects,$(generator-sources),$(src),$(build)) generator = $(build)/generator -converter-objects = \ - $(build)/binaryToObject-main.o \ - $(build)/binaryToObject-tools.o \ - $(build)/binaryToObject-elf.o \ - $(build)/binaryToObject-mach-o64.o \ - $(build)/binaryToObject-mach-o32.o \ - $(build)/binaryToObject-pe.o -converter = $(build)/binaryToObject +converter-depends = $(src)/binaryToObject/tools.h + +converter-sources = \ + $(src)/binaryToObject/main.cpp \ + $(src)/binaryToObject/tools.cpp \ + $(src)/binaryToObject/elf.cpp \ + $(src)/binaryToObject/mach-o.cpp \ + $(src)/binaryToObject/pe.cpp + +converter-objects = $(call cpp-objects,$(converter-sources),$(src),$(build)) +converter = $(build)/binaryToObject/binaryToObject static-library = $(build)/lib$(name).a executable = $(build)/$(name)${exe-suffix} @@ -838,23 +841,9 @@ $(boot-object): $(boot-source) $(boot-javahome-object): $(src)/boot-javahome.cpp $(compile-object) -$(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp - $(build-cxx) $(converter-cflags) -c $(^) -o $(@) - -$(build)/binaryToObject-tools.o: $(src)/binaryToObject/tools.cpp - $(build-cxx) $(converter-cflags) -c $(^) -o $(@) - -$(build)/binaryToObject-elf.o: $(src)/binaryToObject/elf.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) - -$(build)/binaryToObject-mach-o64.o: $(src)/binaryToObject/mach-o.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=64 -c $(^) -o $(@) - -$(build)/binaryToObject-mach-o32.o: $(src)/binaryToObject/mach-o.cpp - $(build-cxx) $(converter-cflags) -DBITS_PER_WORD=32 -c $(^) -o $(@) - -$(build)/binaryToObject-pe.o: $(src)/binaryToObject/pe.cpp - $(build-cxx) $(converter-cflags) -c $(^) -o $(@) +$(converter-objects): $(build)/binaryToObject/%.o: $(src)/binaryToObject/%.cpp $(converter-depends) + @mkdir -p $(dir $(@)) + $(build-cxx) $(converter-cflags) -c $(<) -o $(@) $(converter): $(converter-objects) $(build-cc) $(^) -o $(@) From ca9b5b2f59c18f36e9cd1ef79f799f4e9c60e634 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 25 Apr 2012 09:09:39 -0600 Subject: [PATCH 065/140] move OutputStream to ObjectWriter constructor in binaryToObject --- src/binaryToObject/elf.cpp | 16 +++++++++------- src/binaryToObject/mach-o.cpp | 16 +++++++++------- src/binaryToObject/main.cpp | 4 ++-- src/binaryToObject/pe.cpp | 21 +++++++++++++-------- src/binaryToObject/tools.h | 4 ++-- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/binaryToObject/elf.cpp b/src/binaryToObject/elf.cpp index 5235c8f0a7..4e752104a1 100644 --- a/src/binaryToObject/elf.cpp +++ b/src/binaryToObject/elf.cpp @@ -162,11 +162,13 @@ public: public: PlatformInfo::Architecture arch; + OutputStream* out; - ElfObjectWriter(PlatformInfo::Architecture arch): - arch(arch) {} + ElfObjectWriter(PlatformInfo::Architecture arch, OutputStream* out): + arch(arch), + out(out) {} - void writeObject(const uint8_t* data, unsigned size, OutputStream* out, + void writeObject(const uint8_t* data, unsigned size, const char* startName, const char* endName, const char* sectionName, unsigned sectionFlags, unsigned alignment, int machine, int encoding) @@ -334,7 +336,7 @@ public: out->writeChunk(&endSymbol, sizeof(endSymbol)); } - virtual bool write(uint8_t* data, size_t size, OutputStream* out, + virtual bool write(uint8_t* data, size_t size, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) { @@ -374,7 +376,7 @@ public: sectionName = ".rodata"; } - writeObject(data, size, out, startName, endName, sectionName, sectionFlags, + writeObject(data, size, startName, endName, sectionName, sectionFlags, alignment, machine, encoding); return true; @@ -388,8 +390,8 @@ public: ElfPlatform(PlatformInfo::Architecture arch): Platform(PlatformInfo(PlatformInfo::Linux, arch)) {} - virtual ObjectWriter* makeObjectWriter() { - return new ElfObjectWriter(info.arch); + virtual ObjectWriter* makeObjectWriter(OutputStream* out) { + return new ElfObjectWriter(info.arch, out); } }; diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index e040569212..5899c652ff 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -144,11 +144,13 @@ public: public: PlatformInfo::Architecture arch; + OutputStream* out; - MachOObjectWriter(PlatformInfo::Architecture arch): - arch(arch) {} + MachOObjectWriter(PlatformInfo::Architecture arch, OutputStream* out): + arch(arch), + out(out) {} - void writeObject(const uint8_t* data, unsigned size, OutputStream* out, + void writeObject(const uint8_t* data, unsigned size, const char* startName, const char* endName, const char* segmentName, const char* sectionName, unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType) @@ -258,7 +260,7 @@ public: out->writeChunk(endName, endNameLength); } - virtual bool write(uint8_t* data, size_t size, OutputStream* out, + virtual bool write(uint8_t* data, size_t size, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) { @@ -307,7 +309,7 @@ public: myEndName[0] = '_'; memcpy(myEndName + 1, endName, endNameLength + 1); - writeObject(data, size, out, myStartName, myEndName, segmentName, + writeObject(data, size, myStartName, myEndName, segmentName, sectionName, alignment, cpuType, cpuSubType); return true; @@ -321,8 +323,8 @@ public: MachOPlatform(PlatformInfo::Architecture arch): Platform(PlatformInfo(PlatformInfo::Darwin, arch)) {} - virtual ObjectWriter* makeObjectWriter() { - return new MachOObjectWriter(info.arch); + virtual ObjectWriter* makeObjectWriter(OutputStream* out) { + return new MachOObjectWriter(info.arch, out); } }; diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index 197bcbf0f6..c9a3fb8d75 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -56,9 +56,9 @@ writeObject(uint8_t* data, unsigned size, OutputStream* out, const char* startNa return false; } - ObjectWriter* writer = platform->makeObjectWriter(); + ObjectWriter* writer = platform->makeObjectWriter(out); - bool success = writer->write(data, size, out, startName, endName, alignment, + bool success = writer->write(data, size, startName, endName, alignment, ObjectWriter::Readable | (writable ? ObjectWriter::Writable : 0) | (executable ? ObjectWriter::Executable : 0)); writer->dispose(); diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 9fcdbe8949..37bf643a95 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -103,13 +103,13 @@ writeObject(const uint8_t* data, unsigned size, OutputStream* out, sectionCount, // NumberOfSections 0, // TimeDateStamp sizeof(IMAGE_FILE_HEADER) - + sizeof(IMAGE_SECTION_HEADER) - + pad(size), // PointerToSymbolTable + + sizeof(IMAGE_SECTION_HEADER) + + pad(size), // PointerToSymbolTable symbolCount, // NumberOfSymbols 0, // SizeOfOptionalHeader IMAGE_FILE_RELOCS_STRIPPED - | IMAGE_FILE_LINE_NUMS_STRIPPED - | machineMask // Characteristics + | IMAGE_FILE_LINE_NUMS_STRIPPED + | machineMask // Characteristics }; IMAGE_SECTION_HEADER sectionHeader = { @@ -118,7 +118,7 @@ writeObject(const uint8_t* data, unsigned size, OutputStream* out, 0, // VirtualAddress pad(size), // SizeOfRawData sizeof(IMAGE_FILE_HEADER) - + sizeof(IMAGE_SECTION_HEADER), // PointerToRawData + + sizeof(IMAGE_SECTION_HEADER), // PointerToRawData 0, // PointerToRelocations 0, // PointerToLinenumbers 0, // NumberOfRelocations @@ -172,7 +172,12 @@ public: class PEObjectWriter : public ObjectWriter { public: - virtual bool write(uint8_t* data, size_t size, OutputStream* out, + OutputStream* out; + + PEObjectWriter(OutputStream* out): + out(out) {} + + virtual bool write(uint8_t* data, size_t size, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) { @@ -237,8 +242,8 @@ public: }; - virtual ObjectWriter* makeObjectWriter() { - return new PEObjectWriter(); + virtual ObjectWriter* makeObjectWriter(OutputStream* out) { + return new PEObjectWriter(out); } WindowsPlatform(): diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h index 359068fe4d..9ba285dd66 100644 --- a/src/binaryToObject/tools.h +++ b/src/binaryToObject/tools.h @@ -44,7 +44,7 @@ public: Executable = 1 << 2 }; - virtual bool write(uint8_t* data, size_t size, OutputStream* out, + virtual bool write(uint8_t* data, size_t size, const char* startName, const char* endName, unsigned alignment, unsigned accessFlags) = 0; @@ -98,7 +98,7 @@ public: first = this; } - virtual ObjectWriter* makeObjectWriter() = 0; + virtual ObjectWriter* makeObjectWriter(OutputStream* out) = 0; static Platform* getPlatform(PlatformInfo info); }; From deeb3c694c263fb7858f56e83013e07c2afccbd3 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 25 Apr 2012 17:47:07 -0600 Subject: [PATCH 066/140] interpret time of zero as infinity when isAbsolute is false in Unsafe.park This behavior is not covered in the documentation, but LockSupport.park clearly relies on it. --- src/classpath-openjdk.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 5b23b4019f..78cb98083a 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2739,12 +2739,15 @@ Avian_sun_misc_Unsafe_park if (time <= 0) { return; } - } else { - time /= 1000 * 1000; + } else if (time) { + // if not absolute, interpret time as nanoseconds, but make sure + // it doesn't become zero when we convert to milliseconds, since + // zero is interpreted as infinity below + time = (time / (1000 * 1000)) + 1; } monitorAcquire(t, local::interruptLock(t, t->javaThread)); - while (time > 0 + while (time >= 0 and (not (threadUnparked(t, t->javaThread) or monitorWait (t, local::interruptLock(t, t->javaThread), time)))) @@ -2752,6 +2755,10 @@ Avian_sun_misc_Unsafe_park int64_t now = t->m->system->now(); time -= now - then; then = now; + + if (time == 0) { + break; + } } threadUnparked(t, t->javaThread) = false; monitorRelease(t, local::interruptLock(t, t->javaThread)); From 661f6c28a8be920a5118f6bb32d3a964ee68d1d8 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 27 Apr 2012 12:08:44 -0600 Subject: [PATCH 067/140] refactor binaryToObject to allow more flexibilty (in particular, allowing arbitrary symbols per object) --- makefile | 19 +- src/binaryToObject/elf.cpp | 422 +++++++++++++++----------------- src/binaryToObject/endianness.h | 25 +- src/binaryToObject/mach-o.cpp | 339 +++++++++++-------------- src/binaryToObject/main.cpp | 20 +- src/binaryToObject/pe.cpp | 323 +++++++++++++----------- src/binaryToObject/tools.cpp | 32 +++ src/binaryToObject/tools.h | 69 +++++- 8 files changed, 640 insertions(+), 609 deletions(-) diff --git a/makefile b/makefile index 1705b53986..ff6cf9855b 100755 --- a/makefile +++ b/makefile @@ -236,7 +236,6 @@ ifeq ($(arch),powerpc) ifneq ($(platform),darwin) ifneq ($(arch),$(build-arch)) - converter-cflags += -DOPPOSITE_ENDIAN cxx = powerpc-linux-gnu-g++ cc = powerpc-linux-gnu-gcc ar = powerpc-linux-gnu-ar @@ -342,10 +341,6 @@ ifeq ($(platform),darwin) lflags += $(flags) endif - ifeq ($(build-arch),powerpc) - converter-cflags += -DBIG_ENDIAN - endif - ifeq ($(arch),powerpc) openjdk-extra-cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} cflags += -arch ppc -mmacosx-version-min=${OSX_SDK_VERSION} @@ -428,6 +423,7 @@ endif ifeq ($(mode),debug) optimization-cflags = -O0 -g3 + converter-cflags += -O0 -g3 strip = : endif ifeq ($(mode),debug-fast) @@ -606,9 +602,6 @@ driver-object = $(build)/main.o driver-dynamic-objects = \ $(build)/main-dynamic.o -gdb-plugin-object = $(build)/gdb-plugin.o -gdb-plugin-source = $(src)/gdb-plugin.cpp - boot-source = $(src)/boot.cpp boot-object = $(build)/boot.o @@ -623,7 +616,10 @@ generator-objects = \ $(call generator-cpp-objects,$(generator-sources),$(src),$(build)) generator = $(build)/generator -converter-depends = $(src)/binaryToObject/tools.h +converter-depends = \ + $(src)/binaryToObject/tools.h \ + $(src)/binaryToObject/endianness.h + converter-sources = \ $(src)/binaryToObject/main.cpp \ @@ -826,9 +822,6 @@ $(heapwalk-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) $(driver-object): $(driver-source) $(compile-object) -$(gdb-plugin-object): $(gdb-plugin-source) - $(compile-object) - $(build)/main-dynamic.o: $(driver-source) @echo "compiling $(@)" @mkdir -p $(dir $(@)) @@ -846,7 +839,7 @@ $(converter-objects): $(build)/binaryToObject/%.o: $(src)/binaryToObject/%.cpp $ $(build-cxx) $(converter-cflags) -c $(<) -o $(@) $(converter): $(converter-objects) - $(build-cc) $(^) -o $(@) + $(build-cc) $(^) -g -o $(@) $(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep) @echo "creating $(@)" diff --git a/src/binaryToObject/elf.cpp b/src/binaryToObject/elf.cpp index 4e752104a1..3548ac8431 100644 --- a/src/binaryToObject/elf.cpp +++ b/src/binaryToObject/elf.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "endianness.h" @@ -119,6 +120,39 @@ using avian::endian::Endianness; #define V4 Endianness::v4 #define VANY Endianness::vAny + +unsigned getElfPlatform(PlatformInfo::Architecture arch) { + switch(arch) { + case PlatformInfo::x86_64: + return EM_X86_64; + case PlatformInfo::x86: + return EM_386; + case PlatformInfo::Arm: + return EM_ARM; + case PlatformInfo::PowerPC: + return EM_PPC; + } + return ~0; +} + +const char* getSectionName(unsigned accessFlags, unsigned& sectionFlags) { + sectionFlags = SHF_ALLOC; + if (accessFlags & Platform::Writable) { + if (accessFlags & Platform::Executable) { + sectionFlags |= SHF_WRITE | SHF_EXECINSTR; + return ".rwx"; + } else { + sectionFlags |= SHF_WRITE; + return ".data"; + } + } else if (accessFlags & Platform::Executable) { + sectionFlags |= SHF_EXECINSTR; + return ".text"; + } else { + return ".rodata"; + } +} + template class ElfPlatform : public Platform { public: @@ -158,240 +192,182 @@ public: typedef Symbol_Ty Symbol; - class ElfObjectWriter : public ObjectWriter { + static const unsigned Encoding = TargetLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; + + const unsigned machine; + + ElfPlatform(PlatformInfo::Architecture arch): + Platform(PlatformInfo(PlatformInfo::Linux, arch)), + machine(getElfPlatform(arch)) {} + + class FileWriter { public: + unsigned sectionCount; + unsigned sectionStringTableSectionNumber; - PlatformInfo::Architecture arch; - OutputStream* out; + AddrTy dataOffset; - ElfObjectWriter(PlatformInfo::Architecture arch, OutputStream* out): - arch(arch), - out(out) {} + FileHeader header; + StringTable strings; - void writeObject(const uint8_t* data, unsigned size, - const char* startName, const char* endName, - const char* sectionName, unsigned sectionFlags, - unsigned alignment, int machine, int encoding) + FileWriter(unsigned machine): + sectionCount(0), + dataOffset(sizeof(FileHeader)) { - const unsigned sectionCount = 5; - const unsigned symbolCount = 2; - - const unsigned sectionNameLength = strlen(sectionName) + 1; - const unsigned startNameLength = strlen(startName) + 1; - const unsigned endNameLength = strlen(endName) + 1; - - const char* const sectionStringTableName = ".shstrtab"; - const char* const stringTableName = ".strtab"; - const char* const symbolTableName = ".symtab"; - - const unsigned sectionStringTableNameLength - = strlen(sectionStringTableName) + 1; - const unsigned stringTableNameLength = strlen(stringTableName) + 1; - const unsigned symbolTableNameLength = strlen(symbolTableName) + 1; - - const unsigned nullStringOffset = 0; - - const unsigned sectionStringTableNameOffset = nullStringOffset + 1; - const unsigned stringTableNameOffset - = sectionStringTableNameOffset + sectionStringTableNameLength; - const unsigned symbolTableNameOffset - = stringTableNameOffset + stringTableNameLength; - const unsigned sectionNameOffset - = symbolTableNameOffset + symbolTableNameLength; - const unsigned sectionStringTableLength - = sectionNameOffset + sectionNameLength; - - const unsigned startNameOffset = nullStringOffset + 1; - const unsigned endNameOffset = startNameOffset + startNameLength; - const unsigned stringTableLength = endNameOffset + endNameLength; - - const unsigned bodySectionNumber = 1; - const unsigned sectionStringTableSectionNumber = 2; - const unsigned stringTableSectionNumber = 3; - - FileHeader fileHeader; - memset(&fileHeader, 0, sizeof(FileHeader)); - fileHeader.e_ident[EI_MAG0] = V1(ELFMAG0); - fileHeader.e_ident[EI_MAG1] = V1(ELFMAG1); - fileHeader.e_ident[EI_MAG2] = V1(ELFMAG2); - fileHeader.e_ident[EI_MAG3] = V1(ELFMAG3); - fileHeader.e_ident[EI_CLASS] = V1(Class); - fileHeader.e_ident[EI_DATA] = V1(encoding); - fileHeader.e_ident[EI_VERSION] = V1(EV_CURRENT); - fileHeader.e_ident[EI_OSABI] = V1(OSABI); - fileHeader.e_ident[EI_ABIVERSION] = V1(0); - fileHeader.e_type = V2(ET_REL); - fileHeader.e_machine = V2(machine); - fileHeader.e_version = V4(EV_CURRENT); - fileHeader.e_entry = VANY(static_cast(0)); - fileHeader.e_phoff = VANY(static_cast(0)); - fileHeader.e_shoff = VANY(static_cast(sizeof(FileHeader))); - fileHeader.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0); - fileHeader.e_ehsize = V2(sizeof(FileHeader)); - fileHeader.e_phentsize = V2(0); - fileHeader.e_phnum = V2(0); - fileHeader.e_shentsize = V2(sizeof(SectionHeader)); - fileHeader.e_shnum = V2(sectionCount); - fileHeader.e_shstrndx = V2(sectionStringTableSectionNumber); - - SectionHeader nullSection; - memset(&nullSection, 0, sizeof(SectionHeader)); - - SectionHeader bodySection; - bodySection.sh_name = V4(sectionNameOffset); - bodySection.sh_type = V4(SHT_PROGBITS); - bodySection.sh_flags = VANY(static_cast(sectionFlags)); - bodySection.sh_addr = VANY(static_cast(0)); - unsigned bodySectionOffset - = sizeof(FileHeader) + (sizeof(SectionHeader) * sectionCount); - bodySection.sh_offset = VANY(static_cast(bodySectionOffset)); - unsigned bodySectionSize = size; - bodySection.sh_size = VANY(static_cast(bodySectionSize)); - bodySection.sh_link = V4(0); - bodySection.sh_info = V4(0); - bodySection.sh_addralign = VANY(static_cast(alignment)); - bodySection.sh_entsize = VANY(static_cast(0)); - - SectionHeader sectionStringTableSection; - sectionStringTableSection.sh_name = V4(sectionStringTableNameOffset); - sectionStringTableSection.sh_type = V4(SHT_STRTAB); - sectionStringTableSection.sh_flags = VANY(static_cast(0)); - sectionStringTableSection.sh_addr = VANY(static_cast(0)); - unsigned sectionStringTableSectionOffset - = bodySectionOffset + bodySectionSize; - sectionStringTableSection.sh_offset = VANY(static_cast(sectionStringTableSectionOffset)); - unsigned sectionStringTableSectionSize = sectionStringTableLength; - sectionStringTableSection.sh_size = VANY(static_cast(sectionStringTableSectionSize)); - sectionStringTableSection.sh_link = V4(0); - sectionStringTableSection.sh_info = V4(0); - sectionStringTableSection.sh_addralign = VANY(static_cast(1)); - sectionStringTableSection.sh_entsize = VANY(static_cast(0)); - - SectionHeader stringTableSection; - stringTableSection.sh_name = V4(stringTableNameOffset); - stringTableSection.sh_type = V4(SHT_STRTAB); - stringTableSection.sh_flags = VANY(static_cast(0)); - stringTableSection.sh_addr = VANY(static_cast(0)); - unsigned stringTableSectionOffset - = sectionStringTableSectionOffset + sectionStringTableSectionSize; - stringTableSection.sh_offset = VANY(static_cast(stringTableSectionOffset)); - unsigned stringTableSectionSize = stringTableLength; - stringTableSection.sh_size = VANY(static_cast(stringTableSectionSize)); - stringTableSection.sh_link = V4(0); - stringTableSection.sh_info = V4(0); - stringTableSection.sh_addralign = VANY(static_cast(1)); - stringTableSection.sh_entsize = VANY(static_cast(0)); - - SectionHeader symbolTableSection; - symbolTableSection.sh_name = V4(symbolTableNameOffset); - symbolTableSection.sh_type = V4(SHT_SYMTAB); - symbolTableSection.sh_flags = VANY(static_cast(0)); - symbolTableSection.sh_addr = VANY(static_cast(0)); - unsigned symbolTableSectionOffset - = stringTableSectionOffset + stringTableSectionSize; - symbolTableSection.sh_offset = VANY(static_cast(symbolTableSectionOffset)); - unsigned symbolTableSectionSize = sizeof(Symbol) * symbolCount; - symbolTableSection.sh_size = VANY(static_cast(symbolTableSectionSize)); - symbolTableSection.sh_link = V4(stringTableSectionNumber); - symbolTableSection.sh_info = V4(0); - symbolTableSection.sh_addralign = VANY(static_cast(Elf::BytesPerWord)); - symbolTableSection.sh_entsize = VANY(static_cast(sizeof(Symbol))); - - Symbol startSymbol; - startSymbol.st_name = V4(startNameOffset); - startSymbol.st_value = VANY(static_cast(0)); - startSymbol.st_size = VANY(static_cast(0)); - startSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); - startSymbol.st_other = V1(STV_DEFAULT); - startSymbol.st_shndx = V2(bodySectionNumber); - - Symbol endSymbol; - endSymbol.st_name = V4(endNameOffset); - endSymbol.st_value = VANY(static_cast(size)); - endSymbol.st_size = VANY(static_cast(0)); - endSymbol.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); - endSymbol.st_other = V1(STV_DEFAULT); - endSymbol.st_shndx = V2(bodySectionNumber); - - out->writeChunk(&fileHeader, sizeof(fileHeader)); - out->writeChunk(&nullSection, sizeof(nullSection)); - out->writeChunk(&bodySection, sizeof(bodySection)); - out->writeChunk(§ionStringTableSection, sizeof(sectionStringTableSection)); - out->writeChunk(&stringTableSection, sizeof(stringTableSection)); - out->writeChunk(&symbolTableSection, sizeof(symbolTableSection)); - - out->writeChunk(data, size); - - out->write(0); - out->writeChunk(sectionStringTableName, sectionStringTableNameLength); - out->writeChunk(stringTableName, stringTableNameLength); - out->writeChunk(symbolTableName, symbolTableNameLength); - out->writeChunk(sectionName, sectionNameLength); - - out->write(0); - out->writeChunk(startName, startNameLength); - out->writeChunk(endName, endNameLength); - - out->writeChunk(&startSymbol, sizeof(startSymbol)); - out->writeChunk(&endSymbol, sizeof(endSymbol)); + memset(&header, 0, sizeof(FileHeader)); + header.e_ident[EI_MAG0] = V1(ELFMAG0); + header.e_ident[EI_MAG1] = V1(ELFMAG1); + header.e_ident[EI_MAG2] = V1(ELFMAG2); + header.e_ident[EI_MAG3] = V1(ELFMAG3); + header.e_ident[EI_CLASS] = V1(Class); + header.e_ident[EI_DATA] = V1(Encoding); + header.e_ident[EI_VERSION] = V1(EV_CURRENT); + header.e_ident[EI_OSABI] = V1(OSABI); + header.e_ident[EI_ABIVERSION] = V1(0); + header.e_type = V2(ET_REL); + header.e_machine = V2(machine); + header.e_version = V4(EV_CURRENT); + header.e_entry = VANY(static_cast(0)); + header.e_phoff = VANY(static_cast(0)); + header.e_shoff = VANY(static_cast(sizeof(FileHeader))); + header.e_flags = V4(machine == EM_ARM ? 0x04000000 : 0); + header.e_ehsize = V2(sizeof(FileHeader)); + header.e_phentsize = V2(0); + header.e_phnum = V2(0); + header.e_shentsize = V2(sizeof(SectionHeader)); } - virtual bool write(uint8_t* data, size_t size, - const char* startName, const char* endName, - unsigned alignment, unsigned accessFlags) - { - int machine; - int encoding; - if (arch == PlatformInfo::x86_64) { - machine = EM_X86_64; - encoding = ELFDATA2LSB; - } else if (arch == PlatformInfo::x86) { - machine = EM_386; - encoding = ELFDATA2LSB; - } else if (arch == PlatformInfo::Arm) { - machine = EM_ARM; - encoding = ELFDATA2LSB; - } else if (arch == PlatformInfo::PowerPC) { - machine = EM_PPC; - encoding = ELFDATA2MSB; - } else { - fprintf(stderr, "unsupported architecture: %s\n", arch); - return false; - } - - const char* sectionName; - unsigned sectionFlags = SHF_ALLOC; - if (accessFlags & Writable) { - if (accessFlags & Executable) { - sectionName = ".rwx"; - sectionFlags |= SHF_WRITE | SHF_EXECINSTR; - } else { - sectionName = ".data"; - sectionFlags |= SHF_WRITE; - } - } else if (accessFlags & Executable) { - sectionName = ".text"; - sectionFlags |= SHF_EXECINSTR; - } else { - sectionName = ".rodata"; - } - - writeObject(data, size, startName, endName, sectionName, sectionFlags, - alignment, machine, encoding); - - return true; - } - - virtual void dispose() { - delete this; + void writeHeader(OutputStream* out) { + header.e_shnum = V2(sectionCount); + header.e_shstrndx = V2(sectionStringTableSectionNumber); + out->writeChunk(&header, sizeof(FileHeader)); } }; - ElfPlatform(PlatformInfo::Architecture arch): - Platform(PlatformInfo(PlatformInfo::Linux, arch)) {} + class SectionWriter { + public: + FileWriter& file; + String name; + SectionHeader header; + const size_t* dataSize; + const uint8_t* const* data; - virtual ObjectWriter* makeObjectWriter(OutputStream* out) { - return new ElfObjectWriter(info.arch, out); + SectionWriter(FileWriter& file): + file(file), + name(""), + data(0), + dataSize(0) + { + memset(&header, 0, sizeof(SectionHeader)); + file.sectionCount++; + file.dataOffset += sizeof(SectionHeader); + size_t nameOffset = file.strings.add(name); + header.sh_name = V4(nameOffset); + } + + SectionWriter( + FileWriter& file, + const char* chname, + unsigned type, + AddrTy flags, + unsigned alignment, + AddrTy addr, + const uint8_t* const* data, + size_t* dataSize, + size_t entsize = 0, + unsigned link = 0): + + file(file), + name(chname), + data(data), + dataSize(dataSize) + { + if(strcmp(chname, ".shstrtab") == 0) { + file.sectionStringTableSectionNumber = file.sectionCount; + } + file.sectionCount++; + file.dataOffset += sizeof(SectionHeader); + size_t nameOffset = file.strings.add(name); + + header.sh_name = V4(nameOffset); + header.sh_type = V4(type); + header.sh_flags = VANY(flags); + header.sh_addr = VANY(addr); + // header.sh_offset = VANY(static_cast(bodySectionOffset)); + // header.sh_size = VANY(static_cast(*dataSize)); + header.sh_link = V4(link); + header.sh_info = V4(0); + header.sh_addralign = VANY(static_cast(alignment)); + header.sh_entsize = VANY(static_cast(entsize)); + } + + void writeHeader(OutputStream* out) { + if(dataSize) { + header.sh_offset = VANY(file.dataOffset); + header.sh_size = VANY(static_cast(*dataSize)); + file.dataOffset += *dataSize; + } + + out->writeChunk(&header, sizeof(SectionHeader)); + } + + void writeData(OutputStream* out) { + if(data) { + out->writeChunk(*data, *dataSize); + } + } + + + }; + + virtual bool writeObject(OutputStream* out, Slice symbols, Slice data, unsigned accessFlags, unsigned alignment) { + + unsigned sectionFlags; + const char* sectionName = getSectionName(accessFlags, sectionFlags); + + StringTable symbolStringTable; + Buffer symbolTable; + + FileWriter file(machine); + + const int bodySectionNumber = 1; + const int stringTableSectionNumber = 3; + + SectionWriter sections[] = { + SectionWriter(file), // null section + SectionWriter(file, sectionName, SHT_PROGBITS, sectionFlags, alignment, 0, &data.items, &data.count), // body section + SectionWriter(file, ".shstrtab", SHT_STRTAB, 0, 1, 0, &file.strings.data, &file.strings.length), + SectionWriter(file, ".strtab", SHT_STRTAB, 0, 1, 0, &symbolStringTable.data, &symbolStringTable.length), + SectionWriter(file, ".symtab", SHT_SYMTAB, 0, 8, 0, &symbolTable.data, &symbolTable.length, sizeof(Symbol), stringTableSectionNumber) + }; + + // for some reason, string tables require a null first element... + symbolStringTable.add(""); + + for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) { + size_t nameOffset = symbolStringTable.add(sym->name); + + Symbol symbolStruct; + symbolStruct.st_name = V4(nameOffset); + symbolStruct.st_value = VANY(static_cast(sym->addr)); + symbolStruct.st_size = VANY(static_cast(0)); + symbolStruct.st_info = V1(SYMBOL_INFO(STB_GLOBAL, STT_NOTYPE)); + symbolStruct.st_other = V1(STV_DEFAULT); + symbolStruct.st_shndx = V2(bodySectionNumber); + symbolTable.write(&symbolStruct, sizeof(Symbol)); + } + + file.writeHeader(out); + + for(int i = 0; i < file.sectionCount; i++) { + sections[i].writeHeader(out); + } + + for(int i = 0; i < file.sectionCount; i++) { + sections[i].writeData(out); + } + + return true; } }; diff --git a/src/binaryToObject/endianness.h b/src/binaryToObject/endianness.h index 36c5675bac..0537fb8bfe 100644 --- a/src/binaryToObject/endianness.h +++ b/src/binaryToObject/endianness.h @@ -15,11 +15,12 @@ namespace avian { namespace endian { -#ifndef BIG_ENDIAN -const bool LittleEndian = true; -#else -const bool LittleEndian = false; -#endif +static union { + uint32_t i; + char c[4]; +} _DetectEndianness = {1}; + +const bool LittleEndian = _DetectEndianness.c[0] == 1; template class Endianness { @@ -57,13 +58,13 @@ public: return v; } else { return - ((static_cast(v) >> 56) & UINT64_C(0x00000000000000FF)) | - ((static_cast(v) >> 40) & UINT64_C(0x000000000000FF00)) | - ((static_cast(v) >> 24) & UINT64_C(0x0000000000FF0000)) | - ((static_cast(v) >> 8) & UINT64_C(0x00000000FF000000)) | - ((static_cast(v) << 8) & UINT64_C(0x000000FF00000000)) | - ((static_cast(v) << 24) & UINT64_C(0x0000FF0000000000)) | - ((static_cast(v) << 40) & UINT64_C(0x00FF000000000000)) | + ((static_cast(v) >> 56) & (static_cast(0xff) << 0)) | + ((static_cast(v) >> 40) & (static_cast(0xff) << 8)) | + ((static_cast(v) >> 24) & (static_cast(0xff) << 16)) | + ((static_cast(v) >> 8) & (static_cast(0xff) << 24)) | + ((static_cast(v) << 8) & (static_cast(0xff) << 32)) | + ((static_cast(v) << 24) & (static_cast(0xff) << 40)) | + ((static_cast(v) << 40) & (static_cast(0xff) << 48)) | ((static_cast(v) << 56)); } } diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index 5899c652ff..246940329f 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -56,6 +56,14 @@ using avian::endian::Endianness; #define V4 Endianness::v4 #define VANY Endianness::vAny +inline unsigned +log(unsigned n) +{ + unsigned r = 0; + for (unsigned i = 1; i < n; ++r) i <<= 1; + return r; +} + template class MachOPlatform : public Platform { public: @@ -132,200 +140,151 @@ public: return (n + (BytesPerWord - 1)) & ~(BytesPerWord - 1); } - static inline unsigned - log(unsigned n) - { - unsigned r = 0; - for (unsigned i = 1; i < n; ++r) i <<= 1; - return r; + virtual bool writeObject(OutputStream* out, Slice symbols, Slice data, unsigned accessFlags, unsigned alignment) { + cpu_type_t cpuType; + cpu_subtype_t cpuSubType; + switch(info.arch) { + case PlatformInfo::x86_64: + cpuType = CPU_TYPE_X86_64; + cpuSubType = CPU_SUBTYPE_X86_64_ALL; + break; + case PlatformInfo::x86: + cpuType = CPU_TYPE_I386; + cpuSubType = CPU_SUBTYPE_I386_ALL; + break; + case PlatformInfo::PowerPC: + cpuType = CPU_TYPE_POWERPC; + cpuSubType = CPU_SUBTYPE_POWERPC_ALL; + break; + case PlatformInfo::Arm: + cpuType = CPU_TYPE_ARM; + cpuSubType = CPU_SUBTYPE_ARM_V7; + default: + // should never happen (see MachOPlatform declarations at bottom) + fprintf(stderr, "unsupported architecture: %d\n", info.arch); + return false; + } + + const char* segmentName; + const char* sectionName; + if (accessFlags & Writable) { + if (accessFlags & Executable) { + segmentName = "__RWX"; + sectionName = "__rwx"; + } else { + segmentName = "__DATA"; + sectionName = "__data"; + } + } else { + segmentName = "__TEXT"; + sectionName = "__text"; + } + + FileHeader header = { + V4(Magic), // magic + V4(cpuType), + V4(cpuSubType), + V4(MH_OBJECT), // filetype, + V4(2), // ncmds + V4(sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand)), // sizeofcmds + V4(0) // flags + }; + + AddrTy finalSize = pad(data.count); + + SegmentCommand segment = { + V4(Segment), // cmd + V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize + "", // segname + VANY(static_cast(0)), // vmaddr + VANY(static_cast(finalSize)), // vmsize + VANY(static_cast(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand))), // fileoff + VANY(static_cast(finalSize)), // filesize + V4(7), // maxprot + V4(7), // initprot + V4(1), // nsects + V4(0) // flags + }; + + strncpy(segment.segname, segmentName, sizeof(segment.segname)); + + Section sect = { + "", // sectname + "", // segname + VANY(static_cast(0)), // addr + VANY(static_cast(finalSize)), // size + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand)), // offset + V4(log(alignment)), // align + V4(0), // reloff + V4(0), // nreloc + V4(S_REGULAR), // flags + V4(0), // reserved1 + V4(0), // reserved2 + }; + + strncpy(sect.segname, segmentName, sizeof(sect.segname)); + strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); + + StringTable strings; + strings.add(""); + Buffer symbolList; + + for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) { + unsigned offset = strings.length; + strings.write("_", 1); + strings.add(sym->name); + NList symbol = { + V4(offset), // n_un + V1(N_SECT | N_EXT), // n_type + V1(1), // n_sect + V2(0), // n_desc + VANY(static_cast(sym->addr)) // n_value + }; + symbolList.write(&symbol, sizeof(NList)); + } + + SymtabCommand symbolTable = { + V4(LC_SYMTAB), // cmd + V4(sizeof(SymtabCommand)), // cmdsize + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand) + + finalSize), // symoff + V4(symbols.count), // nsyms + V4(sizeof(FileHeader) + + sizeof(SegmentCommand) + + sizeof(Section) + + sizeof(SymtabCommand) + + finalSize + + (sizeof(NList) * symbols.count)), // stroff + V4(strings.length), // strsize + }; + + out->writeChunk(&header, sizeof(header)); + out->writeChunk(&segment, sizeof(segment)); + out->writeChunk(§, sizeof(sect)); + out->writeChunk(&symbolTable, sizeof(symbolTable)); + + out->writeChunk(data.items, data.count); + out->writeRepeat(0, finalSize - data.count); + + out->writeChunk(symbolList.data, symbolList.length); + + out->writeChunk(strings.data, strings.length); } - - class MachOObjectWriter : public ObjectWriter { - public: - - PlatformInfo::Architecture arch; - OutputStream* out; - - MachOObjectWriter(PlatformInfo::Architecture arch, OutputStream* out): - arch(arch), - out(out) {} - - void writeObject(const uint8_t* data, unsigned size, - const char* startName, const char* endName, - const char* segmentName, const char* sectionName, - unsigned alignment, cpu_type_t cpuType, cpu_subtype_t cpuSubType) - { - unsigned startNameLength = strlen(startName) + 1; - unsigned endNameLength = strlen(endName) + 1; - - FileHeader header = { - V4(Magic), // magic - V4(cpuType), - V4(cpuSubType), - V4(MH_OBJECT), // filetype, - V4(2), // ncmds - V4(sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(SymtabCommand)), // sizeofcmds - V4(0) // flags - }; - - SegmentCommand segment = { - V4(Segment), // cmd - V4(sizeof(SegmentCommand) + sizeof(Section)), // cmdsize - "", // segname - VANY(static_cast(0)), // vmaddr - VANY(static_cast(pad(size))), // vmsize - VANY(static_cast(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(SymtabCommand))), // fileoff - VANY(static_cast(pad(size))), // filesize - V4(7), // maxprot - V4(7), // initprot - V4(1), // nsects - V4(0) // flags - }; - - strncpy(segment.segname, segmentName, sizeof(segment.segname)); - - Section sect = { - "", // sectname - "", // segname - VANY(static_cast(0)), // addr - VANY(static_cast(pad(size))), // size - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(SymtabCommand)), // offset - V4(log(alignment)), // align - V4(0), // reloff - V4(0), // nreloc - V4(S_REGULAR), // flags - V4(0), // reserved1 - V4(0), // reserved2 - }; - - strncpy(sect.segname, segmentName, sizeof(sect.segname)); - strncpy(sect.sectname, sectionName, sizeof(sect.sectname)); - - SymtabCommand symbolTable = { - V4(LC_SYMTAB), // cmd - V4(sizeof(SymtabCommand)), // cmdsize - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(SymtabCommand) - + pad(size)), // symoff - V4(2), // nsyms - V4(sizeof(FileHeader) - + sizeof(SegmentCommand) - + sizeof(Section) - + sizeof(SymtabCommand) - + pad(size) - + (sizeof(NList) * 2)), // stroff - V4(1 + startNameLength + endNameLength), // strsize - }; - - NList symbolList[] = { - { - V4(1), // n_un - V1(N_SECT | N_EXT), // n_type - V1(1), // n_sect - V2(0), // n_desc - VANY(static_cast(0)) // n_value - }, - { - V4(1 + startNameLength), // n_un - V1(N_SECT | N_EXT), // n_type - V1(1), // n_sect - V2(0), // n_desc - VANY(static_cast(size)) // n_value - } - }; - - out->writeChunk(&header, sizeof(header)); - out->writeChunk(&segment, sizeof(segment)); - out->writeChunk(§, sizeof(sect)); - out->writeChunk(&symbolTable, sizeof(symbolTable)); - - out->writeChunk(data, size); - out->writeRepeat(0, pad(size) - size); - - out->writeChunk(&symbolList, sizeof(symbolList)); - - out->write(0); - - out->writeChunk(startName, startNameLength); - out->writeChunk(endName, endNameLength); - } - - virtual bool write(uint8_t* data, size_t size, - const char* startName, const char* endName, - unsigned alignment, unsigned accessFlags) - { - - cpu_type_t cpuType; - cpu_subtype_t cpuSubType; - if (arch == PlatformInfo::x86_64) { - cpuType = CPU_TYPE_X86_64; - cpuSubType = CPU_SUBTYPE_X86_64_ALL; - } else if (arch == PlatformInfo::x86) { - cpuType = CPU_TYPE_I386; - cpuSubType = CPU_SUBTYPE_I386_ALL; - } else if (arch == PlatformInfo::PowerPC) { - cpuType = CPU_TYPE_POWERPC; - cpuSubType = CPU_SUBTYPE_POWERPC_ALL; - } else if (arch == PlatformInfo::Arm) { - cpuType = CPU_TYPE_ARM; - cpuSubType = CPU_SUBTYPE_ARM_V7; - } else { - fprintf(stderr, "unsupported architecture: %d\n", arch); - return false; - } - - const char* segmentName; - const char* sectionName; - if (accessFlags & Writable) { - if (accessFlags & Executable) { - segmentName = "__RWX"; - sectionName = "__rwx"; - } else { - segmentName = "__DATA"; - sectionName = "__data"; - } - } else { - segmentName = "__TEXT"; - sectionName = "__text"; - } - - unsigned startNameLength = strlen(startName); - char myStartName[startNameLength + 2]; - myStartName[0] = '_'; - memcpy(myStartName + 1, startName, startNameLength + 1); - - unsigned endNameLength = strlen(endName); - char myEndName[endNameLength + 2]; - myEndName[0] = '_'; - memcpy(myEndName + 1, endName, endNameLength + 1); - - writeObject(data, size, myStartName, myEndName, segmentName, - sectionName, alignment, cpuType, cpuSubType); - - return true; - } - - virtual void dispose() { - delete this; - } - }; MachOPlatform(PlatformInfo::Architecture arch): Platform(PlatformInfo(PlatformInfo::Darwin, arch)) {} - - virtual ObjectWriter* makeObjectWriter(OutputStream* out) { - return new MachOObjectWriter(info.arch, out); - } + }; MachOPlatform darwinx86Platform(PlatformInfo::x86); diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index c9a3fb8d75..e9bc749abc 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -33,18 +33,14 @@ void* operator new(size_t size) { return malloc(size); } -void operator delete(void* mem) { - if(mem) { - free(mem); - } -} +void operator delete(void* mem) { abort(); } namespace { using namespace avian::tools; bool -writeObject(uint8_t* data, unsigned size, OutputStream* out, const char* startName, +writeObject(uint8_t* data, size_t size, OutputStream* out, const char* startName, const char* endName, const char* os, const char* architecture, unsigned alignment, bool writable, bool executable) @@ -56,14 +52,16 @@ writeObject(uint8_t* data, unsigned size, OutputStream* out, const char* startNa return false; } - ObjectWriter* writer = platform->makeObjectWriter(out); + SymbolInfo symbols[2]; + symbols[0].name = startName; + symbols[0].addr = 0; + symbols[1].name = endName; + symbols[1].addr = size; - bool success = writer->write(data, size, startName, endName, alignment, - ObjectWriter::Readable | (writable ? ObjectWriter::Writable : 0) | (executable ? ObjectWriter::Executable : 0)); + unsigned accessFlags = (writable ? Platform::Writable : 0) | (executable ? Platform::Executable : 0); - writer->dispose(); + return platform->writeObject(out, Slice(symbols, 2), Slice(data, size), accessFlags, alignment); - return success; } void diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 37bf643a95..aab60feb90 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "tools.h" @@ -81,169 +82,193 @@ pad(unsigned n) using namespace avian::tools; -void -writeObject(const uint8_t* data, unsigned size, OutputStream* out, - const char* startName, const char* endName, - const char* sectionName, int machine, int machineMask, - int sectionMask) -{ - const unsigned sectionCount = 1; - const unsigned symbolCount = 2; - - const unsigned sectionNumber = 1; - - const unsigned startNameLength = strlen(startName) + 1; - const unsigned endNameLength = strlen(endName) + 1; - - const unsigned startNameOffset = 4; - const unsigned endNameOffset = startNameOffset + startNameLength; - - IMAGE_FILE_HEADER fileHeader = { - machine, // Machine - sectionCount, // NumberOfSections - 0, // TimeDateStamp - sizeof(IMAGE_FILE_HEADER) - + sizeof(IMAGE_SECTION_HEADER) - + pad(size), // PointerToSymbolTable - symbolCount, // NumberOfSymbols - 0, // SizeOfOptionalHeader - IMAGE_FILE_RELOCS_STRIPPED - | IMAGE_FILE_LINE_NUMS_STRIPPED - | machineMask // Characteristics - }; - - IMAGE_SECTION_HEADER sectionHeader = { - "", // Name - 0, // PhysicalAddress - 0, // VirtualAddress - pad(size), // SizeOfRawData - sizeof(IMAGE_FILE_HEADER) - + sizeof(IMAGE_SECTION_HEADER), // PointerToRawData - 0, // PointerToRelocations - 0, // PointerToLinenumbers - 0, // NumberOfRelocations - 0, // NumberOfLinenumbers - sectionMask // Characteristics - }; - - strncpy(reinterpret_cast(sectionHeader.Name), sectionName, - sizeof(sectionHeader.Name)); - - IMAGE_SYMBOL startSymbol = { - { 0 }, // Name - 0, // Value - sectionNumber, // SectionNumber - 0, // Type - 2, // StorageClass - 0, // NumberOfAuxSymbols - }; - startSymbol.N.Name.Long = startNameOffset; - - IMAGE_SYMBOL endSymbol = { - { 0 }, // Name - size, // Value - sectionNumber, // SectionNumber - 0, // Type - 2, // StorageClass - 0, // NumberOfAuxSymbols - }; - endSymbol.N.Name.Long = endNameOffset; - - out->writeChunk(&fileHeader, sizeof(fileHeader)); - out->writeChunk(§ionHeader, sizeof(sectionHeader)); - - out->writeChunk(data, size); - out->writeRepeat(0, pad(size) - size); - - out->writeChunk(&startSymbol, sizeof(startSymbol)); - out->writeChunk(&endSymbol, sizeof(endSymbol)); - - uint32_t symbolTableSize = endNameOffset + endNameLength; - out->writeChunk(&symbolTableSize, 4); - - out->writeChunk(startName, startNameLength); - out->writeChunk(endName, endNameLength); -} - template class WindowsPlatform : public Platform { public: - class PEObjectWriter : public ObjectWriter { + + class FileWriter { public: + unsigned sectionCount; + unsigned symbolCount; + unsigned dataStart; + unsigned dataOffset; - OutputStream* out; + IMAGE_FILE_HEADER header; - PEObjectWriter(OutputStream* out): - out(out) {} + StringTable strings; + Buffer symbols; - virtual bool write(uint8_t* data, size_t size, - const char* startName, const char* endName, - unsigned alignment, unsigned accessFlags) + FileWriter(unsigned machine, unsigned machineMask, unsigned symbolCount): + sectionCount(0), + symbolCount(symbolCount), + dataStart(sizeof(IMAGE_FILE_HEADER)), + dataOffset(0) { - int machine; - int machineMask; - - if (BytesPerWord == 8) { - machine = IMAGE_FILE_MACHINE_AMD64; - machineMask = 0; - } else { // if (BytesPerWord == 8) - machine = IMAGE_FILE_MACHINE_I386; - machineMask = IMAGE_FILE_32BIT_MACHINE; - } - - int sectionMask; - switch (alignment) { - case 0: - case 1: - sectionMask = IMAGE_SCN_ALIGN_1BYTES; - break; - case 2: - sectionMask = IMAGE_SCN_ALIGN_2BYTES; - break; - case 4: - sectionMask = IMAGE_SCN_ALIGN_4BYTES; - break; - case 8: - sectionMask = IMAGE_SCN_ALIGN_8BYTES; - break; - default: - fprintf(stderr, "unsupported alignment: %d\n", alignment); - return false; - } - - sectionMask |= IMAGE_SCN_MEM_READ; - - const char* sectionName; - if (accessFlags & ObjectWriter::Writable) { - if (accessFlags & ObjectWriter::Executable) { - sectionName = ".rwx"; - sectionMask |= IMAGE_SCN_MEM_WRITE - | IMAGE_SCN_MEM_EXECUTE - | IMAGE_SCN_CNT_CODE; - } else { - sectionName = ".data"; - sectionMask |= IMAGE_SCN_MEM_WRITE; - } - } else { - sectionName = ".text"; - sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; - } - - writeObject(data, size, out, startName, endName, sectionName, machine, - machineMask, sectionMask); - - return true; + header.Machine = machine; + // header.NumberOfSections = sectionCount; + header.TimeDateStamp = 0; + // header.PointerToSymbolTable = sizeof(IMAGE_FILE_HEADER) + // + sizeof(IMAGE_SECTION_HEADER) + // + pad(size); + // header.NumberOfSymbols = symbolCount; + header.SizeOfOptionalHeader = 0; + header.Characteristics = IMAGE_FILE_RELOCS_STRIPPED + | IMAGE_FILE_LINE_NUMS_STRIPPED + | machineMask; } - virtual void dispose() { - delete this; + void writeHeader(OutputStream* out) { + header.NumberOfSections = sectionCount; + header.PointerToSymbolTable = dataStart + dataOffset; + printf("symbol table start: 0x%x\n", header.PointerToSymbolTable); + dataOffset = pad(dataOffset + symbolCount * sizeof(IMAGE_SYMBOL)); + printf("string table start: 0x%x\n", dataStart + dataOffset); + header.NumberOfSymbols = symbolCount; + out->writeChunk(&header, sizeof(IMAGE_FILE_HEADER)); } + void addSymbol(String name, unsigned addr, unsigned sectionNumber, unsigned type, unsigned storageClass) { + unsigned nameOffset = strings.add(name); + IMAGE_SYMBOL symbol = { + { 0 }, // Name + addr, // Value + sectionNumber, // SectionNumber + type, // Type + storageClass, // StorageClass + 0, // NumberOfAuxSymbols + }; + symbol.N.Name.Long = nameOffset+4; + symbols.write(&symbol, sizeof(IMAGE_SYMBOL)); + } + + void writeData(OutputStream* out) { + out->writeChunk(symbols.data, symbols.length); + uint32_t size = strings.length + 4; + out->writeChunk(&size, 4); + out->writeChunk(strings.data, strings.length); + } + }; + + class SectionWriter { + public: + FileWriter& file; + IMAGE_SECTION_HEADER header; + size_t dataSize; + size_t finalSize; + const uint8_t* data; + unsigned dataOffset; + + SectionWriter( + FileWriter& file, + const char* name, + unsigned sectionMask, + const uint8_t* data, + size_t dataSize): + + file(file), + data(data), + dataSize(dataSize), + finalSize(pad(dataSize)) + { + file.sectionCount++; + file.dataStart += sizeof(IMAGE_SECTION_HEADER); + strcpy(reinterpret_cast(header.Name), name); + header.Misc.VirtualSize = 0; + header.SizeOfRawData = finalSize; + // header.PointerToRawData = file.dataOffset; + dataOffset = file.dataOffset; + file.dataOffset += finalSize; + header.PointerToRelocations = 0; + header.PointerToLinenumbers = 0; + header.NumberOfRelocations = 0; + header.NumberOfLinenumbers = 0; + header.Characteristics = sectionMask; + } + + void writeHeader(OutputStream* out) { + header.PointerToRawData = dataOffset + file.dataStart; + printf("section %s: data at 0x%x, ending at 0x%x\n", header.Name, header.PointerToRawData, header.PointerToRawData + header.SizeOfRawData); + out->writeChunk(&header, sizeof(IMAGE_SECTION_HEADER)); + } + + void writeData(OutputStream* out) { + out->writeChunk(data, dataSize); + out->writeRepeat(0, finalSize - dataSize); + } + + }; - virtual ObjectWriter* makeObjectWriter(OutputStream* out) { - return new PEObjectWriter(out); + virtual bool writeObject(OutputStream* out, Slice symbols, Slice data, unsigned accessFlags, unsigned alignment) { + + int machine; + int machineMask; + + if (BytesPerWord == 8) { + machine = IMAGE_FILE_MACHINE_AMD64; + machineMask = 0; + } else { // if (BytesPerWord == 8) + machine = IMAGE_FILE_MACHINE_I386; + machineMask = IMAGE_FILE_32BIT_MACHINE; + } + + int sectionMask; + switch (alignment) { + case 0: + case 1: + sectionMask = IMAGE_SCN_ALIGN_1BYTES; + break; + case 2: + sectionMask = IMAGE_SCN_ALIGN_2BYTES; + break; + case 4: + sectionMask = IMAGE_SCN_ALIGN_4BYTES; + break; + case 8: + sectionMask = IMAGE_SCN_ALIGN_8BYTES; + break; + default: + fprintf(stderr, "unsupported alignment: %d\n", alignment); + return false; + } + + sectionMask |= IMAGE_SCN_MEM_READ; + + const char* sectionName; + if (accessFlags & Platform::Writable) { + if (accessFlags & Platform::Executable) { + sectionName = ".rwx"; + sectionMask |= IMAGE_SCN_MEM_WRITE + | IMAGE_SCN_MEM_EXECUTE + | IMAGE_SCN_CNT_CODE; + } else { + sectionName = ".data"; + sectionMask |= IMAGE_SCN_MEM_WRITE; + } + } else { + sectionName = ".text"; + sectionMask |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE; + } + + FileWriter file(machine, machineMask, symbols.count); + + SectionWriter section(file, sectionName, sectionMask, data.items, data.count); + + file.writeHeader(out); + + for(SymbolInfo* sym = symbols.begin(); sym != symbols.end(); sym++) { + file.addSymbol(sym->name, sym->addr, 1, 0, 2); + } + + section.writeHeader(out); + + section.writeData(out); + + file.writeData(out); + + return true; + } WindowsPlatform(): @@ -253,4 +278,4 @@ public: WindowsPlatform<4> windows32Platform; WindowsPlatform<8> windows64Platform; -} +} // namespace diff --git a/src/binaryToObject/tools.cpp b/src/binaryToObject/tools.cpp index 0768e8a24b..4f8b8170d0 100644 --- a/src/binaryToObject/tools.cpp +++ b/src/binaryToObject/tools.cpp @@ -19,6 +19,38 @@ namespace avian { namespace tools { +String::String(const char* text): + text(text), + length(strlen(text)) {} + +Buffer::Buffer(): + capacity(100), + length(0), + data((uint8_t*)malloc(capacity)) {} + +Buffer::~Buffer() { + free(data); +} + +void Buffer::ensure(size_t more) { + if(length + more > capacity) { + capacity = capacity * 2 + more; + data = (uint8_t*)realloc(data, capacity); + } +} + +void Buffer::write(const void* d, size_t size) { + ensure(size); + memcpy(data + length, d, size); + length += size; +} + +unsigned StringTable::add(String str) { + unsigned offset = Buffer::length; + Buffer::write(str.text, str.length + 1); + return offset; +} + void OutputStream::write(uint8_t byte) { writeChunk(&byte, 1); } diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h index 9ba285dd66..bc3d1f4f19 100644 --- a/src/binaryToObject/tools.h +++ b/src/binaryToObject/tools.h @@ -35,20 +35,62 @@ public: virtual void write(uint8_t byte); }; -class ObjectWriter { +class String { public: + const char* text; + size_t length; - enum AccessFlags { - Readable = 1 << 0, - Writable = 1 << 1, - Executable = 1 << 2 - }; + String(const char* text); +}; - virtual bool write(uint8_t* data, size_t size, - const char* startName, const char* endName, - unsigned alignment, unsigned accessFlags) = 0; +class SymbolInfo { +public: + unsigned addr; + String name; - virtual void dispose() = 0; + inline SymbolInfo(uint64_t addr, const char* name): + addr(addr), + name(name) {} + + inline SymbolInfo(): + name("") {} +}; + +class Buffer { +public: + size_t capacity; + size_t length; + uint8_t* data; + + Buffer(); + ~Buffer(); + + void ensure(size_t more); + void write(const void* d, size_t size); +}; + +class StringTable : public Buffer { +public: + unsigned add(String str); +}; + +template +class Slice { +public: + T* items; + size_t count; + + inline Slice(T* items, size_t count): + items(items), + count(count) {} + + inline T* begin() { + return items; + } + + inline T* end() { + return items + count; + } }; class PlatformInfo { @@ -98,7 +140,12 @@ public: first = this; } - virtual ObjectWriter* makeObjectWriter(OutputStream* out) = 0; + enum AccessFlags { + Writable = 1 << 0, + Executable = 1 << 1 + }; + + virtual bool writeObject(OutputStream* out, Slice symbols, Slice data, unsigned accessFlags, unsigned alignment) = 0; static Platform* getPlatform(PlatformInfo info); }; From b0dd39aa864b9aab10a95f27d4dbf813d4e505bb Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 30 Apr 2012 09:43:24 -0600 Subject: [PATCH 068/140] fix darwin arm binaryToObject support (just a missing break...) --- src/binaryToObject/mach-o.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index 246940329f..ef9cbe5f30 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -159,6 +159,7 @@ public: case PlatformInfo::Arm: cpuType = CPU_TYPE_ARM; cpuSubType = CPU_SUBTYPE_ARM_V7; + break; default: // should never happen (see MachOPlatform declarations at bottom) fprintf(stderr, "unsupported architecture: %d\n", info.arch); From e6afc6c321181871ac4a0b707d40e3ebc2490e5b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 2 May 2012 11:41:36 -0600 Subject: [PATCH 069/140] set Thread.interrupted to true if thread is interrupted outside wait or sleep This is the correct behavior according to the Thread.interrupt JavaDoc, and it fixes an intermittent hang on exit in Eclipse. --- src/classpath-avian.cpp | 6 ++++++ src/classpath-openjdk.cpp | 20 ++++++++++++++++++-- src/machine.h | 4 ++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 39cde4ff83..5df85fa6b6 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -54,6 +54,12 @@ class MyClasspath : public Classpath { root(t, Machine::BootLoader), 0, 0, group, 0); } + virtual void + clearInterrupted(Thread*) + { + // ignore + } + virtual void runThread(Thread* t) { diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 78cb98083a..721889e452 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -344,6 +344,9 @@ makeClassNameString(Thread* t, object name) void interceptFileOperations(Thread*); +void +clearInterrupted(Thread*); + class MyClasspath : public Classpath { public: static const unsigned BufferSize = 1024; @@ -506,6 +509,12 @@ class MyClasspath : public Classpath { return thread; } + virtual void + clearInterrupted(Thread* t) + { + local::clearInterrupted(t); + } + virtual void runThread(Thread* t) { @@ -2212,6 +2221,14 @@ interruptLock(Thread* t, object thread) return threadInterruptLock(t, thread); } +void +clearInterrupted(Thread* t) +{ + monitorAcquire(t, local::interruptLock(t, t->javaThread)); + threadInterrupted(t, t->javaThread) = false; + monitorRelease(t, local::interruptLock(t, t->javaThread)); +} + bool pipeAvailable(int fd, int* available) { @@ -3350,9 +3367,8 @@ jvmInterrupt(Thread* t, uintptr_t* arguments) Thread* p = reinterpret_cast(threadPeer(t, *thread)); if (p) { interrupt(t, p); - } else { - threadInterrupted(t, *thread) = true; } + threadInterrupted(t, *thread) = true; monitorRelease(t, local::interruptLock(t, *thread)); return 1; diff --git a/src/machine.h b/src/machine.h index cdb3ecf039..eea9cc506b 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1577,6 +1577,9 @@ class Classpath { virtual object makeThread(Thread* t, Thread* parent) = 0; + virtual void + clearInterrupted(Thread* t) = 0; + virtual void runThread(Thread* t) = 0; @@ -3215,6 +3218,7 @@ wait(Thread* t, object o, int64_t milliseconds) if (interrupted) { if (t->m->alive or (t->flags & Thread::DaemonFlag) == 0) { + t->m->classpath->clearInterrupted(t); throwNew(t, Machine::InterruptedExceptionType); } else { throw_(t, root(t, Machine::Shutdown)); From 2107a0962310d529caaf9f2e5881e9261b8a03f7 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 2 May 2012 18:00:12 -0600 Subject: [PATCH 070/140] fix incorrect argument marshalling in Unsafe.{allocate|free}Memory This was causing UnsafeTest to crash on PowerPC. --- src/builtin.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/builtin.cpp b/src/builtin.cpp index f7f2c12d29..7cd41cb3b6 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -332,7 +332,8 @@ extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_allocateMemory (Thread* t, object, uintptr_t* arguments) { - void* p = malloc(arguments[1]); + int64_t size; memcpy(&size, arguments + 1, 8); + void* p = malloc(size); if (p) { return reinterpret_cast(p); } else { @@ -344,9 +345,9 @@ extern "C" JNIEXPORT void JNICALL Avian_sun_misc_Unsafe_freeMemory (Thread*, object, uintptr_t* arguments) { - void* p = reinterpret_cast(arguments[1]); + int64_t p; memcpy(&p, arguments + 1, 8); if (p) { - free(p); + free(reinterpret_cast(p)); } } From 2fa7fa0e832935e8d043ef5fefe8da4b9fcceb8a Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 30 Apr 2012 12:36:54 -0600 Subject: [PATCH 071/140] correct bootimage dependency chain --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index ff6cf9855b..686f9ec5ea 100755 --- a/makefile +++ b/makefile @@ -916,7 +916,7 @@ else endif $(strip) $(strip-all) $(@) -$(bootimage-generator): +$(bootimage-generator): $(bootimage-generator-objects) $(MAKE) mode=$(mode) \ arch=$(build-arch) \ platform=$(bootimage-platform) \ From 99bc9b1d55033236cd0415e19b18fa7504f34caa Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 30 Apr 2012 12:44:18 -0600 Subject: [PATCH 072/140] prettify SymbolInfo array --- src/binaryToObject/main.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index e9bc749abc..c3f3eb493f 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -52,11 +52,10 @@ writeObject(uint8_t* data, size_t size, OutputStream* out, const char* startName return false; } - SymbolInfo symbols[2]; - symbols[0].name = startName; - symbols[0].addr = 0; - symbols[1].name = endName; - symbols[1].addr = size; + SymbolInfo symbols[] = { + SymbolInfo(0, startName), + SymbolInfo(size, endName) + }; unsigned accessFlags = (writable ? Platform::Writable : 0) | (executable ? Platform::Executable : 0); From b742c58055ad0e65498bcaacf84021704d3e7b00 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Tue, 1 May 2012 13:16:32 -0600 Subject: [PATCH 073/140] directly emit codeimage as a object (binaryToObject is statically linked in), as a stepping stone to including extra symbols in said codeimage --- makefile | 56 +++++++++++++++++++++------------ src/binaryToObject/main.cpp | 2 +- src/binaryToObject/tools.h | 17 ++++++---- src/bootimage.cpp | 63 ++++++++++++++++++++++--------------- src/environment.h | 33 +++++++++++++++++++ src/x86.cpp | 7 +++-- 6 files changed, 122 insertions(+), 56 deletions(-) create mode 100644 src/environment.h diff --git a/makefile b/makefile index 686f9ec5ea..ff1a862afe 100755 --- a/makefile +++ b/makefile @@ -18,6 +18,7 @@ build-platform := \ | sed 's/^cygwin.*$$/cygwin/') arch = $(build-arch) +target-arch = $(arch) bootimage-platform = \ $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) platform = $(bootimage-platform) @@ -185,8 +186,10 @@ endif build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ "-I$(JAVA_HOME)/include/linux" -I$(src) -pthread -converter-cflags = -D__STDC_CONSTANT_MACROS -Isrc/binaryToObject \ - -fno-rtti -fno-exceptions +converter-cflags = -D__STDC_CONSTANT_MACROS -Isrc/binaryToObject -Isrc/ \ + -fno-rtti -fno-exceptions \ + -DAVIAN_TARGET_ARCH=AVIAN_ARCH_UNKNOWN \ + -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_UNKNOWN cflags = $(build-cflags) @@ -223,9 +226,22 @@ ifeq ($(build-arch),powerpc) endif endif -ifeq ($(arch),i386) - pointer-size = 4 +ifeq ($(target-arch),i386) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_X86 endif + +ifeq ($(target-arch),x86_64) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_X86_64 +endif + +ifeq ($(target-arch),powerpc) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_POWERPC +endif + +ifeq ($(target-arch),arm) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_ARM +endif + ifeq ($(arch),powerpc) asm = powerpc pointer-size = 4 @@ -244,9 +260,11 @@ ifeq ($(arch),powerpc) endif endif endif + ifeq ($(arch),arm) asm = arm pointer-size = 4 + ifeq ($(build-platform),darwin) ios = true else @@ -277,7 +295,7 @@ ifeq ($(ios),true) endif ifeq ($(platform),linux) - bootimage-cflags += -DTARGET_PLATFORM_LINUX + cflags += -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_LINUX endif ifeq ($(build-platform),darwin) @@ -287,7 +305,7 @@ ifeq ($(build-platform),darwin) endif ifeq ($(platform),darwin) - bootimage-cflags += -DTARGET_PLATFORM_DARWIN + cflags += -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_DARWIN ifeq (${OSX_SDK_SYSROOT},) OSX_SDK_SYSROOT = 10.4u @@ -364,7 +382,7 @@ ifeq ($(platform),darwin) endif ifeq ($(platform),windows) - bootimage-cflags += -DTARGET_PLATFORM_WINDOWS + cflags += -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_WINDOWS inc = "$(win32)/include" lib = "$(win32)/lib" @@ -378,7 +396,7 @@ ifeq ($(platform),windows) exe-suffix = .exe lflags = -L$(lib) $(common-lflags) -lws2_32 -mwindows -mconsole - cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 -DTARGET_PLATFORM_WINDOWS + cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_WINDOWS ifeq (,$(filter mingw32 cygwin,$(build-platform))) @@ -486,7 +504,7 @@ ifdef msvc -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ -Fd$(build)/$(name).pdb -I"$(zlib)/include" -I$(src) -I"$(build)" \ -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ - -DTARGET_BYTES_PER_WORD=$(pointer-size) -DTARGET_PLATFORM_WINDOWS + -DTARGET_BYTES_PER_WORD=$(pointer-size) -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_WINDOWS shared = -dll lflags = -nologo -LIBPATH:"$(zlib)/lib" -DEFAULTLIB:ws2_32 \ -DEFAULTLIB:zlib -MANIFEST -debug @@ -622,13 +640,16 @@ converter-depends = \ converter-sources = \ - $(src)/binaryToObject/main.cpp \ $(src)/binaryToObject/tools.cpp \ $(src)/binaryToObject/elf.cpp \ $(src)/binaryToObject/mach-o.cpp \ $(src)/binaryToObject/pe.cpp +converter-tool-sources = \ + $(src)/binaryToObject/main.cpp + converter-objects = $(call cpp-objects,$(converter-sources),$(src),$(build)) +converter-tool-objects = $(call cpp-objects,$(converter-tool-sources),$(src),$(build)) converter = $(build)/binaryToObject/binaryToObject static-library = $(build)/lib$(name).a @@ -834,11 +855,11 @@ $(boot-object): $(boot-source) $(boot-javahome-object): $(src)/boot-javahome.cpp $(compile-object) -$(converter-objects): $(build)/binaryToObject/%.o: $(src)/binaryToObject/%.cpp $(converter-depends) +$(converter-objects) $(converter-tool-objects): $(build)/binaryToObject/%.o: $(src)/binaryToObject/%.cpp $(converter-depends) @mkdir -p $(dir $(@)) $(build-cxx) $(converter-cflags) -c $(<) -o $(@) -$(converter): $(converter-objects) +$(converter): $(converter-objects) $(converter-tool-objects) $(build-cc) $(^) -g -o $(@) $(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep) @@ -881,7 +902,7 @@ $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ $(ranlib) $(@) $(bootimage-bin): $(bootimage-generator) - $(<) $(classpath-build) $(@) $(codeimage-bin) + $(<) $(classpath-build) $(@) $(codeimage-object) $(bootimage-object): $(bootimage-bin) $(converter) @echo "creating $(@)" @@ -889,12 +910,6 @@ $(bootimage-object): $(bootimage-bin) $(converter) _binary_bootimage_bin_end $(platform) $(arch) $(pointer-size) \ writable -$(codeimage-object): $(bootimage-bin) $(converter) - @echo "creating $(@)" - $(converter) $(codeimage-bin) $(@) _binary_codeimage_bin_start \ - _binary_codeimage_bin_end $(platform) $(arch) $(pointer-size) \ - executable - executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ $(javahome-object) $(boot-javahome-object) @@ -919,6 +934,7 @@ endif $(bootimage-generator): $(bootimage-generator-objects) $(MAKE) mode=$(mode) \ arch=$(build-arch) \ + target-arch=$(arch) \ platform=$(bootimage-platform) \ openjdk=$(openjdk) \ openjdk-src=$(openjdk-src) \ @@ -930,7 +946,7 @@ $(bootimage-generator): $(bootimage-generator-objects) $(build-bootimage-generator): \ $(vm-objects) $(classpath-object) $(classpath-objects) \ - $(heapwalk-objects) $(bootimage-generator-objects) + $(heapwalk-objects) $(bootimage-generator-objects) $(converter-objects) @echo "linking $(@)" ifeq ($(platform),windows) ifdef msvc diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index c3f3eb493f..00515947e3 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -45,7 +45,7 @@ writeObject(uint8_t* data, size_t size, OutputStream* out, const char* startName const char* architecture, unsigned alignment, bool writable, bool executable) { - Platform* platform = Platform::getPlatform(PlatformInfo(os, architecture)); + Platform* platform = Platform::getPlatform(PlatformInfo(PlatformInfo::osFromString(os), PlatformInfo::archFromString(architecture))); if(!platform) { fprintf(stderr, "unsupported platform: %s/%s\n", os, architecture); diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h index bc3d1f4f19..52ac647bb9 100644 --- a/src/binaryToObject/tools.h +++ b/src/binaryToObject/tools.h @@ -11,6 +11,8 @@ #ifndef AVIAN_TOOLS_H_ #define AVIAN_TOOLS_H_ +#include "environment.h" + namespace avian { namespace tools { @@ -96,11 +98,18 @@ public: class PlatformInfo { public: enum OperatingSystem { - Linux, Windows, Darwin, UnknownOS + Linux = AVIAN_PLATFORM_LINUX, + Windows = AVIAN_PLATFORM_WINDOWS, + Darwin = AVIAN_PLATFORM_DARWIN, + UnknownOS = AVIAN_PLATFORM_UNKNOWN }; enum Architecture { - x86, x86_64, PowerPC, Arm, UnknownArch + x86 = AVIAN_ARCH_X86, + x86_64 = AVIAN_ARCH_X86_64, + PowerPC = AVIAN_ARCH_POWERPC, + Arm = AVIAN_ARCH_ARM, + UnknownArch = AVIAN_ARCH_UNKNOWN }; const OperatingSystem os; @@ -113,10 +122,6 @@ public: os(os), arch(arch) {} - inline PlatformInfo(const char* os, const char* arch): - os(osFromString(os)), - arch(archFromString(arch)) {} - inline bool operator == (const PlatformInfo& other) { return os == other.os && arch == other.arch; } diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 3d75f4401c..1571f5f9ca 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -16,12 +16,14 @@ #include "stream.h" #include "assembler.h" #include "target.h" +#include "binaryToObject/tools.h" // since we aren't linking against libstdc++, we must implement this // ourselves: extern "C" void __cxa_pure_virtual(void) { abort(); } using namespace vm; +using namespace avian::tools; namespace { @@ -1285,7 +1287,7 @@ targetThunk(BootImage::Thunk t) } void -writeBootImage2(Thread* t, FILE* bootimageOutput, FILE* codeOutput, +writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutput, BootImage* image, uint8_t* code, const char* className, const char* methodName, const char* methodSpec) { @@ -1593,17 +1595,13 @@ writeBootImage2(Thread* t, FILE* bootimageOutput, FILE* codeOutput, #include "bootimage-fields.cpp" #undef THUNK_FIELD - fwrite(&targetImage, sizeof(BootImage), 1, bootimageOutput); + bootimageOutput->writeChunk(&targetImage, sizeof(BootImage)); } - fwrite(bootClassTable, image->bootClassCount * sizeof(unsigned), 1, - bootimageOutput); - fwrite(appClassTable, image->appClassCount * sizeof(unsigned), 1, - bootimageOutput); - fwrite(stringTable, image->stringCount * sizeof(unsigned), 1, - bootimageOutput); - fwrite(callTable, image->callCount * sizeof(unsigned) * 2, 1, - bootimageOutput); + bootimageOutput->writeChunk(bootClassTable, image->bootClassCount * sizeof(unsigned)); + bootimageOutput->writeChunk(appClassTable, image->appClassCount * sizeof(unsigned)); + bootimageOutput->writeChunk(stringTable, image->stringCount * sizeof(unsigned)); + bootimageOutput->writeChunk(callTable, image->callCount * sizeof(unsigned) * 2); unsigned offset = sizeof(BootImage) + (image->bootClassCount * sizeof(unsigned)) @@ -1613,24 +1611,40 @@ writeBootImage2(Thread* t, FILE* bootimageOutput, FILE* codeOutput, while (offset % TargetBytesPerWord) { uint8_t c = 0; - fwrite(&c, 1, 1, bootimageOutput); + bootimageOutput->write(c); ++ offset; } - fwrite(heapMap, pad(heapMapSize(image->heapSize), TargetBytesPerWord), 1, - bootimageOutput); + bootimageOutput->writeChunk(heapMap, pad(heapMapSize(image->heapSize), TargetBytesPerWord)); - fwrite(heap, pad(image->heapSize, TargetBytesPerWord), 1, bootimageOutput); + bootimageOutput->writeChunk(heap, pad(image->heapSize, TargetBytesPerWord)); - fwrite(code, pad(image->codeSize, TargetBytesPerWord), 1, codeOutput); + // fwrite(code, pad(image->codeSize, TargetBytesPerWord), 1, codeOutput); + + Platform* platform = Platform::getPlatform(PlatformInfo((PlatformInfo::OperatingSystem)AVIAN_TARGET_PLATFORM, (PlatformInfo::Architecture)AVIAN_TARGET_ARCH)); + + // if(!platform) { + // fprintf(stderr, "unsupported platform: %s/%s\n", os, architecture); + // return false; + // } + + const char* const startName = "_binary_codeimage_bin_start"; + const char* const endName = "_binary_codeimage_bin_end"; + + SymbolInfo symbols[] = { + SymbolInfo(0, startName), + SymbolInfo(image->codeSize, endName) + }; + + platform->writeObject(codeOutput, Slice(symbols, 2), Slice(code, image->codeSize), Platform::Executable, TargetBytesPerWord); } } uint64_t writeBootImage(Thread* t, uintptr_t* arguments) { - FILE* bootimageOutput = reinterpret_cast(arguments[0]); - FILE* codeOutput = reinterpret_cast(arguments[1]); + OutputStream* bootimageOutput = reinterpret_cast(arguments[0]); + OutputStream* codeOutput = reinterpret_cast(arguments[1]); BootImage* image = reinterpret_cast(arguments[2]); uint8_t* code = reinterpret_cast(arguments[3]); const char* className = reinterpret_cast(arguments[4]); @@ -1679,20 +1693,20 @@ main(int ac, const char** av) enter(t, Thread::ActiveState); enter(t, Thread::IdleState); - FILE* bootimageOutput = vm::fopen(av[2], "wb"); - if (bootimageOutput == 0) { + FileOutputStream bootimageOutput(av[2]); + if (!bootimageOutput.isValid()) { fprintf(stderr, "unable to open %s\n", av[2]); return -1; } - FILE* codeOutput = vm::fopen(av[3], "wb"); - if (codeOutput == 0) { + FileOutputStream codeOutput(av[3]); + if (!codeOutput.isValid()) { fprintf(stderr, "unable to open %s\n", av[3]); return -1; } - uintptr_t arguments[] = { reinterpret_cast(bootimageOutput), - reinterpret_cast(codeOutput), + uintptr_t arguments[] = { reinterpret_cast(&bootimageOutput), + reinterpret_cast(&codeOutput), reinterpret_cast(&image), reinterpret_cast(code), reinterpret_cast(ac > 4 ? av[4] : 0), @@ -1701,9 +1715,6 @@ main(int ac, const char** av) run(t, writeBootImage, arguments); - fclose(codeOutput); - fclose(bootimageOutput); - if (t->exception) { printTrace(t, t->exception); return -1; diff --git a/src/environment.h b/src/environment.h new file mode 100644 index 0000000000..53a309057e --- /dev/null +++ b/src/environment.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2008-2011, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_ENVIRONMENT_H +#define AVIAN_ENVIRONMENT_H + +#ifndef AVIAN_TARGET_PLATFORM +#error build system should have defined AVIAN_TARGET_PLATFORM +#endif + +#ifndef AVIAN_TARGET_ARCH +#error build system should have defined AVIAN_TARGET_ARCH +#endif + +#define AVIAN_PLATFORM_UNKNOWN 0 +#define AVIAN_PLATFORM_LINUX 1 +#define AVIAN_PLATFORM_WINDOWS 2 +#define AVIAN_PLATFORM_DARWIN 3 + +#define AVIAN_ARCH_UNKNOWN 0 +#define AVIAN_ARCH_X86 (1 << 8) +#define AVIAN_ARCH_X86_64 (2 << 8) +#define AVIAN_ARCH_ARM (3 << 8) +#define AVIAN_ARCH_POWERPC (4 << 8) + +#endif \ No newline at end of file diff --git a/src/x86.cpp b/src/x86.cpp index bd6c418417..89d6f5df25 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -8,6 +8,7 @@ There is NO WARRANTY for this software. See license.txt for details. */ +#include "environment.h" #include "assembler.h" #include "target.h" #include "vector.h" @@ -2816,7 +2817,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned frameFootprint(unsigned footprint) { -#ifdef TARGET_PLATFORM_WINDOWS +#if AVIAN_TARGET_PLATFORM == AVIAN_PLATFORM_WINDOWS return max(footprint, StackAlignmentInWords); #else return max(footprint > argumentRegisterCount() ? @@ -2838,7 +2839,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned argumentRegisterCount() { -#ifdef TARGET_PLATFORM_WINDOWS +#if AVIAN_TARGET_PLATFORM == AVIAN_PLATFORM_WINDOWS if (TargetBytesPerWord == 8) return 4; else #else if (TargetBytesPerWord == 8) return 6; else @@ -2849,7 +2850,7 @@ class MyArchitecture: public Assembler::Architecture { virtual int argumentRegister(unsigned index) { assert(&c, TargetBytesPerWord == 8); switch (index) { -#ifdef TARGET_PLATFORM_WINDOWS +#if AVIAN_TARGET_PLATFORM == AVIAN_PLATFORM_WINDOWS case 0: return rcx; case 1: From a09736e749ef8bf37f5c5b7729afcbc236c253af Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 2 May 2012 09:49:31 -0600 Subject: [PATCH 074/140] write java symbols to bootimage --- src/binaryToObject/tools.h | 30 +++++++++++++++ src/bootimage.cpp | 39 ++++++++++++++----- src/compile.cpp | 76 ++++++++++++++++++++++++++++---------- src/interpret.cpp | 4 ++ src/processor.h | 10 +++++ 5 files changed, 130 insertions(+), 29 deletions(-) diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h index 52ac647bb9..dffbb96668 100644 --- a/src/binaryToObject/tools.h +++ b/src/binaryToObject/tools.h @@ -12,6 +12,7 @@ #define AVIAN_TOOLS_H_ #include "environment.h" +#include namespace avian { @@ -86,6 +87,10 @@ public: items(items), count(count) {} + inline Slice(const Slice& copy): + items(copy.items), + count(copy.count) {} + inline T* begin() { return items; } @@ -95,6 +100,31 @@ public: } }; +template +class DynamicArray : public Slice { +public: + size_t capacity; + + DynamicArray(): + Slice((T*)malloc(10 * sizeof(T)), 0), + capacity(10) {} + ~DynamicArray() { + free(Slice::items); + } + + void ensure(size_t more) { + if(Slice::count + more > capacity) { + capacity = capacity * 2 + more; + Slice::items = (T*)realloc(Slice::items, capacity * sizeof(T)); + } +} + + void add(const T& item) { + ensure(1); + Slice::items[Slice::count++] = item; + } +}; + class PlatformInfo { public: enum OperatingSystem { diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 1571f5f9ca..31edca3490 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1293,6 +1293,32 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp { Zone zone(t->m->system, t->m->heap, 64 * 1024); + class MyCompilationHandler : public Processor::CompilationHandler { + public: + virtual void compiled(const void* code, unsigned size, unsigned frameSize UNUSED, const char* class_, const char* name, const char* spec) { + size_t classLen = strlen(class_); + size_t nameLen = strlen(name); + size_t specLen = strlen(spec); + + char* completeName = (char*)malloc(classLen + nameLen + specLen + 2); + sprintf(completeName, "%s.%s%s", class_, name, spec); + uint64_t offset = reinterpret_cast(code) - codeOffset; + symbols.add(SymbolInfo(offset, completeName)); + // printf("%ld %ld %s.%s%s\n", offset, offset + size, class_, name, spec); + free(completeName); + } + + virtual void dispose() {} + + DynamicArray symbols; + uint64_t codeOffset; + + MyCompilationHandler(uint64_t codeOffset): + codeOffset(codeOffset) {} + } compilationHandler(reinterpret_cast(code)); + + t->m->processor->addCompilationHandler(&compilationHandler); + object classPoolMap; object typeMaps; object constants; @@ -1603,7 +1629,7 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp bootimageOutput->writeChunk(stringTable, image->stringCount * sizeof(unsigned)); bootimageOutput->writeChunk(callTable, image->callCount * sizeof(unsigned) * 2); - unsigned offset = sizeof(BootImage) + unsigned offset = sizeof(BootImage) + (image->bootClassCount * sizeof(unsigned)) + (image->appClassCount * sizeof(unsigned)) + (image->stringCount * sizeof(unsigned)) @@ -1628,15 +1654,10 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp // return false; // } - const char* const startName = "_binary_codeimage_bin_start"; - const char* const endName = "_binary_codeimage_bin_end"; + compilationHandler.symbols.add(SymbolInfo(0, "_binary_codeimage_bin_start")); + compilationHandler.symbols.add(SymbolInfo(image->codeSize, "_binary_codeimage_bin_end")); - SymbolInfo symbols[] = { - SymbolInfo(0, startName), - SymbolInfo(image->codeSize, endName) - }; - - platform->writeObject(codeOutput, Slice(symbols, 2), Slice(code, image->codeSize), Platform::Executable, TargetBytesPerWord); + platform->writeObject(codeOutput, Slice(compilationHandler.symbols), Slice(code, image->codeSize), Platform::Executable, TargetBytesPerWord); } } diff --git a/src/compile.cpp b/src/compile.cpp index 2b415588db..154e80f69b 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -6149,25 +6149,7 @@ FILE* compileLog = 0; void logCompile(MyThread* t, const void* code, unsigned size, const char* class_, - const char* name, const char* spec) -{ - static bool open = false; - if (not open) { - open = true; - const char* path = findProperty(t, "avian.jit.log"); - if (path) { - compileLog = vm::fopen(path, "wb"); - } else if (DebugCompile) { - compileLog = stderr; - } - } - - if (compileLog) { - fprintf(compileLog, "%p %p %s.%s%s\n", - code, static_cast(code) + size, - class_, name, spec); - } -} + const char* name, const char* spec); int resolveIpForwards(Context* context, int start, int end) @@ -8448,6 +8430,24 @@ processor(MyThread* t); void compileThunks(MyThread* t, FixedAllocator* allocator); +class CompilationHandlerList { +public: + CompilationHandlerList(CompilationHandlerList* next, Processor::CompilationHandler* handler): + next(next), + handler(handler) {} + + void dispose(Allocator* allocator) { + if(this) { + next->dispose(allocator); + handler->dispose(); + allocator->free(this, sizeof(*this)); + } + } + + CompilationHandlerList* next; + Processor::CompilationHandler* handler; +}; + class MyProcessor: public Processor { public: class Thunk { @@ -8491,7 +8491,8 @@ class MyProcessor: public Processor { FixedSizeOfArithmeticException), codeAllocator(s, 0, 0), callTableSize(0), - useNativeFeatures(useNativeFeatures) + useNativeFeatures(useNativeFeatures), + compilationHandlers(0) { thunkTable[compileMethodIndex] = voidPointer(local::compileMethod); thunkTable[compileVirtualMethodIndex] = voidPointer(compileVirtualMethod); @@ -8797,6 +8798,7 @@ class MyProcessor: public Processor { t->arch->release(); t->m->heap->free(t, sizeof(*t)); + } virtual void dispose() { @@ -8804,6 +8806,8 @@ class MyProcessor: public Processor { s->freeExecutable(codeAllocator.base, codeAllocator.capacity); } + compilationHandlers->dispose(allocator); + s->handleSegFault(0); allocator->free(this, sizeof(*this)); @@ -8900,6 +8904,10 @@ class MyProcessor: public Processor { codeAllocator.capacity = capacity; } + virtual void addCompilationHandler(CompilationHandler* handler) { + compilationHandlers = new(allocator->allocate(sizeof(CompilationHandlerList))) CompilationHandlerList(compilationHandlers, handler); + } + virtual void compileMethod(Thread* vmt, Zone* zone, object* constants, object* calls, DelayedPromise** addresses, object method, OffsetResolver* resolver) @@ -9055,8 +9063,36 @@ class MyProcessor: public Processor { unsigned callTableSize; bool useNativeFeatures; void* thunkTable[dummyIndex + 1]; + CompilationHandlerList* compilationHandlers; }; +void +logCompile(MyThread* t, const void* code, unsigned size, const char* class_, + const char* name, const char* spec) +{ + static bool open = false; + if (not open) { + open = true; + const char* path = findProperty(t, "avian.jit.log"); + if (path) { + compileLog = vm::fopen(path, "wb"); + } else if (DebugCompile) { + compileLog = stderr; + } + } + + if (compileLog) { + fprintf(compileLog, "%p %p %s.%s%s\n", + code, static_cast(code) + size, + class_, name, spec); + } + + MyProcessor* p = static_cast(t->m->processor); + for(CompilationHandlerList* h = p->compilationHandlers; h; h = h->next) { + h->handler->compiled(code, 0, 0, class_, name, spec); + } +} + void* compileMethod2(MyThread* t, void* ip) { diff --git a/src/interpret.cpp b/src/interpret.cpp index 6f3c853ec6..d38e89b16b 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -3067,6 +3067,10 @@ class MyProcessor: public Processor { abort(s); } + virtual void addCompilationHandler(CompilationHandler* handler) { + abort(s); + } + virtual void compileMethod(vm::Thread*, Zone*, object*, object*, DelayedPromise**, object, OffsetResolver*) { diff --git a/src/processor.h b/src/processor.h index 71defc268e..3794570b14 100644 --- a/src/processor.h +++ b/src/processor.h @@ -41,6 +41,13 @@ class Processor { virtual unsigned count() = 0; }; + class CompilationHandler { + public: + virtual void compiled(const void* code, unsigned size, unsigned frameSize, const char* class_, const char* name, const char* spec) = 0; + + virtual void dispose() = 0; + }; + virtual Thread* makeThread(Machine* m, object javaThread, Thread* parent) = 0; @@ -120,6 +127,9 @@ class Processor { virtual void initialize(BootImage* image, uint8_t* code, unsigned capacity) = 0; + virtual void + addCompilationHandler(CompilationHandler* handler) = 0; + virtual void compileMethod(Thread* t, Zone* zone, object* constants, object* calls, DelayedPromise** addresses, object method, From 5724baad41da6673a8ab9d7ef9e7de1019e60392 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 2 May 2012 10:22:44 -0600 Subject: [PATCH 075/140] free symbol names after writing codeimage --- src/binaryToObject/tools.h | 4 ++++ src/bootimage.cpp | 11 +++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h index dffbb96668..f287a56b99 100644 --- a/src/binaryToObject/tools.h +++ b/src/binaryToObject/tools.h @@ -44,6 +44,10 @@ public: size_t length; String(const char* text); + + inline String(const char* text, size_t length): + text(text), + length(length) {} }; class SymbolInfo { diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 31edca3490..67e89db8fe 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1295,7 +1295,7 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp class MyCompilationHandler : public Processor::CompilationHandler { public: - virtual void compiled(const void* code, unsigned size, unsigned frameSize UNUSED, const char* class_, const char* name, const char* spec) { + virtual void compiled(const void* code, unsigned size UNUSED, unsigned frameSize UNUSED, const char* class_, const char* name, const char* spec) { size_t classLen = strlen(class_); size_t nameLen = strlen(name); size_t specLen = strlen(spec); @@ -1305,7 +1305,6 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp uint64_t offset = reinterpret_cast(code) - codeOffset; symbols.add(SymbolInfo(offset, completeName)); // printf("%ld %ld %s.%s%s\n", offset, offset + size, class_, name, spec); - free(completeName); } virtual void dispose() {} @@ -1654,10 +1653,14 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp // return false; // } - compilationHandler.symbols.add(SymbolInfo(0, "_binary_codeimage_bin_start")); - compilationHandler.symbols.add(SymbolInfo(image->codeSize, "_binary_codeimage_bin_end")); + compilationHandler.symbols.add(SymbolInfo(0, strdup("_binary_codeimage_bin_start"))); + compilationHandler.symbols.add(SymbolInfo(image->codeSize, strdup("_binary_codeimage_bin_end"))); platform->writeObject(codeOutput, Slice(compilationHandler.symbols), Slice(code, image->codeSize), Platform::Executable, TargetBytesPerWord); + + for(SymbolInfo* sym = compilationHandler.symbols.begin(); sym != compilationHandler.symbols.end(); sym++) { + free(const_cast((const void*)sym->name.text)); + } } } From 53225edbfedd9f7aab4176933494fa2bf6fe1287 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 2 May 2012 12:13:55 -0600 Subject: [PATCH 076/140] remove debug logging --- src/binaryToObject/pe.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index aab60feb90..ddad7b3bb6 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -121,9 +121,7 @@ public: void writeHeader(OutputStream* out) { header.NumberOfSections = sectionCount; header.PointerToSymbolTable = dataStart + dataOffset; - printf("symbol table start: 0x%x\n", header.PointerToSymbolTable); dataOffset = pad(dataOffset + symbolCount * sizeof(IMAGE_SYMBOL)); - printf("string table start: 0x%x\n", dataStart + dataOffset); header.NumberOfSymbols = symbolCount; out->writeChunk(&header, sizeof(IMAGE_FILE_HEADER)); } @@ -188,7 +186,6 @@ public: void writeHeader(OutputStream* out) { header.PointerToRawData = dataOffset + file.dataStart; - printf("section %s: data at 0x%x, ending at 0x%x\n", header.Name, header.PointerToRawData, header.PointerToRawData + header.SizeOfRawData); out->writeChunk(&header, sizeof(IMAGE_SECTION_HEADER)); } From 132af5f70e917d04f998c1d79bee74ff8f0df188 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 2 May 2012 13:38:00 -0600 Subject: [PATCH 077/140] fix windows build --- makefile | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/makefile b/makefile index ff1a862afe..592b33e4cd 100755 --- a/makefile +++ b/makefile @@ -226,22 +226,6 @@ ifeq ($(build-arch),powerpc) endif endif -ifeq ($(target-arch),i386) - cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_X86 -endif - -ifeq ($(target-arch),x86_64) - cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_X86_64 -endif - -ifeq ($(target-arch),powerpc) - cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_POWERPC -endif - -ifeq ($(target-arch),arm) - cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_ARM -endif - ifeq ($(arch),powerpc) asm = powerpc pointer-size = 4 @@ -720,6 +704,22 @@ ifeq ($(tails),true) extra.Tails endif +ifeq ($(target-arch),i386) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_X86 +endif + +ifeq ($(target-arch),x86_64) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_X86_64 +endif + +ifeq ($(target-arch),powerpc) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_POWERPC +endif + +ifeq ($(target-arch),arm) + cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_ARM +endif + class-name = $(patsubst $(1)/%.class,%,$(2)) class-names = $(foreach x,$(2),$(call class-name,$(1),$(x))) From d76807d9e0fc144aef8c5cb8a3b6283ace4dc37d Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 2 May 2012 14:52:19 -0600 Subject: [PATCH 078/140] add back pointer-size assignment in makefile for i386 (accidentally removed) --- makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/makefile b/makefile index 592b33e4cd..b94ad9c777 100755 --- a/makefile +++ b/makefile @@ -226,6 +226,10 @@ ifeq ($(build-arch),powerpc) endif endif +ifeq ($(arch),i386) + pointer-size = 4 +endif + ifeq ($(arch),powerpc) asm = powerpc pointer-size = 4 From 1b5f37c9dea11025ec0a8bde8cf86333b90900f3 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 3 May 2012 08:45:17 -0600 Subject: [PATCH 079/140] correctly define the target platform in the case of a bootimage build --- makefile | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/makefile b/makefile index b94ad9c777..ff01cd7ba2 100755 --- a/makefile +++ b/makefile @@ -22,6 +22,7 @@ target-arch = $(arch) bootimage-platform = \ $(subst cygwin,windows,$(subst mingw32,windows,$(build-platform))) platform = $(bootimage-platform) +target-platform = $(platform) mode = fast process = compile @@ -282,10 +283,6 @@ ifeq ($(ios),true) cflags += -DAVIAN_IOS endif -ifeq ($(platform),linux) - cflags += -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_LINUX -endif - ifeq ($(build-platform),darwin) build-cflags = $(common-cflags) -fPIC -fvisibility=hidden -I$(src) cflags += -I/System/Library/Frameworks/JavaVM.framework/Headers/ @@ -293,8 +290,6 @@ ifeq ($(build-platform),darwin) endif ifeq ($(platform),darwin) - cflags += -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_DARWIN - ifeq (${OSX_SDK_SYSROOT},) OSX_SDK_SYSROOT = 10.4u endif @@ -370,8 +365,6 @@ ifeq ($(platform),darwin) endif ifeq ($(platform),windows) - cflags += -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_WINDOWS - inc = "$(win32)/include" lib = "$(win32)/lib" @@ -384,7 +377,7 @@ ifeq ($(platform),windows) exe-suffix = .exe lflags = -L$(lib) $(common-lflags) -lws2_32 -mwindows -mconsole - cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_WINDOWS + cflags = -I$(inc) $(common-cflags) -DWINVER=0x0500 ifeq (,$(filter mingw32 cygwin,$(build-platform))) @@ -492,7 +485,7 @@ ifdef msvc -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" \ -Fd$(build)/$(name).pdb -I"$(zlib)/include" -I$(src) -I"$(build)" \ -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ - -DTARGET_BYTES_PER_WORD=$(pointer-size) -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_WINDOWS + -DTARGET_BYTES_PER_WORD=$(pointer-size) shared = -dll lflags = -nologo -LIBPATH:"$(zlib)/lib" -DEFAULTLIB:ws2_32 \ -DEFAULTLIB:zlib -MANIFEST -debug @@ -724,6 +717,18 @@ ifeq ($(target-arch),arm) cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_ARM endif +ifeq ($(target-platform),linux) + cflags += -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_LINUX +endif + +ifeq ($(target-platform),windows) + cflags += -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_WINDOWS +endif + +ifeq ($(target-platform),darwin) + cflags += -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_DARWIN +endif + class-name = $(patsubst $(1)/%.class,%,$(2)) class-names = $(foreach x,$(2),$(call class-name,$(1),$(x))) @@ -936,10 +941,12 @@ endif $(strip) $(strip-all) $(@) $(bootimage-generator): $(bootimage-generator-objects) + echo arch=$(arch) platform=$(platform) $(MAKE) mode=$(mode) \ arch=$(build-arch) \ target-arch=$(arch) \ platform=$(bootimage-platform) \ + target-platform=$(platform) \ openjdk=$(openjdk) \ openjdk-src=$(openjdk-src) \ bootimage-generator= \ From 9cbd67ec61e3b79aaa2514ae422890afe36d7892 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 3 May 2012 08:50:22 -0600 Subject: [PATCH 080/140] darwin doesn't have , apparently --- src/binaryToObject/tools.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h index f287a56b99..999d010535 100644 --- a/src/binaryToObject/tools.h +++ b/src/binaryToObject/tools.h @@ -11,8 +11,8 @@ #ifndef AVIAN_TOOLS_H_ #define AVIAN_TOOLS_H_ +#include #include "environment.h" -#include namespace avian { From 8c0ef382f8ef0581ef9df09a551408b26edaf02d Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 3 May 2012 12:04:34 -0600 Subject: [PATCH 081/140] write out bootimage directly from the bootimage-generator, eliminating one of the steps in a custom bootimage build --- makefile | 13 ++----------- readme.txt | 14 +------------- src/bootimage.cpp | 25 +++++++++++++++++-------- 3 files changed, 20 insertions(+), 32 deletions(-) diff --git a/makefile b/makefile index ff01cd7ba2..67b4e7e738 100755 --- a/makefile +++ b/makefile @@ -576,10 +576,7 @@ bootimage-generator-objects = \ $(call cpp-objects,$(bootimage-generator-sources),$(src),$(build)) bootimage-generator = $(build)/bootimage-generator -bootimage-bin = $(build)/bootimage.bin bootimage-object = $(build)/bootimage-bin.o - -codeimage-bin = $(build)/codeimage.bin codeimage-object = $(build)/codeimage-bin.o ifeq ($(bootimage),true) @@ -910,14 +907,8 @@ $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ $(ar) cru $(@) $(^) $(ranlib) $(@) -$(bootimage-bin): $(bootimage-generator) - $(<) $(classpath-build) $(@) $(codeimage-object) - -$(bootimage-object): $(bootimage-bin) $(converter) - @echo "creating $(@)" - $(converter) $(<) $(@) _binary_bootimage_bin_start \ - _binary_bootimage_bin_end $(platform) $(arch) $(pointer-size) \ - writable +$(bootimage-object) $(codeimage-object): $(bootimage-generator) + $(<) $(classpath-build) $(bootimage-object) $(codeimage-object) executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ diff --git a/readme.txt b/readme.txt index a81b6b2693..d214dda8b7 100644 --- a/readme.txt +++ b/readme.txt @@ -557,19 +557,7 @@ Step 6: Build the boot and code images. $ ../build/linux-i386-bootimage/bootimage-generator stage2 \ bootimage.bin codeimage.bin -Step 7: Make an object file out of the boot and code images. - - $ ../build/linux-i386-bootimage/binaryToObject \ - bootimage.bin bootimage-bin.o \ - _binary_bootimage_bin_start _binary_bootimage_bin_end \ - linux i386 8 writable - - $ ../build/linux-i386-bootimage/binaryToObject \ - codeimage.bin codeimage-bin.o \ - _binary_codeimage_bin_start _binary_codeimage_bin_end \ - linux i386 8 executable - -Step 8: Write a driver which starts the VM and runs the desired main +Step 7: Write a driver which starts the VM and runs the desired main method. Note the bootimageBin function, which will be called by the VM to get a handle to the embedded boot image. We tell the VM about this function via the "avian.bootimage" property. diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 67e89db8fe..21a1da5f22 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1604,6 +1604,8 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp image->bootClassCount, image->stringCount, image->callCount, image->heapSize, image->codeSize); + Buffer bootimageData; + if (true) { { BootImage targetImage; @@ -1620,13 +1622,13 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp #include "bootimage-fields.cpp" #undef THUNK_FIELD - bootimageOutput->writeChunk(&targetImage, sizeof(BootImage)); + bootimageData.write(&targetImage, sizeof(BootImage)); } - bootimageOutput->writeChunk(bootClassTable, image->bootClassCount * sizeof(unsigned)); - bootimageOutput->writeChunk(appClassTable, image->appClassCount * sizeof(unsigned)); - bootimageOutput->writeChunk(stringTable, image->stringCount * sizeof(unsigned)); - bootimageOutput->writeChunk(callTable, image->callCount * sizeof(unsigned) * 2); + bootimageData.write(bootClassTable, image->bootClassCount * sizeof(unsigned)); + bootimageData.write(appClassTable, image->appClassCount * sizeof(unsigned)); + bootimageData.write(stringTable, image->stringCount * sizeof(unsigned)); + bootimageData.write(callTable, image->callCount * sizeof(unsigned) * 2); unsigned offset = sizeof(BootImage) + (image->bootClassCount * sizeof(unsigned)) @@ -1636,13 +1638,13 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp while (offset % TargetBytesPerWord) { uint8_t c = 0; - bootimageOutput->write(c); + bootimageData.write(&c, 1); ++ offset; } - bootimageOutput->writeChunk(heapMap, pad(heapMapSize(image->heapSize), TargetBytesPerWord)); + bootimageData.write(heapMap, pad(heapMapSize(image->heapSize), TargetBytesPerWord)); - bootimageOutput->writeChunk(heap, pad(image->heapSize, TargetBytesPerWord)); + bootimageData.write(heap, pad(image->heapSize, TargetBytesPerWord)); // fwrite(code, pad(image->codeSize, TargetBytesPerWord), 1, codeOutput); @@ -1653,6 +1655,13 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp // return false; // } + SymbolInfo bootimageSymbols[] = { + SymbolInfo(0, "_binary_bootimage_bin_start"), + SymbolInfo(bootimageData.length, "_binary_bootimage_bin_end") + }; + + platform->writeObject(bootimageOutput, Slice(bootimageSymbols, 2), Slice(bootimageData.data, bootimageData.length), Platform::Writable, TargetBytesPerWord); + compilationHandler.symbols.add(SymbolInfo(0, strdup("_binary_codeimage_bin_start"))); compilationHandler.symbols.add(SymbolInfo(image->codeSize, strdup("_binary_codeimage_bin_end"))); From 58691a7fdbd85b09ba27f7309c0290072c4168ce Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 3 May 2012 14:55:51 -0600 Subject: [PATCH 082/140] fix native Windows build For some reason, Cygwin's MinGW-W64 compilers end up pulling in our version of process.h from unistd.h. That doesn't really make sense -- it should use the one from the sysroot, but we can work around it by just not including unistd.h, since it's not needed on Windows anyway. --- src/binaryToObject/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index 00515947e3..b7a35b90f4 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -18,9 +18,9 @@ #include #else #include +#include #endif #include -#include #include "tools.h" From ea4e0a2f5d1fb19b1783d8d1243646031c87cdbe Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 4 May 2012 18:35:13 -0600 Subject: [PATCH 083/140] fix a couple of subtle Thread.getStackTrace bugs The first problem was that, on x86, we failed to properly keep track of whether to expect the return address to be on the stack or not when unwinding through a frame. We were relying on a "stackLimit" pointer to tell us whether we were looking at the most recently-called frame by comparing it with the stack pointer for that frame. That was inaccurate in the case of a thread executing at the beginning of a method before a new frame is allocated, in which case the most recent two frames share a stack pointer, confusing the unwinder. The solution involves keeping track of how many frames we've looked at while walking the stack. The other problem was that compareIpToMethodBounds assumed every method was followed by at least one byte of padding before the next method started. That assumption was usually valid because we were storing the size following method code prior to the code itself. However, the last method of an AOT-compiled code image is not followed by any such method header and may instead be followed directly by native code with no intervening padding. In that case, we risk interpreting that native code as part of the preceding method, with potentially bizarre results. The reason for the compareIpToMethodBounds assumption was that methods which throw exceptions as their last instruction generate a non-returning call, which nonetheless push a return address on the stack which points past the end of the method, and the unwinder needs to know that return address belongs to that method. A better solution is to add an extra trap instruction to the end of such methods, which is what this patch does. --- src/arm.cpp | 14 ++++++-- src/assembler.h | 7 ++-- src/bootimage.cpp | 4 --- src/compile.cpp | 84 +++++++++++++++++++++++++++++------------------ src/compiler.cpp | 21 +++++++----- src/compiler.h | 2 ++ src/machine.cpp | 4 +-- src/powerpc.cpp | 14 ++++++-- src/types.def | 1 + src/x86.cpp | 27 ++++++++++----- 10 files changed, 114 insertions(+), 64 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index af1c6398a2..9f815765b4 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -136,6 +136,7 @@ inline int ble(int offset) { return SETCOND(b(offset), LE); } inline int bge(int offset) { return SETCOND(b(offset), GE); } inline int blo(int offset) { return SETCOND(b(offset), CC); } inline int bhs(int offset) { return SETCOND(b(offset), CS); } +inline int bkpt() { return 0xe1200070; } // todo: macro-ify } const uint64_t MASK_LO32 = 0xffffffff; @@ -1616,6 +1617,12 @@ return_(Context* c) emit(c, bx(LinkRegister)); } +void +trap(Context* c) +{ + emit(c, bkpt()); +} + void memoryBarrier(Context*) {} @@ -1629,7 +1636,7 @@ argumentFootprint(unsigned footprint) void nextFrame(ArchitectureContext* c, uint32_t* start, unsigned size UNUSED, - unsigned footprint, void* link, void*, + unsigned footprint, void* link, bool, unsigned targetParameterFootprint UNUSED, void** ip, void** stack) { assert(c, *ip >= start); @@ -1703,6 +1710,7 @@ populateTables(ArchitectureContext* c) zo[LoadBarrier] = memoryBarrier; zo[StoreStoreBarrier] = memoryBarrier; zo[StoreLoadBarrier] = memoryBarrier; + zo[Trap] = trap; uo[index(c, LongCall, C)] = CAST1(longCallC); @@ -1922,12 +1930,12 @@ class MyArchitecture: public Assembler::Architecture { } virtual void nextFrame(void* start, unsigned size, unsigned footprint, - void* link, void* stackLimit, + void* link, bool mostRecent, unsigned targetParameterFootprint, void** ip, void** stack) { ::nextFrame(&c, static_cast(start), size, footprint, link, - stackLimit, targetParameterFootprint, ip, stack); + mostRecent, targetParameterFootprint, ip, stack); } virtual void* frameIp(void* stack) { diff --git a/src/assembler.h b/src/assembler.h index 1566df6cd7..07e02a31d5 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -32,10 +32,11 @@ enum Operation { Return, LoadBarrier, StoreStoreBarrier, - StoreLoadBarrier + StoreLoadBarrier, + Trap }; -const unsigned OperationCount = StoreLoadBarrier + 1; +const unsigned OperationCount = Trap + 1; enum UnaryOperation { Call, @@ -367,7 +368,7 @@ class Assembler { virtual unsigned alignFrameSize(unsigned sizeInWords) = 0; virtual void nextFrame(void* start, unsigned size, unsigned footprint, - void* link, void* stackLimit, + void* link, bool mostRecent, unsigned targetParameterFootprint, void** ip, void** stack) = 0; virtual void* frameIp(void* stack) = 0; diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 21a1da5f22..0888fc7f81 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -686,10 +686,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, } for (; methods; methods = pairSecond(t, methods)) { - intptr_t address = codeCompiled(t, methodCode(t, pairFirst(t, methods))); - reinterpret_cast(address)[-1] - = targetVW(reinterpret_cast(address)[-1]); - codeCompiled(t, methodCode(t, pairFirst(t, methods))) -= reinterpret_cast(code); } diff --git a/src/compile.cpp b/src/compile.cpp index 154e80f69b..395e7a3114 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -176,8 +176,8 @@ class MyThread: public Thread { Context(t, ip, stack, continuation, trace), t(t), link(0), - javaStackLimit(0), - next(t->traceContext) + next(t->traceContext), + methodIsMostRecent(false) { t->traceContext = this; } @@ -186,8 +186,8 @@ class MyThread: public Thread { Context(t, t->ip, t->stack, t->continuation, t->trace), t(t), link(link), - javaStackLimit(0), - next(t->traceContext) + next(t->traceContext), + methodIsMostRecent(false) { t->traceContext = this; } @@ -198,8 +198,8 @@ class MyThread: public Thread { MyThread* t; void* link; - void* javaStackLimit; TraceContext* next; + bool methodIsMostRecent; }; static void doTransition(MyThread* t, void* ip, void* stack, @@ -353,18 +353,18 @@ root(Thread* t, Root root); void setRoot(Thread* t, Root root, object value); -unsigned -compiledSize(intptr_t address) -{ - return reinterpret_cast(address)[-1]; -} - intptr_t methodCompiled(Thread* t, object method) { return codeCompiled(t, methodCode(t, method)); } +unsigned +methodCompiledSize(Thread* t, object method) +{ + return codeCompiledSize(t, methodCode(t, method)); +} + intptr_t compareIpToMethodBounds(Thread* t, intptr_t ip, object method) { @@ -374,13 +374,13 @@ compareIpToMethodBounds(Thread* t, intptr_t ip, object method) fprintf(stderr, "find %p in (%p,%p)\n", reinterpret_cast(ip), reinterpret_cast(start), - reinterpret_cast(start + compiledSize(start))); + reinterpret_cast(start + methodCompiledSize(t, method))); } if (ip < start) { return -1; } else if (ip < start + static_cast - (compiledSize(start) + TargetBytesPerWord)) + (methodCompiledSize(t, method))) { return 0; } else { @@ -427,19 +427,20 @@ alignedFrameSize(MyThread* t, object method) } void -nextFrame(MyThread* t, void** ip, void** sp, object method, object target) +nextFrame(MyThread* t, void** ip, void** sp, object method, object target, + bool mostRecent) { object code = methodCode(t, method); intptr_t start = codeCompiled(t, code); void* link; - void* javaStackLimit; + bool methodIsMostRecent; if (t->traceContext) { link = t->traceContext->link; - javaStackLimit = t->traceContext->javaStackLimit; + methodIsMostRecent = mostRecent and t->traceContext->methodIsMostRecent; } else { link = 0; - javaStackLimit = 0; + methodIsMostRecent = false; } // fprintf(stderr, "nextFrame %s.%s%s target %s.%s%s ip %p sp %p\n", @@ -458,8 +459,8 @@ nextFrame(MyThread* t, void** ip, void** sp, object method, object target) // *ip, *sp); t->arch->nextFrame - (reinterpret_cast(start), compiledSize(start), - alignedFrameSize(t, method), link, javaStackLimit, + (reinterpret_cast(start), codeCompiledSize(t, code), + alignedFrameSize(t, method), link, methodIsMostRecent, target ? methodParameterFootprint(t, target) : -1, ip, sp); // fprintf(stderr, "next frame ip %p sp %p\n", *ip, *sp); @@ -514,6 +515,7 @@ class MyStackWalker: public Processor::StackWalker { state(Start), method_(0), target(0), + count_(0), protector(this) { if (t->traceContext) { @@ -538,6 +540,7 @@ class MyStackWalker: public Processor::StackWalker { method_(w->method_), target(w->target), continuation(w->continuation), + count_(0), protector(this) { } @@ -609,13 +612,15 @@ class MyStackWalker: public Processor::StackWalker { } void next() { + expect(t, count_ <= StackSizeInWords); + switch (state) { case Continuation: continuation = continuationNext(t, continuation); break; case Method: - nextFrame(t, &ip_, &stack, method_, target); + nextFrame(t, &ip_, &stack, method_, target, count_ == 0); break; case NativeMethod: @@ -625,6 +630,8 @@ class MyStackWalker: public Processor::StackWalker { abort(t); } + ++ count_; + state = Next; } @@ -671,6 +678,7 @@ class MyStackWalker: public Processor::StackWalker { object method_; object target; object continuation; + unsigned count_; MyProtector protector; }; @@ -2065,6 +2073,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetFrame, } object target = t->trace->targetMethod; + bool mostRecent = true; *targetIp = 0; while (*targetIp == 0) { @@ -2075,7 +2084,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetFrame, if (handler) { *targetIp = handler; - nextFrame(t, &ip, &stack, method, target); + nextFrame(t, &ip, &stack, method, target, mostRecent); void** sp = static_cast(stackForFrame(t, stack, method)) + t->arch->frameReturnAddressSize(); @@ -2089,7 +2098,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetFrame, t->exception = 0; } else { - nextFrame(t, &ip, &stack, method, target); + nextFrame(t, &ip, &stack, method, target, mostRecent); if (t->exception) { releaseLock(t, method, stack); @@ -2137,6 +2146,8 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetFrame, *targetContinuation = continuationNext(t, c); } } + + mostRecent = false; } } @@ -2160,6 +2171,8 @@ makeCurrentContinuation(MyThread* t, void** targetIp, void** targetStack) object last = 0; PROTECT(t, last); + bool mostRecent = true; + *targetIp = 0; while (*targetIp == 0) { object method = methodForIp(t, ip); @@ -2177,7 +2190,7 @@ makeCurrentContinuation(MyThread* t, void** targetIp, void** targetStack) } void* nextIp = ip; - nextFrame(t, &nextIp, &stack, method, target); + nextFrame(t, &nextIp, &stack, method, target, mostRecent); void** bottom = static_cast(stack) + t->arch->frameReturnAddressSize(); @@ -2215,6 +2228,8 @@ makeCurrentContinuation(MyThread* t, void** targetIp, void** targetStack) *targetStack = static_cast(stack) + t->arch->frameReturnAddressSize(); } + + mostRecent = false; } expect(t, last); @@ -4295,6 +4310,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, 0, Compiler::VoidType, 2, c->register_(t->arch->thread()), target); + + if (ip == codeLength(t, code)) { + c->trap(); + } } return; case bipush: @@ -6999,15 +7018,14 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) // we must acquire the class lock here at the latest unsigned codeSize = c->resolve - (allocator->base + allocator->offset + TargetBytesPerWord); + (allocator->base + allocator->offset); unsigned total = pad(codeSize, TargetBytesPerWord) - + pad(c->poolSize(), TargetBytesPerWord) + TargetBytesPerWord; + + pad(c->poolSize(), TargetBytesPerWord); target_uintptr_t* code = static_cast (allocator->allocate(total, TargetBytesPerWord)); - code[0] = codeSize; - uint8_t* start = reinterpret_cast(code + 1); + uint8_t* start = reinterpret_cast(code); context->executableAllocator = allocator; context->executableStart = code; @@ -7060,7 +7078,7 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) code = makeCode (t, 0, newExceptionHandlerTable, newLineNumberTable, - reinterpret_cast(start), codeMaxStack(t, code), + reinterpret_cast(start), codeSize, codeMaxStack(t, code), codeMaxLocals(t, code), 0); set(t, context->method, MethodCode, code); @@ -7764,6 +7782,7 @@ visitStack(MyThread* t, Heap::Visitor* v) MyThread::CallTrace* trace = t->trace; object targetMethod = (trace ? trace->targetMethod : 0); object target = targetMethod; + bool mostRecent = true; while (stack) { if (targetMethod) { @@ -7776,7 +7795,7 @@ visitStack(MyThread* t, Heap::Visitor* v) PROTECT(t, method); void* nextIp = ip; - nextFrame(t, &nextIp, &stack, method, target); + nextFrame(t, &nextIp, &stack, method, target, mostRecent); visitStackAndLocals(t, v, stack, method, ip); @@ -7797,6 +7816,8 @@ visitStack(MyThread* t, Heap::Visitor* v) } else { break; } + + mostRecent = false; } } @@ -8831,7 +8852,7 @@ class MyProcessor: public Processor { // we caught the thread in Java code - use the register values c.ip = ip; c.stack = stack; - c.javaStackLimit = stack; + c.methodIsMostRecent = true; } else if (target->transition) { // we caught the thread in native code while in the middle // of updating the context fields (MyThread::stack, etc.) @@ -9492,8 +9513,7 @@ fixupMethods(Thread* t, object map, BootImage* image UNUSED, uint8_t* code) logCompile (static_cast(t), reinterpret_cast(methodCompiled(t, method)), - reinterpret_cast - (methodCompiled(t, method))[-1], + methodCompiledSize(t, method), reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, method)), 0)), reinterpret_cast diff --git a/src/compiler.cpp b/src/compiler.cpp index 737f723da4..5a89b38342 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -4576,14 +4576,14 @@ appendTranslate(Context* c, BinaryOperation type, unsigned firstSize, } } -class BarrierEvent: public Event { +class OperationEvent: public Event { public: - BarrierEvent(Context* c, Operation op): + OperationEvent(Context* c, Operation op): Event(c), op(op) { } virtual const char* name() { - return "BarrierEvent"; + return "OperationEvent"; } virtual void compile(Context* c) { @@ -4594,9 +4594,10 @@ class BarrierEvent: public Event { }; void -appendBarrier(Context* c, Operation op) +appendOperation(Context* c, Operation op) { - append(c, new (c->zone->allocate(sizeof(BarrierEvent))) BarrierEvent(c, op)); + append + (c, new (c->zone->allocate(sizeof(OperationEvent))) OperationEvent(c, op)); } class MemoryEvent: public Event { @@ -6902,16 +6903,20 @@ class MyCompiler: public Compiler { return result; } + virtual void trap() { + appendOperation(&c, Trap); + } + virtual void loadBarrier() { - appendBarrier(&c, LoadBarrier); + appendOperation(&c, LoadBarrier); } virtual void storeStoreBarrier() { - appendBarrier(&c, StoreStoreBarrier); + appendOperation(&c, StoreStoreBarrier); } virtual void storeLoadBarrier() { - appendBarrier(&c, StoreLoadBarrier); + appendOperation(&c, StoreLoadBarrier); } virtual void compile(uintptr_t stackOverflowHandler, diff --git a/src/compiler.h b/src/compiler.h index 85deed9473..acac85b436 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -184,6 +184,8 @@ class Compiler { virtual Operand* f2i(unsigned aSize, unsigned resSize, Operand* a) = 0; virtual Operand* i2f(unsigned aSize, unsigned resSize, Operand* a) = 0; + virtual void trap() = 0; + virtual void loadBarrier() = 0; virtual void storeStoreBarrier() = 0; virtual void storeLoadBarrier() = 0; diff --git a/src/machine.cpp b/src/machine.cpp index ac2c5bdd51..258c873ec2 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1310,7 +1310,7 @@ parseCode(Thread* t, Stream& s, object pool) unsigned maxLocals = s.read2(); unsigned length = s.read4(); - object code = makeCode(t, pool, 0, 0, 0, maxStack, maxLocals, length); + object code = makeCode(t, pool, 0, 0, 0, 0, maxStack, maxLocals, length); s.read(&codeBody(t, code, 0), length); PROTECT(t, code); @@ -2234,7 +2234,7 @@ boot(Thread* t) m->processor->boot(t, 0, 0); - { object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 1); + { object bootCode = makeCode(t, 0, 0, 0, 0, 0, 0, 0, 1); codeBody(t, bootCode, 0) = impdep1; object bootMethod = makeMethod (t, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, bootCode); diff --git a/src/powerpc.cpp b/src/powerpc.cpp index 7e315b1f35..f63bd270c6 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -130,6 +130,7 @@ inline int cmpw(int ra, int rb) { return cmp(0, ra, rb); } inline int cmplw(int ra, int rb) { return cmpl(0, ra, rb); } inline int cmpwi(int ra, int i) { return cmpi(0, ra, i); } inline int cmplwi(int ra, int i) { return cmpli(0, ra, i); } +inline int trap() { return 0x7fe00008; } // todo: macro-ify } const int64_t MASK_LO32 = 0x0ffffffff; @@ -1907,6 +1908,12 @@ return_(Context* c) emit(c, blr()); } +void +trap(Context* c) +{ + emit(c, trap()); +} + void memoryBarrier(Context* c) { @@ -1923,7 +1930,7 @@ argumentFootprint(unsigned footprint) void nextFrame(ArchitectureContext* c UNUSED, int32_t* start, unsigned size, - unsigned footprint, void* link, void*, + unsigned footprint, void* link, bool, unsigned targetParameterFootprint, void** ip, void** stack) { assert(c, *ip >= start); @@ -1988,6 +1995,7 @@ populateTables(ArchitectureContext* c) zo[LoadBarrier] = memoryBarrier; zo[StoreStoreBarrier] = memoryBarrier; zo[StoreLoadBarrier] = memoryBarrier; + zo[Trap] = trap; uo[index(c, LongCall, C)] = CAST1(longCallC); @@ -2215,12 +2223,12 @@ class MyArchitecture: public Assembler::Architecture { } virtual void nextFrame(void* start, unsigned size, unsigned footprint, - void* link, void* stackLimit, + void* link, bool mostRecent, unsigned targetParameterFootprint, void** ip, void** stack) { ::nextFrame(&c, static_cast(start), size, footprint, link, - stackLimit, targetParameterFootprint, ip, stack); + mostRecent, targetParameterFootprint, ip, stack); } virtual void* frameIp(void* stack) { diff --git a/src/types.def b/src/types.def index c95ed03a0a..9b19ccd9bc 100644 --- a/src/types.def +++ b/src/types.def @@ -77,6 +77,7 @@ (object exceptionHandlerTable) (object lineNumberTable) (intptr_t compiled) + (uint32_t compiledSize) (uint16_t maxStack) (uint16_t maxLocals) (array uint8_t body)) diff --git a/src/x86.cpp b/src/x86.cpp index 89d6f5df25..5673b9da97 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -645,6 +645,12 @@ return_(Context* c) opcode(c, 0xc3); } +void +trap(Context* c) +{ + opcode(c, 0xcc); +} + void ignore(Context*) { } @@ -2163,8 +2169,8 @@ divideRR(Context* c, unsigned aSize, Assembler::Register* a, assert(c, a->low != rdx); c->client->save(rdx); - - maybeRex(c, aSize, a, b); + + maybeRex(c, aSize, a, b); opcode(c, 0x99); // cdq maybeRex(c, aSize, b, a); opcode(c, 0xf7, 0xf8 + regCode(a)); @@ -2180,8 +2186,8 @@ remainderRR(Context* c, unsigned aSize, Assembler::Register* a, assert(c, a->low != rdx); c->client->save(rdx); - - maybeRex(c, aSize, a, b); + + maybeRex(c, aSize, a, b); opcode(c, 0x99); // cdq maybeRex(c, aSize, b, a); opcode(c, 0xf7, 0xf8 + regCode(a)); @@ -2552,7 +2558,7 @@ read4(uint8_t* p) void nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, - unsigned footprint, void*, void* stackLimit, + unsigned footprint, void*, bool mostRecent, unsigned targetParameterFootprint, void** ip, void** stack) { assert(c, *ip >= start); @@ -2570,6 +2576,7 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, } if (instruction <= start) { + assert(c, mostRecent); *ip = static_cast(*stack)[0]; return; } @@ -2579,6 +2586,8 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, start += (TargetBytesPerWord == 4 ? 3 : 4); if (instruction <= start or *instruction == 0x5d) { + assert(c, mostRecent); + *ip = static_cast(*stack)[1]; *stack = static_cast(*stack) + 1; return; @@ -2590,8 +2599,7 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, return; } - unsigned offset = footprint + FrameHeaderSize - - (stackLimit == *stack ? 1 : 0); + unsigned offset = footprint + FrameHeaderSize - (mostRecent ? 1 : 0); if (TailCalls) { if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) { @@ -2642,6 +2650,7 @@ populateTables(ArchitectureContext* c) zo[LoadBarrier] = ignore; zo[StoreStoreBarrier] = ignore; zo[StoreLoadBarrier] = storeLoadBarrier; + zo[Trap] = trap; uo[index(c, Call, C)] = CAST1(callC); uo[index(c, Call, R)] = CAST1(callR); @@ -2966,12 +2975,12 @@ class MyArchitecture: public Assembler::Architecture { } virtual void nextFrame(void* start, unsigned size, unsigned footprint, - void* link, void* stackLimit, + void* link, bool mostRecent, unsigned targetParameterFootprint, void** ip, void** stack) { local::nextFrame(&c, static_cast(start), size, footprint, - link, stackLimit, targetParameterFootprint, ip, stack); + link, mostRecent, targetParameterFootprint, ip, stack); } virtual void* frameIp(void* stack) { From 189340954a7b5a3402551270c5989a12de3783e1 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 4 May 2012 18:59:15 -0600 Subject: [PATCH 084/140] fix build regression due to last merge --- src/compile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compile.cpp b/src/compile.cpp index e4b49ed373..0823af833a 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -612,7 +612,7 @@ class MyStackWalker: public Processor::StackWalker { } void next() { - expect(t, count_ <= StackSizeInWords); + expect(t, count_ <= stackSizeInWords(t)); switch (state) { case Continuation: From 1119675b7adc91ba064faf0483430d24f44771f9 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 4 May 2012 19:55:53 -0600 Subject: [PATCH 085/140] override InputStream.available for FileInputStream and the instance returned by ZipFile.getInputStream --- classpath/java/io/FileInputStream.java | 18 +++++++++++++-- classpath/java/util/zip/ZipFile.java | 32 ++++++++++++++++++++++++-- test/Files.java | 28 ++++++++++++++++++++++ 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/classpath/java/io/FileInputStream.java b/classpath/java/io/FileInputStream.java index 9c614e2f7e..29df029529 100644 --- a/classpath/java/io/FileInputStream.java +++ b/classpath/java/io/FileInputStream.java @@ -16,6 +16,7 @@ public class FileInputStream extends InputStream { // } private int fd; + private int remaining; public FileInputStream(FileDescriptor fd) { this.fd = fd.value; @@ -23,12 +24,17 @@ public class FileInputStream extends InputStream { public FileInputStream(String path) throws IOException { fd = open(path); + remaining = (int) new File(path).length(); } public FileInputStream(File file) throws IOException { this(file.getPath()); } + public int available() throws IOException { + return remaining; + } + private static native int open(String path) throws IOException; private static native int read(int fd) throws IOException; @@ -39,7 +45,11 @@ public class FileInputStream extends InputStream { public static native void close(int fd) throws IOException; public int read() throws IOException { - return read(fd); + int c = read(fd); + if (c >= 0 && remaining > 0) { + -- remaining; + } + return c; } public int read(byte[] b, int offset, int length) throws IOException { @@ -51,7 +61,11 @@ public class FileInputStream extends InputStream { throw new ArrayIndexOutOfBoundsException(); } - return read(fd, b, offset, length); + int c = read(fd, b, offset, length); + if (c > 0 && remaining > 0) { + remaining -= c; + } + return c; } public void close() throws IOException { diff --git a/classpath/java/util/zip/ZipFile.java b/classpath/java/util/zip/ZipFile.java index 94d8b99b08..d356bbf5ed 100644 --- a/classpath/java/util/zip/ZipFile.java +++ b/classpath/java/util/zip/ZipFile.java @@ -86,7 +86,7 @@ public class ZipFile { } public InputStream getInputStream(ZipEntry entry) throws IOException { - int pointer = ((MyEntry) entry).pointer(); + final int pointer = ((MyEntry) entry).pointer(); int method = compressionMethod(window, pointer); int size = compressedSize(window, pointer); InputStream in = new MyInputStream(file, fileData(window, pointer), size); @@ -99,7 +99,35 @@ public class ZipFile { return in; case Deflated: - return new InflaterInputStream(in, new Inflater(true)); + return new InflaterInputStream(in, new Inflater(true)) { + int remaining = uncompressedSize(window, pointer); + + public int read() throws IOException { + int c = super.read(); + if (c >= 0) { + -- remaining; + } + return c; + } + + public int read(byte[] buffer) throws IOException { + return read(buffer, 0, buffer.length); + } + + public int read(byte[] buffer, int offset, int length) + throws IOException + { + int c = super.read(buffer, offset, length); + if (c > 0) { + remaining -= c; + } + return c; + } + + public int available() { + return remaining; + } + }; default: throw new IOException(); diff --git a/test/Files.java b/test/Files.java index b5484462cf..7a0170b678 100644 --- a/test/Files.java +++ b/test/Files.java @@ -1,4 +1,6 @@ import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; public class Files { private static void expect(boolean v) { @@ -46,6 +48,32 @@ public class Files { expect(! f.createNewFile()); f.delete(); } + + { File f = new File("test.txt"); + FileOutputStream out = new FileOutputStream(f); + try { + byte[] message = "hello, world!\n".getBytes(); + out.write(message); + out.close(); + + FileInputStream in = new FileInputStream(f); + try { + expect(in.available() == message.length); + + for (int i = 0; i < message.length; ++i) { + in.read(); + expect(in.available() == message.length - i - 1); + } + + expect(in.read() == -1); + expect(in.available() == 0); + } finally { + in.close(); + } + } finally { + f.delete(); + } + } } } From 797b4c25cc6465d465ee2664cce2c5ec06fb508f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 4 May 2012 20:13:26 -0600 Subject: [PATCH 086/140] fix OpenJDK bootimage build regression --- src/bootimage.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 0888fc7f81..72b41028a2 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1292,15 +1292,17 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp class MyCompilationHandler : public Processor::CompilationHandler { public: virtual void compiled(const void* code, unsigned size UNUSED, unsigned frameSize UNUSED, const char* class_, const char* name, const char* spec) { - size_t classLen = strlen(class_); - size_t nameLen = strlen(name); - size_t specLen = strlen(spec); - - char* completeName = (char*)malloc(classLen + nameLen + specLen + 2); - sprintf(completeName, "%s.%s%s", class_, name, spec); - uint64_t offset = reinterpret_cast(code) - codeOffset; - symbols.add(SymbolInfo(offset, completeName)); - // printf("%ld %ld %s.%s%s\n", offset, offset + size, class_, name, spec); + if (class_ and name and spec) { + size_t classLen = strlen(class_); + size_t nameLen = strlen(name); + size_t specLen = strlen(spec); + + char* completeName = (char*)malloc(classLen + nameLen + specLen + 2); + sprintf(completeName, "%s.%s%s", class_, name, spec); + uint64_t offset = reinterpret_cast(code) - codeOffset; + symbols.add(SymbolInfo(offset, completeName)); + // printf("%ld %ld %s.%s%s\n", offset, offset + size, class_, name, spec); + } } virtual void dispose() {} From b09a388be5ab202175450144d4af6c6b32464629 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 4 May 2012 20:31:50 -0600 Subject: [PATCH 087/140] update readme.txt to reflect OpenJDK 7 dependency --- readme.txt | 59 ++++++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/readme.txt b/readme.txt index d0299875c3..45bc4add45 100644 --- a/readme.txt +++ b/readme.txt @@ -220,11 +220,11 @@ features beyond that subset, you may want to tell Avian to use OpenJDK's class library instead. To do so, specify the directory where OpenJDK is installed, e.g.: - $ make openjdk=/usr/lib/jvm/java-6-openjdk + $ make openjdk=/usr/lib/jvm/java-7-openjdk This will build Avian as a conventional JVM (e.g. libjvm.so) which loads its boot class library and native libraries (e.g. libjava.so) -from /usr/lib/jvm/java-6-openjdk/jre at runtime. To run an +from /usr/lib/jvm/java-7-openjdk/jre at runtime. To run an application in this configuration, you'll need to make sure the VM is in your library search path. For example: @@ -235,8 +235,8 @@ in your library search path. For example: Alternatively, you can enable a stand-alone build using OpenJDK by specifying the location of the OpenJDK source code, e.g.: - $ make openjdk=$(pwd)/../jdk6/build/linux-amd64/j2sdk-image \ - openjdk-src=$(pwd)/../jdk6/jdk/src + $ make openjdk=$(pwd)/../jdk7/build/linux-amd64/j2sdk-image \ + openjdk-src=$(pwd)/../jdk7/jdk/src You must ensure that the path specified for openjdk-src does not have any spaces in it; make gets confused when dependency paths include @@ -271,49 +271,42 @@ it on various OSes: Debian-based Linux: # conventional build: - apt-get install openjdk-6-jdk - make openjdk=/usr/lib/jvm/java-6-openjdk test + apt-get install openjdk-7-jdk + make openjdk=/usr/lib/jvm/java-7-openjdk test # stand-alone build: - apt-get install openjdk-6-jdk - apt-get source openjdk-6-jdk - apt-get build-dep openjdk-6-jdk - (cd openjdk-6-6b18-1.8.3 && ./debian/rules patch) - make openjdk=/usr/lib/jvm/java-6-openjdk \ - openjdk-src=$(pwd)/openjdk-6-6b18-1.8.3/build/openjdk/jdk/src \ + apt-get install openjdk-7-jdk + apt-get source openjdk-7-jdk + apt-get build-dep openjdk-7-jdk + (cd openjdk-7-7~b147-2.0 && dpkg-buildpackage) + make openjdk=/usr/lib/jvm/java-7-openjdk \ + openjdk-src=$(pwd)/openjdk-7-7~b147-2.0/build/openjdk/jdk/src \ test Mac OS X: - # Prerequisite: install MacPorts (http://www.macports.org/) - sudo port selfupdate + # Prerequisite: build OpenJDK 7 according to + # https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port # conventional build: - sudo port install openjdk6 - make openjdk=/opt/local/share/java/openjdk6 test + make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test # stand-alone build: - sudo port fetch openjdk6 - sudo port patch openjdk6 - make openjdk=/opt/local/share/java/openjdk6 \ - openjdk-src=/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_java_openjdk6/work/jdk/src \ - test + make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \ + openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test Windows (Cygwin): + # Prerequisite: build OpenJDK 7 according to + # http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction + # conventional build: - # Prerequisite: download and install the latest Windows OpenJDK - # build from http://www.openscg.com/se/openjdk/ - make openjdk=/cygdrive/c/OpenSCG/openjdk-6.21 test + make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image test # stand-alone build: - # Prerequisite: install OpenSCG build as above, plus the - # corresponding source bundle from - # http://download.java.net/openjdk/jdk6/promoted/, e.g.: - wget http://download.java.net/openjdk/jdk6/promoted/b21/openjdk-6-src-b21-20_jan_2011.tar.gz - mkdir openjdk - (cd openjdk && tar xzf ../openjdk-6-src-b21-20_jan_2011.tar.gz) - make openjdk=/cygdrive/c/OpenSCG/openjdk-6.21 \ - openjdk-src=$(pwd)/openjdk/jdk/src \ - test + make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image \ + openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test + +Currently, only OpenJDK 7 is supported. Later versions might work, +but have not yet been tested. Installing From 5c44ba859c2eea9867b56395417801493723578d Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 7 May 2012 08:13:04 -0600 Subject: [PATCH 088/140] minor correction to bootimage process in readme.txt --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index d214dda8b7..24e36a6b86 100644 --- a/readme.txt +++ b/readme.txt @@ -555,7 +555,7 @@ systems with case-insensitive filesystems such as Windows and OS X) Step 6: Build the boot and code images. $ ../build/linux-i386-bootimage/bootimage-generator stage2 \ - bootimage.bin codeimage.bin + bootimage-bin.o codeimage-bin.o Step 7: Write a driver which starts the VM and runs the desired main method. Note the bootimageBin function, which will be called by the From 4266b0df7f2e9618049090d7efc9254ff99ff1ea Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 7 May 2012 08:29:43 -0600 Subject: [PATCH 089/140] fix step numbering in readme.txt --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 24e36a6b86..c067bb5a89 100644 --- a/readme.txt +++ b/readme.txt @@ -664,7 +664,7 @@ EOF $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \ -D_JNI_IMPLEMENTATION_ -c main.cpp -o main.o -Step 9: Link the objects produced above to produce the final +Step 8: Link the objects produced above to produce the final executable, and optionally strip its symbols. $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello From 7c38ea75e4baf777ef5ab207e7f26e8e57e90cf3 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 7 May 2012 10:00:59 -0600 Subject: [PATCH 090/140] give thunks symbol names in the bootimage build, use Heap::allocate instead of malloc --- src/binaryToObject/tools.h | 2 +- src/bootimage.cpp | 42 +++++++++++++++++++++----------------- src/compile.cpp | 22 +++++++++++++++++++- src/processor.h | 2 +- 4 files changed, 46 insertions(+), 22 deletions(-) diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h index 999d010535..ad7e81f86f 100644 --- a/src/binaryToObject/tools.h +++ b/src/binaryToObject/tools.h @@ -55,7 +55,7 @@ public: unsigned addr; String name; - inline SymbolInfo(uint64_t addr, const char* name): + inline SymbolInfo(uint64_t addr, const String& name): addr(addr), name(name) {} diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 72b41028a2..27f0e2aa8a 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1291,28 +1291,32 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp class MyCompilationHandler : public Processor::CompilationHandler { public: - virtual void compiled(const void* code, unsigned size UNUSED, unsigned frameSize UNUSED, const char* class_, const char* name, const char* spec) { - if (class_ and name and spec) { - size_t classLen = strlen(class_); - size_t nameLen = strlen(name); - size_t specLen = strlen(spec); - - char* completeName = (char*)malloc(classLen + nameLen + specLen + 2); - sprintf(completeName, "%s.%s%s", class_, name, spec); - uint64_t offset = reinterpret_cast(code) - codeOffset; - symbols.add(SymbolInfo(offset, completeName)); - // printf("%ld %ld %s.%s%s\n", offset, offset + size, class_, name, spec); - } + + String heapDup(const char* name) { + String ret(name); + char* n = (char*)heap->allocate(ret.length + 1); + memcpy(n, ret.text, ret.length + 1); + ret.text = n; + return ret; + } + + virtual void compiled(const void* code, unsigned size UNUSED, unsigned frameSize UNUSED, const char* name) { + uint64_t offset = reinterpret_cast(code) - codeOffset; + symbols.add(SymbolInfo(offset, heapDup(name))); + // printf("%ld %ld %s.%s%s\n", offset, offset + size, class_, name, spec); } virtual void dispose() {} DynamicArray symbols; uint64_t codeOffset; + Heap* heap; - MyCompilationHandler(uint64_t codeOffset): - codeOffset(codeOffset) {} - } compilationHandler(reinterpret_cast(code)); + MyCompilationHandler(uint64_t codeOffset, Heap* heap): + codeOffset(codeOffset), + heap(heap) {} + + } compilationHandler(reinterpret_cast(code), t->m->heap); t->m->processor->addCompilationHandler(&compilationHandler); @@ -1660,13 +1664,13 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp platform->writeObject(bootimageOutput, Slice(bootimageSymbols, 2), Slice(bootimageData.data, bootimageData.length), Platform::Writable, TargetBytesPerWord); - compilationHandler.symbols.add(SymbolInfo(0, strdup("_binary_codeimage_bin_start"))); - compilationHandler.symbols.add(SymbolInfo(image->codeSize, strdup("_binary_codeimage_bin_end"))); + compilationHandler.symbols.add(SymbolInfo(0, "_binary_codeimage_bin_start")); + compilationHandler.symbols.add(SymbolInfo(image->codeSize, "_binary_codeimage_bin_end")); platform->writeObject(codeOutput, Slice(compilationHandler.symbols), Slice(code, image->codeSize), Platform::Executable, TargetBytesPerWord); - for(SymbolInfo* sym = compilationHandler.symbols.begin(); sym != compilationHandler.symbols.end(); sym++) { - free(const_cast((const void*)sym->name.text)); + for(SymbolInfo* sym = compilationHandler.symbols.begin(); sym != compilationHandler.symbols.end() - 2; sym++) { + t->m->heap->free(const_cast((const void*)sym->name.text), sym->name.length + 1); } } } diff --git a/src/compile.cpp b/src/compile.cpp index 395e7a3114..1adce59df7 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -9087,6 +9087,20 @@ class MyProcessor: public Processor { CompilationHandlerList* compilationHandlers; }; +const char* +stringOrNull(const char* str) { + if(str) { + return str; + } else { + return "(null)"; + } +} + +size_t +stringOrNullSize(const char* str) { + return strlen(stringOrNull(str)); +} + void logCompile(MyThread* t, const void* code, unsigned size, const char* class_, const char* name, const char* spec) @@ -9108,9 +9122,15 @@ logCompile(MyThread* t, const void* code, unsigned size, const char* class_, class_, name, spec); } + size_t nameLength = stringOrNullSize(class_) + stringOrNullSize(name) + stringOrNullSize(spec) + 2; + + THREAD_RUNTIME_ARRAY(t, char, completeName, nameLength); + + sprintf(RUNTIME_ARRAY_BODY(completeName), "%s.%s%s", stringOrNull(class_), stringOrNull(name), stringOrNull(spec)); + MyProcessor* p = static_cast(t->m->processor); for(CompilationHandlerList* h = p->compilationHandlers; h; h = h->next) { - h->handler->compiled(code, 0, 0, class_, name, spec); + h->handler->compiled(code, 0, 0, RUNTIME_ARRAY_BODY(completeName)); } } diff --git a/src/processor.h b/src/processor.h index 3794570b14..a6b548387f 100644 --- a/src/processor.h +++ b/src/processor.h @@ -43,7 +43,7 @@ class Processor { class CompilationHandler { public: - virtual void compiled(const void* code, unsigned size, unsigned frameSize, const char* class_, const char* name, const char* spec) = 0; + virtual void compiled(const void* code, unsigned size, unsigned frameSize, const char* name) = 0; virtual void dispose() = 0; }; From fde7a3e7a1aed1048ebbdf3a0aa957b41fcf7c83 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Mon, 7 May 2012 15:02:16 -0600 Subject: [PATCH 091/140] give virtualThunks names based on index, to avoid conflicts --- src/compile.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/compile.cpp b/src/compile.cpp index 1adce59df7..e5621cf5b6 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -10000,7 +10000,15 @@ compileVirtualThunk(MyThread* t, unsigned index, unsigned* size) a->setDestination(start); a->write(); - logCompile(t, start, *size, 0, "virtualThunk", 0); + const char* const virtualThunkBaseName = "virtualThunk"; + const size_t virtualThunkBaseNameLength = strlen(virtualThunkBaseName); + const size_t maxIntStringLength = 10; + + THREAD_RUNTIME_ARRAY(t, char, virtualThunkName, virtualThunkBaseNameLength + maxIntStringLength); + + sprintf(RUNTIME_ARRAY_BODY(virtualThunkName), "%s%d", virtualThunkBaseName, index); + + logCompile(t, start, *size, 0, virtualThunkName, 0); return reinterpret_cast(start); } From fa9814b86d3460fb48c5b06f1de17ca8219b42f1 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Tue, 8 May 2012 16:13:17 -0600 Subject: [PATCH 092/140] remove lots of unnecessary sizeof computations with a convenient 'operator new' overload --- src/allocator.h | 4 ++ src/arm.cpp | 33 ++++++---------- src/compile.cpp | 23 ++++-------- src/compiler.cpp | 97 +++++++++++++++++++----------------------------- src/powerpc.cpp | 35 +++++++---------- src/util.cpp | 3 +- src/x86.cpp | 38 ++++++++----------- 7 files changed, 92 insertions(+), 141 deletions(-) diff --git a/src/allocator.h b/src/allocator.h index 9fe3958de6..34febb8cd8 100644 --- a/src/allocator.h +++ b/src/allocator.h @@ -57,4 +57,8 @@ copy(Allocator* allocator, const char* a) } // namespace vm +inline void* operator new (size_t size, vm::Allocator* allocator) { + return allocator->allocate(size); +} + #endif//ALLOCATOR_H diff --git a/src/arm.cpp b/src/arm.cpp index 9f815765b4..784d4f3824 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -228,7 +228,7 @@ class Context { public: Context(System* s, Allocator* a, Zone* zone): s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), - firstBlock(new (zone->allocate(sizeof(MyBlock))) MyBlock(this, 0)), + firstBlock(new(zone) MyBlock(this, 0)), lastBlock(firstBlock), poolOffsetHead(0), poolOffsetTail(0), constantPool(0), constantPoolCount(0) { } @@ -346,8 +346,7 @@ class Offset: public Promise { Promise* offset(Context* c, bool forTrace = false) { - return new (c->zone->allocate(sizeof(Offset))) - Offset(c, c->lastBlock, c->code.length(), forTrace); + return new(c->zone) Offset(c, c->lastBlock, c->code.length(), forTrace); } bool @@ -414,8 +413,7 @@ class OffsetTask: public Task { void appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset) { - c->tasks = new (c->zone->allocate(sizeof(OffsetTask))) OffsetTask - (c->tasks, promise, instructionOffset); + c->tasks = new(c->zone) OffsetTask(c->tasks, promise, instructionOffset); } inline unsigned @@ -628,17 +626,14 @@ appendConstantPoolEntry(Context* c, Promise* constant, Promise* callOffset) if (constant->resolved()) { // make a copy, since the original might be allocated on the // stack, and we need our copy to live until assembly is complete - constant = new (c->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(constant->value()); + constant = new(c->zone) ResolvedPromise(constant->value()); } - c->constantPool = new (c->zone->allocate(sizeof(ConstantPoolEntry))) - ConstantPoolEntry(c, constant, c->constantPool, callOffset); + c->constantPool = new(c->zone) ConstantPoolEntry(c, constant, c->constantPool, callOffset); ++ c->constantPoolCount; - PoolOffset* o = new (c->zone->allocate(sizeof(PoolOffset))) PoolOffset - (c->lastBlock, c->constantPool, c->code.length() - c->lastBlock->offset); + PoolOffset* o = new(c->zone) PoolOffset(c->lastBlock, c->constantPool, c->code.length() - c->lastBlock->offset); if (DebugPool) { fprintf(stderr, "add pool offset %p %d to block %p\n", @@ -657,8 +652,7 @@ void appendPoolEvent(Context* c, MyBlock* b, unsigned offset, PoolOffset* head, PoolOffset* tail) { - PoolEvent* e = new (c->zone->allocate(sizeof(PoolEvent))) PoolEvent - (head, tail, offset); + PoolEvent* e = new(c->zone) PoolEvent(head, tail, offset); if (b->poolEventTail) { b->poolEventTail->next = e; @@ -1522,8 +1516,7 @@ branchCM(Context* c, TernaryOperation op, unsigned size, ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { - return new (c->zone->allocate(sizeof(ShiftMaskPromise))) - ShiftMaskPromise(base, shift, mask); + return new(c->zone) ShiftMaskPromise(base, shift, mask); } void @@ -2158,9 +2151,7 @@ class MyAssembler: public Assembler { { Register stack(StackRegister); Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread); - Constant handlerConstant - (new (c.zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(handler)); + Constant handlerConstant(new(c.zone) ResolvedPromise(handler)); branchRM(&c, JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, &handlerConstant); } @@ -2465,8 +2456,7 @@ class MyAssembler: public Assembler { MyBlock* b = c.lastBlock; b->size = c.code.length() - b->offset; if (startNew) { - c.lastBlock = new (c.zone->allocate(sizeof(MyBlock))) - MyBlock(&c, c.code.length()); + c.lastBlock = new (c.zone) MyBlock(&c, c.code.length()); } else { c.lastBlock = 0; } @@ -2537,8 +2527,7 @@ Assembler* makeAssembler(System* system, Allocator* allocator, Zone* zone, Assembler::Architecture* architecture) { - return new (zone->allocate(sizeof(MyAssembler))) - MyAssembler(system, allocator, zone, + return new(zone) MyAssembler(system, allocator, zone, static_cast(architecture)); } diff --git a/src/compile.cpp b/src/compile.cpp index e5621cf5b6..e6943f592a 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1389,8 +1389,7 @@ class Frame { Compiler::Operand* append(object o) { BootContext* bc = context->bootContext; if (bc) { - Promise* p = new (bc->zone->allocate(sizeof(ListenPromise))) - ListenPromise(t->m->system, bc->zone); + Promise* p = new (bc->zone) ListenPromise(t->m->system, bc->zone); PROTECT(t, o); object pointer = makePointer(t, p); @@ -1408,9 +1407,7 @@ class Frame { } } - context->objectPool = new - (context->zone.allocate(sizeof(PoolElement))) - PoolElement(t, o, context->objectPool); + context->objectPool = new(&context->zone) PoolElement(t, o, context->objectPool); ++ context->objectPoolCount; @@ -1615,8 +1612,7 @@ class Frame { Promise* addressPromise(Promise* p) { BootContext* bc = context->bootContext; if (bc) { - bc->addresses = new (bc->zone->allocate(sizeof(DelayedPromise))) - DelayedPromise(t->m->system, bc->zone, p, bc->addresses); + bc->addresses = new(bc->zone) DelayedPromise(t->m->system, bc->zone, p, bc->addresses); return bc->addresses; } else { return p; @@ -1633,7 +1629,7 @@ class Frame { (TargetBytesPerWord, c->memory (c->register_(t->arch->thread()), Compiler::AddressType, TargetThreadCodeImage), c->promiseConstant - (new (context->zone.allocate(sizeof(OffsetPromise))) + (new(&context->zone) OffsetPromise (p, - reinterpret_cast(codeAllocator(t)->base)), Compiler::AddressType)) @@ -3417,8 +3413,7 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall) and (not (TailCalls and tailCall and (methodFlags(t, target) & ACC_NATIVE)))) { - Promise* p = new (bc->zone->allocate(sizeof(ListenPromise))) - ListenPromise(t->m->system, bc->zone); + Promise* p = new(bc->zone) ListenPromise(t->m->system, bc->zone); PROTECT(t, target); object pointer = makePointer(t, p); @@ -6636,7 +6631,7 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots, } if (path == 0) { - path = new (context->zone.allocate(sizeof(SubroutinePath))) + path = new(&context->zone) SubroutinePath(call, subroutinePath, makeRootTable(t, &(context->zone), context->method)); } @@ -7061,8 +7056,7 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) p != bc->addressSentinal; p = p->next) { - p->basis = new (bc->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(p->basis->value()); + p->basis = new(bc->zone) ResolvedPromise(p->basis->value()); } } @@ -9724,8 +9718,7 @@ compileCall(MyThread* t, Context* c, ThunkIndex index, bool call = true) (call ? Call : Jump, TargetBytesPerWord, RegisterOperand, &scratch); } else { Assembler::Constant proc - (new (c->zone.allocate(sizeof(ResolvedPromise))) - ResolvedPromise(reinterpret_cast(t->thunkTable[index]))); + (new(&c->zone) ResolvedPromise(reinterpret_cast(t->thunkTable[index]))); a->apply (call ? LongCall : LongJump, TargetBytesPerWord, ConstantOperand, &proc); diff --git a/src/compiler.cpp b/src/compiler.cpp index 5a89b38342..9fd3fc5e28 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -576,7 +576,7 @@ count(Cell* c) Cell* cons(Context* c, void* value, Cell* next) { - return new (c->zone->allocate(sizeof(Cell))) Cell(next, value); + return new (c->zone) Cell(next, value); } Cell* @@ -648,7 +648,7 @@ Link* link(Context* c, Event* predecessor, Link* nextPredecessor, Event* successor, Link* nextSuccessor, ForkState* forkState) { - return new (c->zone->allocate(sizeof(Link))) Link + return new(c->zone) Link (predecessor, nextPredecessor, successor, nextSuccessor, forkState); } @@ -1602,15 +1602,13 @@ constantSite(Context* c, Promise* value); ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { - return new (c->zone->allocate(sizeof(ShiftMaskPromise))) - ShiftMaskPromise(base, shift, mask); + return new(c->zone) ShiftMaskPromise(base, shift, mask); } CombinedPromise* combinedPromise(Context* c, Promise* low, Promise* high) { - return new (c->zone->allocate(sizeof(CombinedPromise))) - CombinedPromise(low, high); + return new(c->zone) CombinedPromise(low, high); } class ConstantSite: public Site { @@ -1686,14 +1684,13 @@ class ConstantSite: public Site { ConstantSite* constantSite(Context* c, Promise* value) { - return new (c->zone->allocate(sizeof(ConstantSite))) ConstantSite(value); + return new(c->zone) ConstantSite(value); } ResolvedPromise* resolved(Context* c, int64_t value) { - return new (c->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value); + return new(c->zone) ResolvedPromise(value); } ConstantSite* @@ -1776,7 +1773,7 @@ class AddressSite: public Site { AddressSite* addressSite(Context* c, Promise* address) { - return new (c->zone->allocate(sizeof(AddressSite))) AddressSite(address); + return new(c->zone) AddressSite(address); } RegisterSite* @@ -1978,15 +1975,13 @@ registerSite(Context* c, int number) assert(c, (1 << number) & (c->arch->generalRegisterMask() | c->arch->floatRegisterMask())); - return new (c->zone->allocate(sizeof(RegisterSite))) - RegisterSite(1 << number, number); + return new(c->zone) RegisterSite(1 << number, number); } RegisterSite* freeRegisterSite(Context* c, uint32_t mask) { - return new (c->zone->allocate(sizeof(RegisterSite))) - RegisterSite(mask, NoRegister); + return new(c->zone) RegisterSite(mask, NoRegister); } MemorySite* @@ -2219,8 +2214,7 @@ class MemorySite: public Site { MemorySite* memorySite(Context* c, int base, int offset, int index, unsigned scale) { - return new (c->zone->allocate(sizeof(MemorySite))) - MemorySite(base, offset, index, scale); + return new(c->zone) MemorySite(base, offset, index, scale); } MemorySite* @@ -2341,8 +2335,7 @@ read(Context* c, const SiteMask& mask, Value* successor = 0) { assert(c, (mask.typeMask != 1 << MemoryOperand) or mask.frameIndex >= 0); - return new (c->zone->allocate(sizeof(SingleRead))) - SingleRead(mask, successor); + return new(c->zone) SingleRead(mask, successor); } bool @@ -2762,7 +2755,7 @@ class MultiRead: public Read { MultiRead* multiRead(Context* c) { - return new (c->zone->allocate(sizeof(MultiRead))) MultiRead; + return new(c->zone) MultiRead; } class StubRead: public Read { @@ -2811,7 +2804,7 @@ class StubRead: public Read { StubRead* stubRead(Context* c) { - return new (c->zone->allocate(sizeof(StubRead))) StubRead; + return new(c->zone) StubRead; } Site* @@ -3121,15 +3114,13 @@ clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads, CodePromise* codePromise(Context* c, Event* e) { - return e->promises = new (c->zone->allocate(sizeof(CodePromise))) - CodePromise(c, e->promises); + return e->promises = new(c->zone) CodePromise(c, e->promises); } CodePromise* codePromise(Context* c, Promise* offset) { - return new (c->zone->allocate(sizeof(CodePromise))) - CodePromise(c, offset); + return new (c->zone) CodePromise(c, offset); } void @@ -3467,7 +3458,7 @@ appendCall(Context* c, Value* address, unsigned flags, Stack* argumentStack, unsigned argumentCount, unsigned stackArgumentFootprint) { - append(c, new (c->zone->allocate(sizeof(CallEvent))) + append(c, new(c->zone) CallEvent(c, address, flags, traceHandler, result, resultSize, argumentStack, argumentCount, stackArgumentFootprint)); @@ -3515,8 +3506,7 @@ class ReturnEvent: public Event { void appendReturn(Context* c, unsigned size, Value* value) { - append(c, new (c->zone->allocate(sizeof(ReturnEvent))) - ReturnEvent(c, size, value)); + append(c, new(c->zone) ReturnEvent(c, size, value)); } void @@ -3714,7 +3704,7 @@ pickSiteOrMove(Context* c, Value* src, Value* dst, Site* nextWord, Value* value(Context* c, ValueType type, Site* site = 0, Site* target = 0) { - return new (c->zone->allocate(sizeof(Value))) Value(site, target, type); + return new(c->zone) Value(site, target, type); } void @@ -3914,7 +3904,7 @@ appendMove(Context* c, BinaryOperation type, unsigned srcSize, assert(c, not thunk); - append(c, new (c->zone->allocate(sizeof(MoveEvent))) + append(c, new(c->zone) MoveEvent (c, type, srcSize, srcSelectSize, src, dstSize, dst, SiteMask(srcTypeMask, srcRegisterMask, AnyFrameIndex), @@ -4173,7 +4163,7 @@ snapshot(Context* c, Value* value, Snapshot* next) value, value->buddy, buffer); } - return new (c->zone->allocate(sizeof(Snapshot))) Snapshot(c, value, next); + return new(c->zone) Snapshot(c, value, next); } Snapshot* @@ -4189,8 +4179,7 @@ makeSnapshots(Context* c, Value* value, Snapshot* next) Stack* stack(Context* c, Value* value, Stack* next) { - return new (c->zone->allocate(sizeof(Stack))) - Stack(next ? next->index + 1 : 0, value, next); + return new(c->zone) Stack(next ? next->index + 1 : 0, value, next); } Value* @@ -4450,7 +4439,7 @@ appendCombine(Context* c, TernaryOperation type, resultSize, argumentStack, stackSize, 0); } else { append - (c, new (c->zone->allocate(sizeof(CombineEvent))) + (c, new(c->zone) CombineEvent (c, type, firstSize, first, @@ -4568,7 +4557,7 @@ appendTranslate(Context* c, BinaryOperation type, unsigned firstSize, 0, 0, result, resultSize, argumentStack, ceiling(firstSize, TargetBytesPerWord), 0); } else { - append(c, new (c->zone->allocate(sizeof(TranslateEvent))) + append(c, new(c->zone) TranslateEvent (c, type, firstSize, first, resultSize, result, SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), @@ -4597,7 +4586,7 @@ void appendOperation(Context* c, Operation op) { append - (c, new (c->zone->allocate(sizeof(OperationEvent))) OperationEvent(c, op)); + (c, new(c->zone) OperationEvent(c, op)); } class MemoryEvent: public Event { @@ -4677,7 +4666,7 @@ void appendMemory(Context* c, Value* base, int displacement, Value* index, unsigned scale, Value* result) { - append(c, new (c->zone->allocate(sizeof(MemoryEvent))) + append(c, new(c->zone) MemoryEvent(c, base, displacement, index, scale, result)); } @@ -4908,7 +4897,7 @@ appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first, result, address); } else { append - (c, new (c->zone->allocate(sizeof(BranchEvent))) + (c, new(c->zone) BranchEvent (c, type, size, first, second, address, SiteMask(firstTypeMask, firstRegisterMask, AnyFrameIndex), @@ -4972,8 +4961,7 @@ void appendJump(Context* c, UnaryOperation type, Value* address, bool exit = false, bool cleanLocals = false) { - append(c, new (c->zone->allocate(sizeof(JumpEvent))) - JumpEvent(c, type, address, exit, cleanLocals)); + append(c, new(c->zone) JumpEvent(c, type, address, exit, cleanLocals)); } class BoundsCheckEvent: public Event { @@ -5051,8 +5039,7 @@ void appendBoundsCheck(Context* c, Value* object, unsigned lengthOffset, Value* index, intptr_t handler) { - append(c, new (c->zone->allocate(sizeof(BoundsCheckEvent))) - BoundsCheckEvent(c, object, lengthOffset, index, handler)); + append(c, new(c->zone) BoundsCheckEvent(c, object, lengthOffset, index, handler)); } class FrameSiteEvent: public Event { @@ -5078,8 +5065,7 @@ class FrameSiteEvent: public Event { void appendFrameSite(Context* c, Value* value, int index) { - append(c, new (c->zone->allocate(sizeof(FrameSiteEvent))) - FrameSiteEvent(c, value, index)); + append(c, new(c->zone) FrameSiteEvent(c, value, index)); } unsigned @@ -5157,8 +5143,7 @@ class BuddyEvent: public Event { void appendBuddy(Context* c, Value* original, Value* buddy) { - append(c, new (c->zone->allocate(sizeof(BuddyEvent))) - BuddyEvent(c, original, buddy)); + append(c, new(c->zone) BuddyEvent(c, original, buddy)); } class SaveLocalsEvent: public Event { @@ -5183,8 +5168,7 @@ class SaveLocalsEvent: public Event { void appendSaveLocals(Context* c) { - append(c, new (c->zone->allocate(sizeof(SaveLocalsEvent))) - SaveLocalsEvent(c)); + append(c, new(c->zone) SaveLocalsEvent(c)); } class DummyEvent: public Event { @@ -5210,7 +5194,7 @@ appendDummy(Context* c) c->stack = i->stack; c->locals = i->locals; - append(c, new (c->zone->allocate(sizeof(DummyEvent))) DummyEvent(c)); + append(c, new(c->zone) DummyEvent(c)); c->stack = stack; c->locals = locals; @@ -5746,7 +5730,7 @@ class Block { Block* block(Context* c, Event* head) { - return new (c->zone->allocate(sizeof(Block))) Block(head); + return new(c->zone) Block(head); } void @@ -6057,8 +6041,7 @@ class MyCompiler: public Compiler { } virtual Subroutine* startSubroutine() { - return c.subroutine = new (c.zone->allocate(sizeof(MySubroutine))) - MySubroutine; + return c.subroutine = new(c.zone) MySubroutine; } virtual void returnFromSubroutine(Subroutine* subroutine, Operand* address) { @@ -6199,7 +6182,7 @@ class MyCompiler: public Compiler { } virtual Promise* machineIp(unsigned logicalIp) { - return new (c.zone->allocate(sizeof(IpPromise))) IpPromise(&c, logicalIp); + return new(c.zone) IpPromise(&c, logicalIp); } virtual Promise* poolAppend(intptr_t value) { @@ -6207,12 +6190,9 @@ class MyCompiler: public Compiler { } virtual Promise* poolAppendPromise(Promise* value) { - Promise* p = new (c.zone->allocate(sizeof(PoolPromise))) - PoolPromise(&c, c.constantCount); + Promise* p = new(c.zone) PoolPromise(&c, c.constantCount); - ConstantPoolNode* constant - = new (c.zone->allocate(sizeof(ConstantPoolNode))) - ConstantPoolNode(value); + ConstantPoolNode* constant = new (c.zone) ConstantPoolNode(value); if (c.firstConstant) { c.lastConstant->next = constant; @@ -6997,8 +6977,7 @@ Compiler* makeCompiler(System* system, Assembler* assembler, Zone* zone, Compiler::Client* client) { - return new (zone->allocate(sizeof(local::MyCompiler))) - local::MyCompiler(system, assembler, zone, client); + return new(zone) local::MyCompiler(system, assembler, zone, client); } } // namespace vm diff --git a/src/powerpc.cpp b/src/powerpc.cpp index f63bd270c6..6ec487ea88 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -233,7 +233,7 @@ class Context { public: Context(System* s, Allocator* a, Zone* zone): s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), - firstBlock(new (zone->allocate(sizeof(MyBlock))) MyBlock(this, 0)), + firstBlock(new(zone) MyBlock(this, 0)), lastBlock(firstBlock), jumpOffsetHead(0), jumpOffsetTail(0), constantPool(0), constantPoolCount(0) { } @@ -349,8 +349,7 @@ class Offset: public Promise { Promise* offset(Context* c) { - return new (c->zone->allocate(sizeof(Offset))) - Offset(c, c->lastBlock, c->code.length()); + return new(c->zone) Offset(c, c->lastBlock, c->code.length()); } bool @@ -468,14 +467,13 @@ void appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, bool conditional) { - OffsetTask* task = new (c->zone->allocate(sizeof(OffsetTask))) OffsetTask - (c->tasks, promise, instructionOffset, conditional); + OffsetTask* task = new(c->zone) OffsetTask(c->tasks, promise, instructionOffset, conditional); c->tasks = task; if (conditional) { - JumpOffset* offset = new (c->zone->allocate(sizeof(JumpOffset))) JumpOffset - (c->lastBlock, task, c->code.length() - c->lastBlock->offset); + JumpOffset* offset = + new(c->zone) JumpOffset(c->lastBlock, task, c->code.length() - c->lastBlock->offset); if (c->lastBlock->jumpOffsetTail) { c->lastBlock->jumpOffsetTail->next = offset; @@ -490,7 +488,7 @@ void appendJumpEvent(Context* c, MyBlock* b, unsigned offset, JumpOffset* head, JumpOffset* tail) { - JumpEvent* e = new (c->zone->allocate(sizeof(JumpEvent))) JumpEvent + JumpEvent* e = new(c->zone) JumpEvent (head, tail, offset); if (b->jumpEventTail) { @@ -858,8 +856,7 @@ void appendImmediateTask(Context* c, Promise* promise, Promise* offset, unsigned size, unsigned promiseOffset, bool address) { - c->tasks = new (c->zone->allocate(sizeof(ImmediateTask))) ImmediateTask - (c->tasks, promise, offset, size, promiseOffset, address); + c->tasks = new(c->zone) ImmediateTask(c->tasks, promise, offset, size, promiseOffset, address); } class ConstantPoolEntry: public Promise { @@ -890,8 +887,7 @@ class ConstantPoolEntry: public Promise { ConstantPoolEntry* appendConstantPoolEntry(Context* c, Promise* constant) { - return new (c->zone->allocate(sizeof(ConstantPoolEntry))) - ConstantPoolEntry(c, constant); + return new (c->zone) ConstantPoolEntry(c, constant); } void @@ -1785,8 +1781,7 @@ branchCM(Context* c, TernaryOperation op, unsigned size, ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { - return new (c->zone->allocate(sizeof(ShiftMaskPromise))) - ShiftMaskPromise(base, shift, mask); + return new (c->zone) ShiftMaskPromise(base, shift, mask); } void @@ -2462,8 +2457,7 @@ class MyAssembler: public Assembler { Register stack(StackRegister); Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread); Constant handlerConstant - (new (c.zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(handler)); + (new(c.zone) ResolvedPromise(handler)); branchRM(&c, JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, &handlerConstant); } @@ -2783,8 +2777,7 @@ class MyAssembler: public Assembler { MyBlock* b = c.lastBlock; b->size = c.code.length() - b->offset; if (startNew) { - c.lastBlock = new (c.zone->allocate(sizeof(MyBlock))) - MyBlock(&c, c.code.length()); + c.lastBlock = new(c.zone) MyBlock(&c, c.code.length()); } else { c.lastBlock = 0; } @@ -2855,9 +2848,9 @@ Assembler* makeAssembler(System* system, Allocator* allocator, Zone* zone, Assembler::Architecture* architecture) { - return new (zone->allocate(sizeof(MyAssembler))) - MyAssembler(system, allocator, zone, - static_cast(architecture)); + return + new(zone) MyAssembler(system, allocator, zone, + static_cast(architecture)); } } // namespace vm diff --git a/src/util.cpp b/src/util.cpp index 562255b95a..ce830efe2d 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -58,8 +58,7 @@ class TreeContext { TreeContext::Path* path(TreeContext* c, object node, TreeContext::Path* next) { - return new (c->zone->allocate(sizeof(TreeContext::Path))) - TreeContext::Path(node, next); + return new(c->zone) TreeContext::Path(node, next); } inline object diff --git a/src/x86.cpp b/src/x86.cpp index 5673b9da97..d5b6f0269a 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -157,7 +157,7 @@ class Context { public: Context(System* s, Allocator* a, Zone* zone, ArchitectureContext* ac): s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), - firstBlock(new (zone->allocate(sizeof(MyBlock))) MyBlock(0)), + firstBlock(new(zone) MyBlock(0)), lastBlock(firstBlock), ac(ac) { } @@ -207,8 +207,7 @@ expect(Context* c, bool v) ResolvedPromise* resolved(Context* c, int64_t value) { - return new (c->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value); + return new(c->zone) ResolvedPromise(value); } class CodePromise: public Promise { @@ -234,7 +233,7 @@ class CodePromise: public Promise { CodePromise* codePromise(Context* c, unsigned offset) { - return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset); + return new (c->zone) CodePromise(c, offset); } class Offset: public Promise { @@ -268,8 +267,7 @@ class Offset: public Promise { Promise* offset(Context* c) { - return new (c->zone->allocate(sizeof(Offset))) - Offset(c, c->lastBlock, c->code.length(), c->lastBlock->lastPadding); + return new(c->zone) Offset(c, c->lastBlock, c->code.length(), c->lastBlock->lastPadding); } class Task { @@ -346,8 +344,8 @@ void appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset, unsigned instructionSize) { - OffsetTask* task = new (c->zone->allocate(sizeof(OffsetTask))) OffsetTask - (c->tasks, promise, instructionOffset, instructionSize); + OffsetTask* task = + new(c->zone) OffsetTask(c->tasks, promise, instructionOffset, instructionSize); c->tasks = task; } @@ -418,7 +416,7 @@ void appendImmediateTask(Context* c, Promise* promise, Promise* offset, unsigned size, unsigned promiseOffset = 0) { - c->tasks = new (c->zone->allocate(sizeof(ImmediateTask))) ImmediateTask + c->tasks = new(c->zone) ImmediateTask (c->tasks, promise, offset, size, promiseOffset); } @@ -839,7 +837,7 @@ callM(Context* c, unsigned size UNUSED, Assembler::Memory* a) void alignedCallC(Context* c, unsigned size, Assembler::Constant* a) { - new (c->zone->allocate(sizeof(AlignmentPadding))) AlignmentPadding(c, 1, 4); + new(c->zone) AlignmentPadding(c, 1, 4); callC(c, size, a); } @@ -849,8 +847,7 @@ alignedLongCallC(Context* c, unsigned size, Assembler::Constant* a) assert(c, size == TargetBytesPerWord); if (TargetBytesPerWord == 8) { - new (c->zone->allocate(sizeof(AlignmentPadding))) - AlignmentPadding(c, 2, 8); + new (c->zone) AlignmentPadding(c, 2, 8); longCallC(c, size, a); } else { alignedCallC(c, size, a); @@ -860,7 +857,7 @@ alignedLongCallC(Context* c, unsigned size, Assembler::Constant* a) void alignedJumpC(Context* c, unsigned size, Assembler::Constant* a) { - new (c->zone->allocate(sizeof(AlignmentPadding))) AlignmentPadding(c, 1, 4); + new (c->zone) AlignmentPadding(c, 1, 4); jumpC(c, size, a); } @@ -870,8 +867,7 @@ alignedLongJumpC(Context* c, unsigned size, Assembler::Constant* a) assert(c, size == TargetBytesPerWord); if (TargetBytesPerWord == 8) { - new (c->zone->allocate(sizeof(AlignmentPadding))) - AlignmentPadding(c, 2, 8); + new (c->zone) AlignmentPadding(c, 2, 8); longJumpC(c, size, a); } else { alignedJumpC(c, size, a); @@ -1296,8 +1292,7 @@ moveAR(Context* c, unsigned aSize, Assembler::Address* a, ShiftMaskPromise* shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) { - return new (c->zone->allocate(sizeof(ShiftMaskPromise))) - ShiftMaskPromise(base, shift, mask); + return new(c->zone) ShiftMaskPromise(base, shift, mask); } void @@ -3707,8 +3702,7 @@ class MyAssembler: public Assembler { MyBlock* b = c.lastBlock; b->size = c.code.length() - b->offset; if (startNew) { - c.lastBlock = new (c.zone->allocate(sizeof(MyBlock))) - MyBlock(c.code.length()); + c.lastBlock = new(c.zone) MyBlock(c.code.length()); } else { c.lastBlock = 0; } @@ -3752,9 +3746,9 @@ Assembler* makeAssembler(System* system, Allocator* allocator, Zone* zone, Assembler::Architecture* architecture) { - return new (zone->allocate(sizeof(local::MyAssembler))) - local::MyAssembler(system, allocator, zone, - static_cast(architecture)); + return + new(zone) local::MyAssembler(system, allocator, zone, + static_cast(architecture)); } } // namespace vm From 24061251cfa17849208a168f2842ef150d9389d2 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 10 May 2012 12:10:22 -0600 Subject: [PATCH 093/140] fix readme.txt reference to binaryToObject --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index c067bb5a89..17bb8730aa 100644 --- a/readme.txt +++ b/readme.txt @@ -356,7 +356,7 @@ EOF Step 3: Make an object file out of the jar. - $ ../build/${platform}-${arch}/binaryToObject boot.jar boot-jar.o \ + $ ../build/${platform}-${arch}/binaryToObject/binaryToObject boot.jar boot-jar.o \ _binary_boot_jar_start _binary_boot_jar_end ${platform} ${arch} Step 4: Write a driver which starts the VM and runs the desired main From 3dcf886bbeb8d4d0adf51c71f379f071d5eec07f Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 10 May 2012 14:36:30 -0600 Subject: [PATCH 094/140] allow passing bootimage / codeimage start and end symbol names to the bootimage-generator The usage statement for the bootimage-generator now looks like this: build/linux-x86_64-bootimage/bootimage-generator \ -cp \ -bootimage \ -codeimage \ [-entry [.[]]] \ [-bootimage-symbols :] \ [-codeimage-symbols :] --- makefile | 4 +- readme.txt | 12 +- src/bootimage.cpp | 277 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 267 insertions(+), 26 deletions(-) diff --git a/makefile b/makefile index 67b4e7e738..85375afbd0 100755 --- a/makefile +++ b/makefile @@ -908,7 +908,9 @@ $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ $(ranlib) $(@) $(bootimage-object) $(codeimage-object): $(bootimage-generator) - $(<) $(classpath-build) $(bootimage-object) $(codeimage-object) + $(<) -cp $(classpath-build) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \ + -bootimage-symbols _binary_bootimage_bin_start:_binary_bootimage_bin_end \ + -codeimage-symbols _binary_codeimage_bin_start:_binary_codeimage_bin_end executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ diff --git a/readme.txt b/readme.txt index 17bb8730aa..7ae4a46e62 100644 --- a/readme.txt +++ b/readme.txt @@ -554,8 +554,16 @@ systems with case-insensitive filesystems such as Windows and OS X) Step 6: Build the boot and code images. - $ ../build/linux-i386-bootimage/bootimage-generator stage2 \ - bootimage-bin.o codeimage-bin.o + $ ../build/linux-i386-bootimage/bootimage-generator + -cp stage2 \ + -bootimage bootimage-bin.o \ + -codeimage codeimage-bin.o + +Note that you can override the default names for the start and end +symbols in the boot/code image by also passing: + + -bootimage-symbols my_bootimage_start:my_bootimage_end \ + -codeimage-symbols my_codeimage_start:my_codeimage_end Step 7: Write a driver which starts the VM and runs the desired main method. Note the bootimageBin function, which will be called by the diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 27f0e2aa8a..a58f6a6af5 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1285,7 +1285,9 @@ targetThunk(BootImage::Thunk t) void writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutput, BootImage* image, uint8_t* code, const char* className, - const char* methodName, const char* methodSpec) + const char* methodName, const char* methodSpec, + const char* bootimageStart, const char* bootimageEnd, + const char* codeimageStart, const char* codeimageEnd) { Zone zone(t->m->system, t->m->heap, 64 * 1024); @@ -1658,14 +1660,14 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp // } SymbolInfo bootimageSymbols[] = { - SymbolInfo(0, "_binary_bootimage_bin_start"), - SymbolInfo(bootimageData.length, "_binary_bootimage_bin_end") + SymbolInfo(0, bootimageStart), + SymbolInfo(bootimageData.length, bootimageEnd) }; platform->writeObject(bootimageOutput, Slice(bootimageSymbols, 2), Slice(bootimageData.data, bootimageData.length), Platform::Writable, TargetBytesPerWord); - compilationHandler.symbols.add(SymbolInfo(0, "_binary_codeimage_bin_start")); - compilationHandler.symbols.add(SymbolInfo(image->codeSize, "_binary_codeimage_bin_end")); + compilationHandler.symbols.add(SymbolInfo(0, codeimageStart)); + compilationHandler.symbols.add(SymbolInfo(image->codeSize, codeimageEnd)); platform->writeObject(codeOutput, Slice(compilationHandler.symbols), Slice(code, image->codeSize), Platform::Executable, TargetBytesPerWord); @@ -1686,28 +1688,251 @@ writeBootImage(Thread* t, uintptr_t* arguments) const char* methodName = reinterpret_cast(arguments[5]); const char* methodSpec = reinterpret_cast(arguments[6]); + const char* bootimageStart = reinterpret_cast(arguments[7]); + const char* bootimageEnd = reinterpret_cast(arguments[8]); + const char* codeimageStart = reinterpret_cast(arguments[9]); + const char* codeimageEnd = reinterpret_cast(arguments[10]); + writeBootImage2 (t, bootimageOutput, codeOutput, image, code, className, methodName, - methodSpec); + methodSpec, bootimageStart, bootimageEnd, codeimageStart, codeimageEnd); return 1; } +class Arg; + +class ArgParser { +public: + Arg* first; + Arg** last; + + ArgParser(): + first(0), + last(&first) {} + + bool parse(int ac, const char** av); + void printUsage(const char* exe); +}; + +class Arg { +public: + Arg* next; + bool required; + const char* name; + const char* desc; + + const char* value; + + Arg(ArgParser& parser, bool required, const char* name, const char* desc): + next(0), + required(required), + name(name), + desc(desc), + value(0) + { + *parser.last = this; + parser.last = &next; + } +}; + +bool ArgParser::parse(int ac, const char** av) { + Arg* state = 0; + + for(int i = 1; i < ac; i++) { + if(state) { + if(state->value) { + fprintf(stderr, "duplicate parameter %s: '%s' and '%s'\n", state->name, state->value, av[i]); + return false; + } + state->value = av[i]; + state = 0; + } else { + if(av[i][0] != '-') { + fprintf(stderr, "expected -parameter\n"); + return false; + } + for(Arg* arg = first; arg; arg = arg->next) { + if(strcmp(arg->name, &av[i][1]) == 0) { + state = arg; + } + } + if(!state) { + fprintf(stderr, "unrecognized parameter %s\n", av[i]); + return false; + } + } + } + + if(state) { + fprintf(stderr, "expected argument after -%s\n", state->name); + return false; + } + + for(Arg* arg = first; arg; arg = arg->next) { + if(arg->required && !arg->value) { + fprintf(stderr, "expected value for %s\n", arg->name); + return false; + } + } + + return true; +} + +void ArgParser::printUsage(const char* exe) { + fprintf(stderr, "usage:\n%s \\\n", exe); + for(Arg* arg = first; arg; arg = arg->next) { + const char* lineEnd = arg->next ? " \\" : ""; + if(arg->required) { + fprintf(stderr, " -%s\t%s%s\n", arg->name, arg->desc, lineEnd); + } else { + fprintf(stderr, " [-%s\t%s]%s\n", arg->name, arg->desc, lineEnd); + } + } +} + +class Arguments { +public: + + const char* classpath; + + const char* bootimage; + const char* codeimage; + + char* entryClass; + char* entryMethod; + char* entrySpec; + + char* bootimageStart; + char* bootimageEnd; + + char* codeimageStart; + char* codeimageEnd; + + bool maybeSplit(const char* src, char*& destA, char*& destB) { + if(src) { + const char* split = strchr(src, ':'); + if(!split) { + return false; + } + + destA = strndup(src, split - src); + destB = strdup(split + 1); + } + return true; + } + + Arguments(int ac, const char** av): + entryClass(0), + entryMethod(0), + entrySpec(0), + bootimageStart(strdup("_binary_bootimage_bin_start")), + bootimageEnd(strdup("_binary_bootimage_bin_end")), + codeimageStart(strdup("_binary_codeimage_bin_start")), + codeimageEnd(strdup("_binary_codeimage_bin_end")) + { + ArgParser parser; + Arg classpath(parser, true, "cp", ""); + Arg bootimage(parser, true, "bootimage", ""); + Arg codeimage(parser, true, "codeimage", ""); + Arg entry(parser, false, "entry", "[.[]]"); + Arg bootimageSymbols(parser, false, "bootimage-symbols", ":"); + Arg codeimageSymbols(parser, false, "codeimage-symbols", ":"); + + if(!parser.parse(ac, av)) { + parser.printUsage(av[0]); + exit(1); + } + + this->classpath = classpath.value; + this->bootimage = bootimage.value; + this->codeimage = codeimage.value; + + if(entry.value) { + if(const char* entryClassEnd = strchr(entry.value, '.')) { + entryClass = strndup(entry.value, entryClassEnd - entry.value); + if(const char* entryMethodEnd = strchr(entryClassEnd, '(')) { + entryMethod = strndup(entryClassEnd + 1, entryMethodEnd - entryClassEnd - 1); + entrySpec = strdup(entryMethodEnd); + } else { + entryMethod = strdup(entryClassEnd + 1); + } + } else { + entryClass = strdup(entry.value); + } + } + + if(!maybeSplit(bootimageSymbols.value, bootimageStart, bootimageEnd) || + !maybeSplit(codeimageSymbols.value, codeimageStart, codeimageEnd)) + { + fprintf(stderr, "wrong format for symbols\n"); + parser.printUsage(av[0]); + exit(1); + } + + } + + ~Arguments() { + if(entryClass) { + free(entryClass); + } + if(entryMethod) { + free(entryMethod); + } + if(entrySpec) { + free(entrySpec); + } + if(bootimageStart) { + free(bootimageStart); + } + if(bootimageEnd) { + free(bootimageEnd); + } + if(codeimageStart) { + free(codeimageStart); + } + if(codeimageEnd) { + free(codeimageEnd); + } + } + + void dump() { + printf( + "classpath = %s\n" + "bootimage = %s\n" + "codeimage = %s\n" + "entryClass = %s\n" + "entryMethod = %s\n" + "entrySpec = %s\n" + "bootimageStart = %s\n" + "bootimageEnd = %s\n" + "codeimageStart = %s\n" + "codeimageEnd = %s\n", + classpath, + bootimage, + codeimage, + entryClass, + entryMethod, + entrySpec, + bootimageStart, + bootimageEnd, + codeimageStart, + codeimageEnd); + } +}; + } // namespace int main(int ac, const char** av) { - if (ac < 4 or ac > 7) { - fprintf(stderr, "usage: %s " - " [ [ []]]\n", av[0]); - return -1; - } + Arguments args(ac, av); + // args.dump(); System* s = makeSystem(0); Heap* h = makeHeap(s, HeapCapacity * 2); Classpath* c = makeClasspath(s, h, AVIAN_JAVA_HOME, AVIAN_EMBED_PREFIX); - Finder* f = makeFinder(s, h, av[1], 0); + Finder* f = makeFinder(s, h, args.classpath, 0); Processor* p = makeProcessor(s, h, false); // todo: currently, the compiler cannot compile code with jumps or @@ -1728,25 +1953,31 @@ main(int ac, const char** av) enter(t, Thread::ActiveState); enter(t, Thread::IdleState); - FileOutputStream bootimageOutput(av[2]); + FileOutputStream bootimageOutput(args.bootimage); if (!bootimageOutput.isValid()) { - fprintf(stderr, "unable to open %s\n", av[2]); + fprintf(stderr, "unable to open %s\n", args.bootimage); return -1; } - FileOutputStream codeOutput(av[3]); + FileOutputStream codeOutput(args.codeimage); if (!codeOutput.isValid()) { - fprintf(stderr, "unable to open %s\n", av[3]); + fprintf(stderr, "unable to open %s\n", args.codeimage); return -1; } - uintptr_t arguments[] = { reinterpret_cast(&bootimageOutput), - reinterpret_cast(&codeOutput), - reinterpret_cast(&image), - reinterpret_cast(code), - reinterpret_cast(ac > 4 ? av[4] : 0), - reinterpret_cast(ac > 5 ? av[5] : 0), - reinterpret_cast(ac > 6 ? av[6] : 0) }; + uintptr_t arguments[] = { + reinterpret_cast(&bootimageOutput), + reinterpret_cast(&codeOutput), + reinterpret_cast(&image), + reinterpret_cast(code), + reinterpret_cast(args.entryClass), + reinterpret_cast(args.entryMethod), + reinterpret_cast(args.entrySpec), + reinterpret_cast(args.bootimageStart), + reinterpret_cast(args.bootimageEnd), + reinterpret_cast(args.codeimageStart), + reinterpret_cast(args.codeimageEnd) + }; run(t, writeBootImage, arguments); From 362d6594a83dee9585d6c871919f31e4bf9dd734 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Fri, 11 May 2012 09:06:51 -0600 Subject: [PATCH 095/140] fix minor memory leak with default bootimage symbols --- src/bootimage.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index a58f6a6af5..548b8bd39d 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1826,10 +1826,10 @@ public: entryClass(0), entryMethod(0), entrySpec(0), - bootimageStart(strdup("_binary_bootimage_bin_start")), - bootimageEnd(strdup("_binary_bootimage_bin_end")), - codeimageStart(strdup("_binary_codeimage_bin_start")), - codeimageEnd(strdup("_binary_codeimage_bin_end")) + bootimageStart(0), + bootimageEnd(0), + codeimageStart(0), + codeimageEnd(0) { ArgParser parser; Arg classpath(parser, true, "cp", ""); @@ -1870,6 +1870,22 @@ public: exit(1); } + if(!bootimageStart) { + bootimageStart = strdup("_binary_bootimage_bin_start"); + } + + if(!bootimageEnd) { + bootimageEnd = strdup("_binary_bootimage_bin_end"); + } + + if(!codeimageStart) { + codeimageStart = strdup("_binary_codeimage_bin_start"); + } + + if(!codeimageEnd) { + codeimageEnd = strdup("_binary_codeimage_bin_end"); + } + } ~Arguments() { From 90fae940a7eb45ef95023b4869d156286fc51d05 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 11 May 2012 13:19:55 -0600 Subject: [PATCH 096/140] throw IncompatibleClassChangeError on unexpected static status If a class references a field or method as static and we find it's actually non-static -- or vice-versa -- we ought to throw an error rather than abort. --- src/compile.cpp | 49 +++++++++++++++++++++++++++++++++++++------------ vm.pro | 1 + 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index e6943f592a..c6c4f4aba1 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2368,6 +2368,31 @@ findInterfaceMethodFromInstanceAndReference return findInterfaceMethodFromInstance(t, method, instance); } +void +checkMethod(Thread* t, object method, bool shouldBeStatic) +{ + if (((methodFlags(t, method) & ACC_STATIC) == 0) == shouldBeStatic) { + throwNew(t, Machine::IncompatibleClassChangeErrorType, + "expected %s.%s%s to be %s", + &byteArrayBody(t, className(t, methodClass(t, method)), 0), + &byteArrayBody(t, methodName(t, method), 0), + &byteArrayBody(t, methodSpec(t, method), 0), + shouldBeStatic ? "static" : "non-static"); + } +} + +void +checkField(Thread* t, object field, bool shouldBeStatic) +{ + if (((fieldFlags(t, field) & ACC_STATIC) == 0) == shouldBeStatic) { + throwNew(t, Machine::IncompatibleClassChangeErrorType, + "expected %s.%s to be %s", + &byteArrayBody(t, className(t, fieldClass(t, field)), 0), + &byteArrayBody(t, fieldName(t, field), 0), + shouldBeStatic ? "static" : "non-static"); + } +} + int64_t findSpecialMethodFromReference(MyThread* t, object pair) { @@ -2380,7 +2405,7 @@ findSpecialMethodFromReference(MyThread* t, object pair) target = findVirtualMethod(t, target, classSuper(t, class_)); } - assert(t, (methodFlags(t, target) & ACC_STATIC) == 0); + checkMethod(t, target, false); return prepareMethodForCall(t, target); } @@ -2390,7 +2415,7 @@ findStaticMethodFromReference(MyThread* t, object pair) { object target = resolveMethod(t, pair); - assert(t, methodFlags(t, target) & ACC_STATIC); + checkMethod(t, target, true); return prepareMethodForCall(t, target); } @@ -2404,7 +2429,7 @@ findVirtualMethodFromReference(MyThread* t, object pair, object instance) target = findVirtualMethod(t, target, objectClass(t, instance)); - assert(t, (methodFlags(t, target) & ACC_STATIC) == 0); + checkMethod(t, target, false); return prepareMethodForCall(t, target); } @@ -4583,7 +4608,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, Compiler::Operand* table; if (instruction == getstatic) { - assert(t, fieldFlags(t, field) & ACC_STATIC); + checkField(t, field, true); PROTECT(t, field); @@ -4603,7 +4628,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, table = frame->append(classStaticTable(t, fieldClass(t, field))); } else { - assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0); + checkField(t, field, false); table = frame->popObject(); @@ -5048,7 +5073,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, int returnCode; bool tailCall; if (LIKELY(target)) { - assert(t, (methodFlags(t, target) & ACC_STATIC) == 0); + checkMethod(t, target, false); argument = target; thunk = findInterfaceMethodFromInstanceThunk; @@ -5107,7 +5132,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, target = findVirtualMethod(t, target, classSuper(t, class_)); } - assert(t, (methodFlags(t, target) & ACC_STATIC) == 0); + checkMethod(t, target, false); bool tailCall = isTailCall(t, code, ip, context->method, target); @@ -5137,7 +5162,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, object target = resolveMethod(t, context->method, index - 1, false); if (LIKELY(target)) { - assert(t, methodFlags(t, target) & ACC_STATIC); + checkMethod(t, target, true); if (not intrinsic(t, frame, target)) { bool tailCall = isTailCall(t, code, ip, context->method, target); @@ -5163,8 +5188,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, object target = resolveMethod(t, context->method, index - 1, false); if (LIKELY(target)) { - assert(t, (methodFlags(t, target) & ACC_STATIC) == 0); - + checkMethod(t, target, false); + if (not intrinsic(t, frame, target)) { bool tailCall = isTailCall(t, code, ip, context->method, target); @@ -5777,7 +5802,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, object staticTable = 0; if (instruction == putstatic) { - assert(t, fieldFlags(t, field) & ACC_STATIC); + checkField(t, field, true); if (fieldClass(t, field) != methodClass(t, context->method) and classNeedsInit(t, fieldClass(t, field))) @@ -5797,7 +5822,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, staticTable = classStaticTable(t, fieldClass(t, field)); } else { - assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0); + checkField(t, field, false); if (inTryBlock(t, code, ip - 3)) { c->saveLocals(); diff --git a/vm.pro b/vm.pro index 495bc4c3ab..4cdb1654ee 100644 --- a/vm.pro +++ b/vm.pro @@ -66,6 +66,7 @@ -keep public class java.lang.UnsatisfiedLinkError -keep public class java.lang.ExceptionInInitializerError -keep public class java.lang.OutOfMemoryError +-keep public class java.lang.IncompatibleClassChangeError -keep public class java.lang.reflect.InvocationTargetException -keep public class java.io.IOException -keep public class java.io.FileNotFoundException From d0eda37a9017889128b2a64c5b519b3b2c4e8219 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 11 May 2012 13:23:19 -0600 Subject: [PATCH 097/140] make Thread.interrupted static to match Java API --- classpath/java/lang/Thread.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index 4846287daf..7d403ec367 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -145,8 +145,8 @@ public class Thread implements Runnable { private static native boolean interrupt(long peer); - public boolean interrupted() { - return interrupted(peer); + public static boolean interrupted() { + return interrupted(currentThread().peer); } private static native boolean interrupted(long peer); From f94d10cbba05aaf25b8fec7a618101598ac853bd Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 11 May 2012 16:43:38 -0600 Subject: [PATCH 098/140] document iOS support in readme.txt --- readme.txt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/readme.txt b/readme.txt index 7a5591715f..6c08030677 100644 --- a/readme.txt +++ b/readme.txt @@ -54,7 +54,7 @@ Avian can currently target the following platforms: Linux (i386, x86_64, ARM, and 32-bit PowerPC) Windows (i386 and x86_64) Mac OS X (i386, x86_64 and 32-bit PowerPC) - + Apple iOS (i386 and ARM) Building -------- @@ -78,6 +78,7 @@ certain flags described below, all of which are optional. arch={i386,x86_64,powerpc,arm} \ process={compile,interpret} \ mode={debug,debug-fast,fast,small} \ + ios={true,false} \ bootimage={true,false} \ heapdump={true,false} \ tails={true,false} \ @@ -93,13 +94,20 @@ certain flags described below, all of which are optional. default: output of $(uname -m), normalized in some cases (e.g. i686 -> i386) + * process - choice between pure interpreter or JIT compiler + default: compile + * mode - which set of compilation flags to use to determine optimization level, debug symbols, and whether to enable assertions default: fast - * process - choice between pure interpreter or JIT compiler - default: compile + * ios - if true, cross-compile for iOS on OS X. Note that + non-jailbroken iOS devices do not allow JIT compilation, so only + process=interpret or bootimage=true builds will run on such + devices. See git://oss.readytalk.com/hello-ios.git for an example + of an Xcode project for iOS which uses Avian. + default: false * bootimage - if true, create a boot image containing the pre-parsed class library and ahead-of-time compiled methods. This option is From 8d57e91971cc5d4f36bcac31ce7ea8260177e6be Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 11 May 2012 17:43:13 -0600 Subject: [PATCH 099/140] add script for updating copyright years based on most recent Git commit --- update-copyright.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 update-copyright.sh diff --git a/update-copyright.sh b/update-copyright.sh new file mode 100644 index 0000000000..994addef38 --- /dev/null +++ b/update-copyright.sh @@ -0,0 +1,12 @@ +for x in $(find -name *.S -or -name *.cpp -or -name *.h -or -name *.java | sort); do + year_of_last_change=$(git log -1 --format=format:"%ai" $x | cut -c 1-4) + copyright_years=$(grep "^/\* Copyright (c) .*, Avian Contributors$" $x | sed "s-^/\* Copyright (c) \(.*\), Avian Contributors\$-\1-") + if [ "$copyright_years" != "" ]; then + first_copyright_year=$(echo "$copyright_years" | sed "s/\(.*\)-.*/\1/") + last_copyright_year=$(echo "$copyright_years" | sed "s/.*-\(.*\)/\1/") + if [ "$last_copyright_year" != "$year_of_last_change" ]; then + echo "$first_copyright_year-$year_of_last_change $x" + sed -i "s:^/\* Copyright (c) .*, Avian Contributors\$:/* Copyright (c) $first_copyright_year-$year_of_last_change, Avian Contributors:" $x + fi + fi +done From 0addd8c8147d59460523f2a12534c6ae2605a2fc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 11 May 2012 17:43:27 -0600 Subject: [PATCH 100/140] update copyright years --- classpath/avian/Addendum.java | 2 +- classpath/avian/ClassAddendum.java | 2 +- classpath/avian/Classes.java | 2 +- classpath/avian/Continuations.java | 2 +- classpath/avian/Machine.java | 2 +- classpath/avian/MethodAddendum.java | 2 +- classpath/avian/OpenJDK.java | 2 +- classpath/avian/Stream.java | 2 +- classpath/avian/SystemClassLoader.java | 2 +- classpath/avian/VMClass.java | 2 +- classpath/avian/VMField.java | 2 +- classpath/java-io.cpp | 2 +- classpath/java-lang.cpp | 2 +- classpath/java-net.cpp | 2 +- classpath/java-util-zip.cpp | 2 +- classpath/java-util.cpp | 2 +- classpath/java/io/BufferedInputStream.java | 2 +- classpath/java/io/BufferedReader.java | 2 +- classpath/java/io/ByteArrayOutputStream.java | 2 +- classpath/java/io/File.java | 2 +- classpath/java/io/FileInputStream.java | 2 +- classpath/java/io/InputStream.java | 2 +- classpath/java/io/ObjectInputStream.java | 2 +- classpath/java/io/ObjectOutputStream.java | 2 +- classpath/java/io/PrintStream.java | 2 +- classpath/java/io/RandomAccessFile.java | 2 +- classpath/java/io/Reader.java | 2 +- classpath/java/lang/Character.java | 2 +- classpath/java/lang/Class.java | 2 +- classpath/java/lang/ClassLoader.java | 2 +- classpath/java/lang/Enum.java | 2 +- classpath/java/lang/Float.java | 2 +- classpath/java/lang/Package.java | 2 +- classpath/java/lang/Runtime.java | 2 +- classpath/java/lang/String.java | 2 +- classpath/java/lang/System.java | 2 +- classpath/java/lang/Thread.java | 2 +- classpath/java/lang/reflect/Field.java | 2 +- classpath/java/lang/reflect/InvocationHandler.java | 2 +- classpath/java/lang/reflect/Member.java | 2 +- classpath/java/lang/reflect/Proxy.java | 2 +- classpath/java/net/URL.java | 2 +- classpath/java/net/URLConnection.java | 2 +- classpath/java/net/URLStreamHandler.java | 2 +- classpath/java/nio/Buffer.java | 2 +- classpath/java/nio/ByteBuffer.java | 2 +- classpath/java/nio/channels/Channels.java | 2 +- classpath/java/nio/channels/SelectableChannel.java | 2 +- classpath/java/nio/channels/ServerSocketChannel.java | 2 +- classpath/java/nio/channels/SocketChannel.java | 2 +- classpath/java/nio/channels/SocketSelector.java | 2 +- classpath/java/security/CodeSource.java | 2 +- classpath/java/security/ProtectionDomain.java | 2 +- classpath/java/util/AbstractCollection.java | 2 +- classpath/java/util/ArrayList.java | 2 +- classpath/java/util/Collections.java | 2 +- classpath/java/util/Locale.java | 2 +- classpath/java/util/Properties.java | 2 +- classpath/java/util/Random.java | 2 +- classpath/java/util/TreeSet.java | 2 +- classpath/java/util/Vector.java | 2 +- classpath/java/util/regex/Matcher.java | 2 +- classpath/java/util/zip/Deflater.java | 2 +- classpath/java/util/zip/DeflaterOutputStream.java | 2 +- classpath/java/util/zip/Inflater.java | 2 +- classpath/java/util/zip/ZipEntry.java | 2 +- classpath/java/util/zip/ZipFile.java | 2 +- license.txt | 2 +- src/allocator.h | 2 +- src/arm.cpp | 2 +- src/assembler.h | 2 +- src/binaryToObject/elf.cpp | 2 +- src/binaryToObject/endianness.h | 2 +- src/binaryToObject/mach-o.cpp | 2 +- src/binaryToObject/main.cpp | 2 +- src/binaryToObject/pe.cpp | 2 +- src/binaryToObject/tools.cpp | 2 +- src/binaryToObject/tools.h | 2 +- src/boot-javahome.cpp | 2 +- src/boot.cpp | 2 +- src/bootimage.cpp | 2 +- src/bootimage.h | 2 +- src/builtin.cpp | 2 +- src/classpath-avian.cpp | 2 +- src/classpath-common.h | 2 +- src/classpath-openjdk.cpp | 2 +- src/common.h | 2 +- src/compile-arm.S | 2 +- src/compile.cpp | 2 +- src/compiler.cpp | 2 +- src/compiler.h | 2 +- src/environment.h | 2 +- src/finder.cpp | 2 +- src/finder.h | 2 +- src/heap.h | 2 +- src/interpret.cpp | 2 +- src/machine.cpp | 2 +- src/machine.h | 2 +- src/main.cpp | 2 +- src/openjdk/jni_md.h | 2 +- src/posix.cpp | 2 +- src/powerpc.cpp | 2 +- src/powerpc.h | 2 +- src/process.h | 2 +- src/processor.h | 2 +- src/system.h | 2 +- src/util.cpp | 2 +- src/windows.cpp | 2 +- src/x86.cpp | 2 +- src/x86.h | 2 +- src/zlib-custom.h | 2 +- 111 files changed, 111 insertions(+), 111 deletions(-) diff --git a/classpath/avian/Addendum.java b/classpath/avian/Addendum.java index b363ecfc7c..b5c86d9008 100644 --- a/classpath/avian/Addendum.java +++ b/classpath/avian/Addendum.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2010, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/ClassAddendum.java b/classpath/avian/ClassAddendum.java index 276be33fe9..48ac3bdd07 100644 --- a/classpath/avian/ClassAddendum.java +++ b/classpath/avian/ClassAddendum.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2010, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/Classes.java b/classpath/avian/Classes.java index 1d2ad9370e..a445114022 100644 --- a/classpath/avian/Classes.java +++ b/classpath/avian/Classes.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Avian Contributors +/* Copyright (c) 2010-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/Continuations.java b/classpath/avian/Continuations.java index 4ca98d86bd..a2d4948c8b 100644 --- a/classpath/avian/Continuations.java +++ b/classpath/avian/Continuations.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2010, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/Machine.java b/classpath/avian/Machine.java index a17cbff9d7..6115cf0c37 100644 --- a/classpath/avian/Machine.java +++ b/classpath/avian/Machine.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/MethodAddendum.java b/classpath/avian/MethodAddendum.java index 597c169179..e2ae385b81 100644 --- a/classpath/avian/MethodAddendum.java +++ b/classpath/avian/MethodAddendum.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2010, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/OpenJDK.java b/classpath/avian/OpenJDK.java index de9c6f1f40..95248b2398 100644 --- a/classpath/avian/OpenJDK.java +++ b/classpath/avian/OpenJDK.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Avian Contributors +/* Copyright (c) 2010-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/Stream.java b/classpath/avian/Stream.java index 14e6fc5773..a0762e6213 100644 --- a/classpath/avian/Stream.java +++ b/classpath/avian/Stream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/SystemClassLoader.java b/classpath/avian/SystemClassLoader.java index defb9d490a..5c228cd9c1 100644 --- a/classpath/avian/SystemClassLoader.java +++ b/classpath/avian/SystemClassLoader.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/VMClass.java b/classpath/avian/VMClass.java index 5a3fdc662f..c3e87353b5 100644 --- a/classpath/avian/VMClass.java +++ b/classpath/avian/VMClass.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/avian/VMField.java b/classpath/avian/VMField.java index 8df0d426c5..2e986321da 100644 --- a/classpath/avian/VMField.java +++ b/classpath/avian/VMField.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index d08601a465..86020f57c8 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 855e6b5c60..3cad9680a3 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java-net.cpp b/classpath/java-net.cpp index 20d853adc2..1cfea1fbc2 100644 --- a/classpath/java-net.cpp +++ b/classpath/java-net.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Avian Contributors +/* Copyright (c) 2010-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java-util-zip.cpp b/classpath/java-util-zip.cpp index f883e528bc..9ae2833332 100644 --- a/classpath/java-util-zip.cpp +++ b/classpath/java-util-zip.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java-util.cpp b/classpath/java-util.cpp index b880ff2d95..4c0a73161c 100644 --- a/classpath/java-util.cpp +++ b/classpath/java-util.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/BufferedInputStream.java b/classpath/java/io/BufferedInputStream.java index 67ac256a21..3f03a7c743 100644 --- a/classpath/java/io/BufferedInputStream.java +++ b/classpath/java/io/BufferedInputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/BufferedReader.java b/classpath/java/io/BufferedReader.java index 2618dfdbd6..5b90b62012 100644 --- a/classpath/java/io/BufferedReader.java +++ b/classpath/java/io/BufferedReader.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/ByteArrayOutputStream.java b/classpath/java/io/ByteArrayOutputStream.java index f0668da2da..0960dd3008 100644 --- a/classpath/java/io/ByteArrayOutputStream.java +++ b/classpath/java/io/ByteArrayOutputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index 59c7da8d16..86e093495b 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/FileInputStream.java b/classpath/java/io/FileInputStream.java index 29df029529..d3cd3cd08e 100644 --- a/classpath/java/io/FileInputStream.java +++ b/classpath/java/io/FileInputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/InputStream.java b/classpath/java/io/InputStream.java index 8e74c2db8d..ec29b52b7a 100644 --- a/classpath/java/io/InputStream.java +++ b/classpath/java/io/InputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/ObjectInputStream.java b/classpath/java/io/ObjectInputStream.java index 45bacc7380..b0f1ec0dd7 100644 --- a/classpath/java/io/ObjectInputStream.java +++ b/classpath/java/io/ObjectInputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/ObjectOutputStream.java b/classpath/java/io/ObjectOutputStream.java index 7e45f9d2cc..3f310128bd 100644 --- a/classpath/java/io/ObjectOutputStream.java +++ b/classpath/java/io/ObjectOutputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/PrintStream.java b/classpath/java/io/PrintStream.java index a720fac6a0..7bd27d06b1 100644 --- a/classpath/java/io/PrintStream.java +++ b/classpath/java/io/PrintStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/RandomAccessFile.java b/classpath/java/io/RandomAccessFile.java index cc3c41e757..b6e88dd00e 100644 --- a/classpath/java/io/RandomAccessFile.java +++ b/classpath/java/io/RandomAccessFile.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/io/Reader.java b/classpath/java/io/Reader.java index a09c8a24e9..2edfd70803 100644 --- a/classpath/java/io/Reader.java +++ b/classpath/java/io/Reader.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/Character.java b/classpath/java/lang/Character.java index 88025280e8..3e7f1ed269 100644 --- a/classpath/java/lang/Character.java +++ b/classpath/java/lang/Character.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index 22b645793a..eb183260d6 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/ClassLoader.java b/classpath/java/lang/ClassLoader.java index e245e4c9f1..9f2a853c46 100644 --- a/classpath/java/lang/ClassLoader.java +++ b/classpath/java/lang/ClassLoader.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/Enum.java b/classpath/java/lang/Enum.java index cf1d033cc3..8d0d4756b0 100644 --- a/classpath/java/lang/Enum.java +++ b/classpath/java/lang/Enum.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/Float.java b/classpath/java/lang/Float.java index d466cca2a3..408de61220 100644 --- a/classpath/java/lang/Float.java +++ b/classpath/java/lang/Float.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/Package.java b/classpath/java/lang/Package.java index 5cd9b9547e..ed1e4e2985 100644 --- a/classpath/java/lang/Package.java +++ b/classpath/java/lang/Package.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/Runtime.java b/classpath/java/lang/Runtime.java index 88c8ba71e3..a3c00bcbbf 100644 --- a/classpath/java/lang/Runtime.java +++ b/classpath/java/lang/Runtime.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index 83ce12dfa3..24a893ad87 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/System.java b/classpath/java/lang/System.java index 827f357e8b..859121c56d 100644 --- a/classpath/java/lang/System.java +++ b/classpath/java/lang/System.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index 7d403ec367..539a709169 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java index 524cb7613a..8d76a6258f 100644 --- a/classpath/java/lang/reflect/Field.java +++ b/classpath/java/lang/reflect/Field.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/reflect/InvocationHandler.java b/classpath/java/lang/reflect/InvocationHandler.java index 9541797ad3..584ae0c430 100644 --- a/classpath/java/lang/reflect/InvocationHandler.java +++ b/classpath/java/lang/reflect/InvocationHandler.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/reflect/Member.java b/classpath/java/lang/reflect/Member.java index e5e74042c6..09b00759c4 100644 --- a/classpath/java/lang/reflect/Member.java +++ b/classpath/java/lang/reflect/Member.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2010, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/lang/reflect/Proxy.java b/classpath/java/lang/reflect/Proxy.java index 2801f96618..06805fc72c 100644 --- a/classpath/java/lang/reflect/Proxy.java +++ b/classpath/java/lang/reflect/Proxy.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2010, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/net/URL.java b/classpath/java/net/URL.java index d1c97450ec..f80e327997 100644 --- a/classpath/java/net/URL.java +++ b/classpath/java/net/URL.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/net/URLConnection.java b/classpath/java/net/URLConnection.java index 0219fbe688..0ff8cacb4b 100644 --- a/classpath/java/net/URLConnection.java +++ b/classpath/java/net/URLConnection.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/net/URLStreamHandler.java b/classpath/java/net/URLStreamHandler.java index 2505408921..0e08bf45da 100644 --- a/classpath/java/net/URLStreamHandler.java +++ b/classpath/java/net/URLStreamHandler.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/Buffer.java b/classpath/java/nio/Buffer.java index c93c11f347..00e34c6932 100644 --- a/classpath/java/nio/Buffer.java +++ b/classpath/java/nio/Buffer.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/ByteBuffer.java b/classpath/java/nio/ByteBuffer.java index 2dee03f7d9..e63217f6ea 100644 --- a/classpath/java/nio/ByteBuffer.java +++ b/classpath/java/nio/ByteBuffer.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/channels/Channels.java b/classpath/java/nio/channels/Channels.java index 849a16dffc..2e786e70b2 100644 --- a/classpath/java/nio/channels/Channels.java +++ b/classpath/java/nio/channels/Channels.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Avian Contributors +/* Copyright (c) 2010-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/channels/SelectableChannel.java b/classpath/java/nio/channels/SelectableChannel.java index 734bce9fc8..0475f6adfe 100644 --- a/classpath/java/nio/channels/SelectableChannel.java +++ b/classpath/java/nio/channels/SelectableChannel.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/channels/ServerSocketChannel.java b/classpath/java/nio/channels/ServerSocketChannel.java index 53e6eec36d..1b27e0f049 100644 --- a/classpath/java/nio/channels/ServerSocketChannel.java +++ b/classpath/java/nio/channels/ServerSocketChannel.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/channels/SocketChannel.java b/classpath/java/nio/channels/SocketChannel.java index 65c9768d88..36fdf06c2e 100644 --- a/classpath/java/nio/channels/SocketChannel.java +++ b/classpath/java/nio/channels/SocketChannel.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/nio/channels/SocketSelector.java b/classpath/java/nio/channels/SocketSelector.java index a19d608918..82bcd6da41 100644 --- a/classpath/java/nio/channels/SocketSelector.java +++ b/classpath/java/nio/channels/SocketSelector.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/security/CodeSource.java b/classpath/java/security/CodeSource.java index 296f38c128..8ae784177a 100644 --- a/classpath/java/security/CodeSource.java +++ b/classpath/java/security/CodeSource.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/security/ProtectionDomain.java b/classpath/java/security/ProtectionDomain.java index 25673c8ee3..f17bf6810e 100644 --- a/classpath/java/security/ProtectionDomain.java +++ b/classpath/java/security/ProtectionDomain.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/AbstractCollection.java b/classpath/java/util/AbstractCollection.java index 54cd7288df..f7e06bad32 100644 --- a/classpath/java/util/AbstractCollection.java +++ b/classpath/java/util/AbstractCollection.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/ArrayList.java b/classpath/java/util/ArrayList.java index 698f3f79df..d7a61d61ed 100644 --- a/classpath/java/util/ArrayList.java +++ b/classpath/java/util/ArrayList.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/Collections.java b/classpath/java/util/Collections.java index 40c133f753..acb94cb40d 100644 --- a/classpath/java/util/Collections.java +++ b/classpath/java/util/Collections.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/Locale.java b/classpath/java/util/Locale.java index 373506bdec..66e685378b 100644 --- a/classpath/java/util/Locale.java +++ b/classpath/java/util/Locale.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2010, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/Properties.java b/classpath/java/util/Properties.java index 10b5c90687..9b1798491f 100644 --- a/classpath/java/util/Properties.java +++ b/classpath/java/util/Properties.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/Random.java b/classpath/java/util/Random.java index 311230f538..ac39a4417e 100644 --- a/classpath/java/util/Random.java +++ b/classpath/java/util/Random.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/TreeSet.java b/classpath/java/util/TreeSet.java index 01e76496a2..0faac7ad12 100644 --- a/classpath/java/util/TreeSet.java +++ b/classpath/java/util/TreeSet.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/Vector.java b/classpath/java/util/Vector.java index e95c8df414..0e1dadd7fe 100644 --- a/classpath/java/util/Vector.java +++ b/classpath/java/util/Vector.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/regex/Matcher.java b/classpath/java/util/regex/Matcher.java index 99f9d9daad..dd21a062af 100644 --- a/classpath/java/util/regex/Matcher.java +++ b/classpath/java/util/regex/Matcher.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2010, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/zip/Deflater.java b/classpath/java/util/zip/Deflater.java index 8368bb0817..9b6b832039 100644 --- a/classpath/java/util/zip/Deflater.java +++ b/classpath/java/util/zip/Deflater.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/zip/DeflaterOutputStream.java b/classpath/java/util/zip/DeflaterOutputStream.java index 3ee3fcdbb8..c77fbd1a52 100644 --- a/classpath/java/util/zip/DeflaterOutputStream.java +++ b/classpath/java/util/zip/DeflaterOutputStream.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/zip/Inflater.java b/classpath/java/util/zip/Inflater.java index 9f44415194..a4c00e6934 100644 --- a/classpath/java/util/zip/Inflater.java +++ b/classpath/java/util/zip/Inflater.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/zip/ZipEntry.java b/classpath/java/util/zip/ZipEntry.java index ffa8a1a82e..31359a8507 100644 --- a/classpath/java/util/zip/ZipEntry.java +++ b/classpath/java/util/zip/ZipEntry.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/classpath/java/util/zip/ZipFile.java b/classpath/java/util/zip/ZipFile.java index d356bbf5ed..f3d0428e82 100644 --- a/classpath/java/util/zip/ZipFile.java +++ b/classpath/java/util/zip/ZipFile.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2009, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/license.txt b/license.txt index 4ed92c217a..22265643ee 100644 --- a/license.txt +++ b/license.txt @@ -1,4 +1,4 @@ -Copyright (c) 2008-2011, Avian Contributors +Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/src/allocator.h b/src/allocator.h index 34febb8cd8..5bad9044b3 100644 --- a/src/allocator.h +++ b/src/allocator.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/arm.cpp b/src/arm.cpp index 784d4f3824..34b777175f 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, Avian Contributors +/* Copyright (c) 2010-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/assembler.h b/src/assembler.h index 07e02a31d5..d2ba2caf5d 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/binaryToObject/elf.cpp b/src/binaryToObject/elf.cpp index 3548ac8431..caf7c9c545 100644 --- a/src/binaryToObject/elf.cpp +++ b/src/binaryToObject/elf.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2011, Avian Contributors +/* Copyright (c) 2009-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/binaryToObject/endianness.h b/src/binaryToObject/endianness.h index 0537fb8bfe..d1501a3926 100644 --- a/src/binaryToObject/endianness.h +++ b/src/binaryToObject/endianness.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index ef9cbe5f30..50d7e56d78 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index b7a35b90f4..d8f801a5e3 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index ddad7b3bb6..32f13cc4fa 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/binaryToObject/tools.cpp b/src/binaryToObject/tools.cpp index 4f8b8170d0..3181474b94 100644 --- a/src/binaryToObject/tools.cpp +++ b/src/binaryToObject/tools.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/binaryToObject/tools.h b/src/binaryToObject/tools.h index ad7e81f86f..c95d22ae89 100644 --- a/src/binaryToObject/tools.h +++ b/src/binaryToObject/tools.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, Avian Contributors +/* Copyright (c) 2009-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/boot-javahome.cpp b/src/boot-javahome.cpp index 4ef2efd896..bb965cdc3a 100644 --- a/src/boot-javahome.cpp +++ b/src/boot-javahome.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Avian Contributors +/* Copyright (c) 2010-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/boot.cpp b/src/boot.cpp index c78667f5af..4f3d8edbb0 100644 --- a/src/boot.cpp +++ b/src/boot.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 01e9e88959..17a27f198d 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/bootimage.h b/src/bootimage.h index a7e178524a..16f11ab379 100644 --- a/src/bootimage.h +++ b/src/bootimage.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/builtin.cpp b/src/builtin.cpp index e5cd6bfe07..9c3dca8508 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 5df85fa6b6..5e68d2ed14 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, Avian Contributors +/* Copyright (c) 2010-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/classpath-common.h b/src/classpath-common.h index 5f769ae00f..d8105b9cd7 100644 --- a/src/classpath-common.h +++ b/src/classpath-common.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, Avian Contributors +/* Copyright (c) 2010-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 721889e452..fe9dbfdbfb 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, Avian Contributors +/* Copyright (c) 2010-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/common.h b/src/common.h index 8c762f6c70..009b90226e 100644 --- a/src/common.h +++ b/src/common.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/compile-arm.S b/src/compile-arm.S index 0f69903934..8ce5cc3684 100644 --- a/src/compile-arm.S +++ b/src/compile-arm.S @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, Avian Contributors +/* Copyright (c) 2010-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/compile.cpp b/src/compile.cpp index fd3f3520e7..5e54cd8616 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/compiler.cpp b/src/compiler.cpp index 9fd3fc5e28..56a2709e42 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/compiler.h b/src/compiler.h index acac85b436..e66c69a67c 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/environment.h b/src/environment.h index 53a309057e..045eb2642d 100644 --- a/src/environment.h +++ b/src/environment.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/finder.cpp b/src/finder.cpp index 6d9136a991..1a08e65008 100644 --- a/src/finder.cpp +++ b/src/finder.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/finder.h b/src/finder.h index e784fe6e9a..f4582417fa 100644 --- a/src/finder.h +++ b/src/finder.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/heap.h b/src/heap.h index 838d88786c..875b4a5cbc 100644 --- a/src/heap.h +++ b/src/heap.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/interpret.cpp b/src/interpret.cpp index 439f4ca069..6a66c1778b 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/machine.cpp b/src/machine.cpp index 0fab1f3b1b..4df244d536 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/machine.h b/src/machine.h index eea9cc506b..05bc01b1e6 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/main.cpp b/src/main.cpp index f5358e985c..2518d60a13 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/openjdk/jni_md.h b/src/openjdk/jni_md.h index bf5614c995..86858429d3 100644 --- a/src/openjdk/jni_md.h +++ b/src/openjdk/jni_md.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Avian Contributors +/* Copyright (c) 2010-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/posix.cpp b/src/posix.cpp index 35d2d6b7b1..3d0f525013 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/powerpc.cpp b/src/powerpc.cpp index 6ec487ea88..a184c21f36 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2011, Avian Contributors +/* Copyright (c) 2009-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/powerpc.h b/src/powerpc.h index 9b877719d0..8ddc9fc73c 100644 --- a/src/powerpc.h +++ b/src/powerpc.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/process.h b/src/process.h index 45de6d975c..04fcf57c7d 100644 --- a/src/process.h +++ b/src/process.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2011, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/processor.h b/src/processor.h index a6b548387f..4af110401f 100644 --- a/src/processor.h +++ b/src/processor.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/system.h b/src/system.h index 897193d042..c36aefacd9 100644 --- a/src/system.h +++ b/src/system.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/util.cpp b/src/util.cpp index ce830efe2d..915913e6e1 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/windows.cpp b/src/windows.cpp index 37c9251726..f6b4f1e550 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/x86.cpp b/src/x86.cpp index d5b6f0269a..095a567c63 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/x86.h b/src/x86.h index 72cc891ac1..298cab6aaa 100644 --- a/src/x86.h +++ b/src/x86.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2011, Avian Contributors +/* Copyright (c) 2008-2012, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided diff --git a/src/zlib-custom.h b/src/zlib-custom.h index cf1119e1fe..ab00841eec 100644 --- a/src/zlib-custom.h +++ b/src/zlib-custom.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2009, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided From 2d201732240aecf24bed8d1deaf38a4a3bf5483d Mon Sep 17 00:00:00 2001 From: JET Date: Thu, 17 May 2012 18:39:40 -0600 Subject: [PATCH 101/140] added immediate to bkpt instruction --- src/arm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arm.cpp b/src/arm.cpp index 14baab01e2..885a320594 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -1931,7 +1931,7 @@ return_(Context* c) void trap(Context* c) { - emit(c, bkpt()); + emit(c, bkpt(0)); } void From 7bd3ea1892e59caab72d923307b2c71c6bb3363d Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Tue, 22 May 2012 13:53:32 -0600 Subject: [PATCH 102/140] add simple disassembler for debugging --- src/machine.cpp | 442 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 439 insertions(+), 3 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index 4df244d536..fd4fed94c4 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -20,6 +20,8 @@ using namespace vm; namespace { +const bool DebugClassReader = false; + const unsigned NoByte = 0xFFFF; #ifdef USE_ATOMIC_OPERATIONS @@ -813,13 +815,22 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) switch (s.read1()) { case CONSTANT_Integer: case CONSTANT_Float: { - singletonValue(t, pool, i) = s.read4(); + uint32_t v = s.read4(); + singletonValue(t, pool, i) = v; + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = int/float 0x%x\n", i, v); + } } return 1; case CONSTANT_Long: case CONSTANT_Double: { uint64_t v = s.read8(); memcpy(&singletonValue(t, pool, i), &v, 8); + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = long/double \n", i); + } } return 2; case CONSTANT_Utf8: { @@ -829,6 +840,10 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) value = internByteArray(t, value); } set(t, pool, SingletonBody + (i * BytesPerWord), value); + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = utf8 %s\n", i, &byteArrayBody(t, value, 0)); + } } } return 1; @@ -839,6 +854,10 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) object value = makeReference(t, 0, singletonObject(t, pool, si), 0); set(t, pool, SingletonBody + (i * BytesPerWord), value); + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = class \n", i); + } } } return 1; @@ -852,6 +871,10 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) (t, value, 0, cast(value, BytesPerWord) - 1); value = intern(t, value); set(t, pool, SingletonBody + (i * BytesPerWord), value); + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = string \n", i); + } } } return 1; @@ -867,6 +890,10 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) object type = singletonObject(t, pool, ti); object value = makePair(t, name, type); set(t, pool, SingletonBody + (i * BytesPerWord), value); + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = nameAndType %s%s\n", i, &byteArrayBody(t, name, 0), &byteArrayBody(t, type, 0)); + } } } return 1; @@ -886,6 +913,10 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) object value = makeReference (t, class_, pairFirst(t, nameAndType), pairSecond(t, nameAndType)); set(t, pool, SingletonBody + (i * BytesPerWord), value); + + if(DebugClassReader) { + fprintf(stderr, " consts[%d] = method %s.%s%s\n", i, &byteArrayBody(t, class_, 0), &byteArrayBody(t, pairFirst(t, nameAndType), 0), &byteArrayBody(t, pairSecond(t, nameAndType), 0)); + } } } return 1; @@ -900,6 +931,10 @@ parsePool(Thread* t, Stream& s) object pool = makeSingletonOfSize(t, count + poolMaskSize(count)); PROTECT(t, pool); + if(DebugClassReader) { + fprintf(stderr, " const pool entries %d\n", count); + } + if (count) { uint32_t* index = static_cast(t->m->heap->allocate(count * 4)); @@ -1299,6 +1334,381 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) } } +uint16_t read16(uint8_t* code, unsigned& ip) { + uint16_t a = code[ip++]; + uint16_t b = code[ip++]; + return (a << 8) | b; +} + +uint32_t read32(uint8_t* code, unsigned& ip) { + uint32_t b = code[ip++]; + uint32_t a = code[ip++]; + uint32_t c = code[ip++]; + uint32_t d = code[ip++]; + return (a << 24) | (b << 16) | (c << 8) | d; +} + +void +disassembleCode(const char* prefix, uint8_t* code, unsigned length) +{ + unsigned ip = 0; + + while(ip < length) { + unsigned instr; + fprintf(stderr, "%s%x:\t", prefix, ip); + switch (instr = code[ip++]) { + case aaload: fprintf(stderr, "aaload\n"); break; + case aastore: fprintf(stderr, "aastore\n"); break; + + case aconst_null: fprintf(stderr, "aconst_null\n"); break; + + case aload: fprintf(stderr, "aload %02x\n", code[ip++]); break; + case aload_0: fprintf(stderr, "aload_0\n"); break; + case aload_1: fprintf(stderr, "aload_1\n"); break; + case aload_2: fprintf(stderr, "aload_2\n"); break; + case aload_3: fprintf(stderr, "aload_3\n"); break; + + case anewarray: fprintf(stderr, "anewarray %04x\n", read16(code, ip)); break; + case areturn: fprintf(stderr, "areturn\n"); break; + case arraylength: fprintf(stderr, "arraylength\n"); break; + + case astore: fprintf(stderr, "astore %02x\n", code[ip++]); break; + case astore_0: fprintf(stderr, "astore_0\n"); break; + case astore_1: fprintf(stderr, "astore_1\n"); break; + case astore_2: fprintf(stderr, "astore_2\n"); break; + case astore_3: fprintf(stderr, "astore_3\n"); break; + + + case athrow: fprintf(stderr, "athrow\n"); break; + case baload: fprintf(stderr, "baload\n"); break; + case bastore: fprintf(stderr, "bastore\n"); break; + + case bipush: fprintf(stderr, "bipush %02x\n", code[ip++]); break; + case caload: fprintf(stderr, "caload\n"); break; + case castore: fprintf(stderr, "castore\n"); break; + case checkcast: fprintf(stderr, "checkcast %04x\n", read16(code, ip)); break; + case d2f: fprintf(stderr, "d2f\n"); break; + case d2i: fprintf(stderr, "d2i\n"); break; + case d2l: fprintf(stderr, "d2l\n"); break; + case dadd: fprintf(stderr, "dadd\n"); break; + case daload: fprintf(stderr, "daload\n"); break; + case dastore: fprintf(stderr, "dastore\n"); break; + case dcmpg: fprintf(stderr, "dcmpg\n"); break; + case dcmpl: fprintf(stderr, "dcmpl\n"); break; + case dconst_0: fprintf(stderr, "dconst_0\n"); break; + case dconst_1: fprintf(stderr, "dconst_1\n"); break; + case ddiv: fprintf(stderr, "ddiv\n"); break; + case dmul: fprintf(stderr, "dmul\n"); break; + case dneg: fprintf(stderr, "dneg\n"); break; + case vm::drem: fprintf(stderr, "drem\n"); break; + case dsub: fprintf(stderr, "dsub\n"); break; + case dup: fprintf(stderr, "dup\n"); break; + case dup_x1: fprintf(stderr, "dup_x1\n"); break; + case dup_x2: fprintf(stderr, "dup_x2\n"); break; + case dup2: fprintf(stderr, "dup2\n"); break; + case dup2_x1: fprintf(stderr, "dup2_x1\n"); break; + case dup2_x2: fprintf(stderr, "dup2_x2\n"); break; + case f2d: fprintf(stderr, "f2d\n"); break; + case f2i: fprintf(stderr, "f2i\n"); break; + case f2l: fprintf(stderr, "f2l\n"); break; + case fadd: fprintf(stderr, "fadd\n"); break; + case faload: fprintf(stderr, "faload\n"); break; + case fastore: fprintf(stderr, "fastore\n"); break; + case fcmpg: fprintf(stderr, "fcmpg\n"); break; + case fcmpl: fprintf(stderr, "fcmpl\n"); break; + case fconst_0: fprintf(stderr, "fconst_0\n"); break; + case fconst_1: fprintf(stderr, "fconst_1\n"); break; + case fconst_2: fprintf(stderr, "fconst_2\n"); break; + case fdiv: fprintf(stderr, "fdiv\n"); break; + case fmul: fprintf(stderr, "fmul\n"); break; + case fneg: fprintf(stderr, "fneg\n"); break; + case frem: fprintf(stderr, "frem\n"); break; + case fsub: fprintf(stderr, "fsub\n"); break; + + case getfield: fprintf(stderr, "getfield %04x\n", read16(code, ip)); break; + case getstatic: fprintf(stderr, "getstatic %04x\n", read16(code, ip)); break; + case goto_: { + int16_t offset = read16(code, ip); + fprintf(stderr, "goto %04x\n", offset + ip - 3); + } break; + case goto_w: { + int32_t offset = read32(code, ip); + fprintf(stderr, "goto_w %08x\n", offset + ip - 5); + } break; + + case i2b: fprintf(stderr, "i2b\n"); break; + case i2c: fprintf(stderr, "i2c\n"); break; + case i2d: fprintf(stderr, "i2d\n"); break; + case i2f: fprintf(stderr, "i2f\n"); break; + case i2l: fprintf(stderr, "i2l\n"); break; + case i2s: fprintf(stderr, "i2s\n"); break; + case iadd: fprintf(stderr, "iadd\n"); break; + case iaload: fprintf(stderr, "iaload\n"); break; + case iand: fprintf(stderr, "iand\n"); break; + case iastore: fprintf(stderr, "iastore\n"); break; + case iconst_m1: fprintf(stderr, "iconst_m1\n"); break; + case iconst_0: fprintf(stderr, "iconst_0\n"); break; + case iconst_1: fprintf(stderr, "iconst_1\n"); break; + case iconst_2: fprintf(stderr, "iconst_2\n"); break; + case iconst_3: fprintf(stderr, "iconst_3\n"); break; + case iconst_4: fprintf(stderr, "iconst_4\n"); break; + case iconst_5: fprintf(stderr, "iconst_5\n"); break; + case idiv: fprintf(stderr, "idiv\n"); break; + + case if_acmpeq: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_acmpeq %04x\n", offset + ip - 3); + } break; + case if_acmpne: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_acmpne %04x\n", offset + ip - 3); + } break; + case if_icmpeq: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmpeq %04x\n", offset + ip - 3); + } break; + case if_icmpne: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmpne %04x\n", offset + ip - 3); + } break; + + case if_icmpgt: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmpgt %04x\n", offset + ip - 3); + } break; + case if_icmpge: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmpge %04x\n", offset + ip - 3); + } break; + case if_icmplt: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmplt %04x\n", offset + ip - 3); + } break; + case if_icmple: { + int16_t offset = read16(code, ip); + fprintf(stderr, "if_icmple %04x\n", offset + ip - 3); + } break; + + case ifeq: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifeq %04x\n", offset + ip - 3); + } break; + case ifne: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifne %04x\n", offset + ip - 3); + } break; + case ifgt: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifgt %04x\n", offset + ip - 3); + } break; + case ifge: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifge %04x\n", offset + ip - 3); + } break; + case iflt: { + int16_t offset = read16(code, ip); + fprintf(stderr, "iflt %04x\n", offset + ip - 3); + } break; + case ifle: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifle %04x\n", offset + ip - 3); + } break; + + case ifnonnull: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifnonnull %04x\n", offset + ip - 3); + } break; + case ifnull: { + int16_t offset = read16(code, ip); + fprintf(stderr, "ifnull %04x\n", offset + ip - 3); + } break; + + case iinc: { + uint8_t a = code[ip++]; + uint8_t b = code[ip++]; + fprintf(stderr, "iinc %02x %02x\n", a, b); + } break; + + case iload: fprintf(stderr, "iload %02x\n", code[ip++]); break; + case fload: fprintf(stderr, "fload %02x\n", code[ip++]); break; + + case iload_0: fprintf(stderr, "iload_0\n"); break; + case fload_0: fprintf(stderr, "fload_0\n"); break; + case iload_1: fprintf(stderr, "iload_1\n"); break; + case fload_1: fprintf(stderr, "fload_1\n"); break; + + case iload_2: fprintf(stderr, "iload_2\n"); break; + case fload_2: fprintf(stderr, "fload_2\n"); break; + case iload_3: fprintf(stderr, "iload_3\n"); break; + case fload_3: fprintf(stderr, "fload_3\n"); break; + + case imul: fprintf(stderr, "imul\n"); break; + case ineg: fprintf(stderr, "ineg\n"); break; + + case instanceof: fprintf(stderr, "instanceof %04x\n", read16(code, ip)); break; + case invokeinterface: fprintf(stderr, "invokeinterface %04x\n", read16(code, ip)); break; + case invokespecial: fprintf(stderr, "invokespecial %04x\n", read16(code, ip)); break; + case invokestatic: fprintf(stderr, "invokestatic %04x\n", read16(code, ip)); break; + case invokevirtual: fprintf(stderr, "invokevirtual %04x\n", read16(code, ip)); break; + + case ior: fprintf(stderr, "ior\n"); break; + case irem: fprintf(stderr, "irem\n"); break; + case ireturn: fprintf(stderr, "ireturn\n"); break; + case freturn: fprintf(stderr, "freturn\n"); break; + case ishl: fprintf(stderr, "ishl\n"); break; + case ishr: fprintf(stderr, "ishr\n"); break; + + case istore: fprintf(stderr, "istore %02x\n", code[ip++]); break; + case fstore: fprintf(stderr, "fstore %02x\n", code[ip++]); break; + + case istore_0: fprintf(stderr, "istore_0\n"); break; + case fstore_0: fprintf(stderr, "fstore_0\n"); break; + case istore_1: fprintf(stderr, "istore_1\n"); break; + case fstore_1: fprintf(stderr, "fstore_1\n"); break; + case istore_2: fprintf(stderr, "istore_2\n"); break; + case fstore_2: fprintf(stderr, "fstore_2\n"); break; + case istore_3: fprintf(stderr, "istore_3\n"); break; + case fstore_3: fprintf(stderr, "fstore_3\n"); break; + + case isub: fprintf(stderr, "isub\n"); break; + case iushr: fprintf(stderr, "iushr\n"); break; + case ixor: fprintf(stderr, "ixor\n"); break; + + case jsr: fprintf(stderr, "jsr %04x\n", read16(code, ip)); break; + case jsr_w: fprintf(stderr, "jsr_w %08x\n", read32(code, ip)); break; + + case l2d: fprintf(stderr, "l2d\n"); break; + case l2f: fprintf(stderr, "l2f\n"); break; + case l2i: fprintf(stderr, "l2i\n"); break; + case ladd: fprintf(stderr, "ladd\n"); break; + case laload: fprintf(stderr, "laload\n"); break; + + case land: fprintf(stderr, "land\n"); break; + case lastore: fprintf(stderr, "lastore\n"); break; + + case lcmp: fprintf(stderr, "lcmp\n"); break; + case lconst_0: fprintf(stderr, "lconst_0\n"); break; + case lconst_1: fprintf(stderr, "lconst_1\n"); break; + + case ldc: fprintf(stderr, "ldc %04x\n", read16(code, ip)); break; + case ldc_w: fprintf(stderr, "ldc_w %08x\n", read32(code, ip)); break; + case ldc2_w: fprintf(stderr, "ldc2_w %04x\n", read16(code, ip)); break; + + case ldiv_: fprintf(stderr, "ldiv_\n"); break; + + case lload: fprintf(stderr, "lload %02x\n", code[ip++]); break; + case dload: fprintf(stderr, "dload %02x\n", code[ip++]); break; + + case lload_0: fprintf(stderr, "lload_0\n"); break; + case dload_0: fprintf(stderr, "dload_0\n"); break; + case lload_1: fprintf(stderr, "lload_1\n"); break; + case dload_1: fprintf(stderr, "dload_1\n"); break; + case lload_2: fprintf(stderr, "lload_2\n"); break; + case dload_2: fprintf(stderr, "dload_2\n"); break; + case lload_3: fprintf(stderr, "lload_3\n"); break; + case dload_3: fprintf(stderr, "dload_3\n"); break; + + case lmul: fprintf(stderr, "lmul\n"); break; + case lneg: fprintf(stderr, "lneg\n"); break; + + case lookupswitch: { + int32_t default_ = read32(code, ip); + int32_t pairCount = read32(code, ip); + fprintf(stderr, "lookupswitch default: %d pairCount: %d\n", default_, pairCount); + + for (int i = 0; i < pairCount; i++) { + int32_t k = read32(code, ip); + int32_t d = read32(code, ip); + fprintf(stderr, "%s key: %02x dest: %2x\n", prefix, k, d); + } + } break; + + case lor: fprintf(stderr, "lor\n"); break; + case lrem: fprintf(stderr, "lrem\n"); break; + case lreturn: fprintf(stderr, "lreturn\n"); break; + case dreturn: fprintf(stderr, "dreturn\n"); break; + case lshl: fprintf(stderr, "lshl\n"); break; + case lshr: fprintf(stderr, "lshr\n"); break; + + case lstore: fprintf(stderr, "lstore %02x\n", code[ip++]); break; + case dstore: fprintf(stderr, "dstore %02x\n", code[ip++]); break; + + case lstore_0: fprintf(stderr, "lstore_0\n"); break; + case dstore_0: fprintf(stderr, "dstore_0\n"); break; + case lstore_1: fprintf(stderr, "lstore_1\n"); break; + case dstore_1: fprintf(stderr, "dstore_1\n"); break; + case lstore_2: fprintf(stderr, "lstore_2\n"); break; + case dstore_2: fprintf(stderr, "dstore_2\n"); break; + case lstore_3: fprintf(stderr, "lstore_3\n"); break; + case dstore_3: fprintf(stderr, "dstore_3\n"); break; + + case lsub: fprintf(stderr, "lsub\n"); break; + case lushr: fprintf(stderr, "lushr\n"); break; + case lxor: fprintf(stderr, "lxor\n"); break; + + case monitorenter: fprintf(stderr, "monitorenter\n"); break; + case monitorexit: fprintf(stderr, "monitorexit\n"); break; + + case multianewarray: fprintf(stderr, "multianewarray %04x %02x\n", read16(code, ip), code[ip++]); break; + + case new_: fprintf(stderr, "new %04x\n", read16(code, ip)); break; + + case newarray: fprintf(stderr, "newarray %02x\n", code[ip++]); break; + + case nop: fprintf(stderr, "nop\n"); break; + case pop_: fprintf(stderr, "pop\n"); break; + case pop2: fprintf(stderr, "pop2\n"); break; + + case putfield: fprintf(stderr, "putfield %04x\n", read16(code, ip)); break; + case putstatic: fprintf(stderr, "putstatic %04x\n", read16(code, ip)); break; + + case ret: fprintf(stderr, "ret %02x\n", code[ip++]); break; + + case return_: fprintf(stderr, "return_\n"); break; + case saload: fprintf(stderr, "saload\n"); break; + case sastore: fprintf(stderr, "sastore\n"); break; + + case sipush: fprintf(stderr, "sipush %04x\n", read16(code, ip)); break; + + case swap: fprintf(stderr, "swap\n"); break; + + case tableswitch: { + int32_t default_ = read32(code, ip); + int32_t bottom = read32(code, ip); + int32_t top = read32(code, ip); + fprintf(stderr, "tableswitch default: %d bottom: %d top: %d\n", default_, bottom, top); + + for (int i = 0; i < top - bottom + 1; i++) { + int32_t d = read32(code, ip); + fprintf(stderr, "%s key: %d dest: %2x\n", prefix, i + bottom, d); + } + } break; + + case wide: { + switch (code[ip++]) { + case aload: fprintf(stderr, "wide aload %04x\n", read16(code, ip)); break; + + case astore: fprintf(stderr, "wide astore %04x\n", read16(code, ip)); break; + case iinc: fprintf(stderr, "wide iinc %04x %04x\n", read16(code, ip), read16(code, ip)); break; + case iload: fprintf(stderr, "wide iload %04x\n", read16(code, ip)); break; + case istore: fprintf(stderr, "wide istore %04x\n", read16(code, ip)); break; + case lload: fprintf(stderr, "wide lload %04x\n", read16(code, ip)); break; + case lstore: fprintf(stderr, "wide lstore %04x\n", read16(code, ip)); break; + case ret: fprintf(stderr, "wide ret %04x\n", read16(code, ip)); break; + + default: { + fprintf(stderr, "unknown wide instruction %02x %04x\n", instr, read16(code, ip)); + } + } + } break; + + default: { + fprintf(stderr, "unknown instruction %02x\n", instr); + } + } + } +} + object parseCode(Thread* t, Stream& s, object pool) { @@ -1308,10 +1718,18 @@ parseCode(Thread* t, Stream& s, object pool) unsigned maxLocals = s.read2(); unsigned length = s.read4(); + if(DebugClassReader) { + fprintf(stderr, " code: maxStack %d maxLocals %d length %d\n", maxStack, maxLocals, length); + } + object code = makeCode(t, pool, 0, 0, 0, 0, maxStack, maxLocals, length); s.read(&codeBody(t, code, 0), length); PROTECT(t, code); + if(DebugClassReader) { + disassembleCode(" ", &codeBody(t, code, 0), length); + } + unsigned ehtLength = s.read2(); if (ehtLength) { object eht = makeExceptionHandlerTable(t, ehtLength); @@ -1450,6 +1868,11 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) PROTECT(t, newVirtuals); unsigned count = s.read2(); + + if(DebugClassReader) { + fprintf(stderr, " method count %d\n", count); + } + if (count) { object methodTable = makeArray(t, count); PROTECT(t, methodTable); @@ -1465,6 +1888,12 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool) unsigned name = s.read2(); unsigned spec = s.read2(); + if(DebugClassReader) { + fprintf(stderr, " method flags %d name %d spec %d '%s%s'\n", flags, name, spec, + &byteArrayBody(t, singletonObject(t, pool, name - 1), 0), + &byteArrayBody(t, singletonObject(t, pool, spec - 1), 0)); + } + addendum = 0; code = 0; @@ -3423,8 +3852,11 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size, uint32_t magic = s.read4(); expect(t, magic == 0xCAFEBABE); - s.read2(); // minor version - s.read2(); // major version + unsigned minorVer = s.read2(); // minor version + unsigned majorVer = s.read2(); // major version + if(DebugClassReader) { + fprintf(stderr, "read class (minor %d major %d)\n", minorVer, majorVer); + } object pool = parsePool(t, s); PROTECT(t, pool); @@ -3468,6 +3900,10 @@ parseClass(Thread* t, object loader, const uint8_t* data, unsigned size, & (ReferenceFlag | WeakReferenceFlag | HasFinalizerFlag | NeedInitFlag)); } + + if(DebugClassReader) { + fprintf(stderr, " flags %d name %d super %d\n", flags, name, super); + } parseInterfaceTable(t, s, class_, pool, throwType); From a5c9dd6f248c6e3254b562b0830a7bcead429eea Mon Sep 17 00:00:00 2001 From: Mike Keesey Date: Tue, 22 May 2012 14:00:31 -0600 Subject: [PATCH 103/140] Fixing some issues with runtime annotations within avian. We were not properly converting dots to slashes internally for package names and we did not properly handle Method.getAnnotations and Method.getAnnotation(Class) on methods without any annotations. Added some tests to cover these cases. --- classpath/avian/VMMethod.java | 4 +++ classpath/java/lang/reflect/Method.java | 4 +-- classpath/java/lang/reflect/Proxy.java | 2 +- makefile | 5 ++- test/Annotations.java | 35 ++++++++----------- test/avian/testing/annotations/Color.java | 5 +++ test/avian/testing/annotations/Test.java | 9 +++++ test/avian/testing/annotations/TestEnum.java | 8 +++++ .../testing/annotations/TestInteger.java | 8 +++++ 9 files changed, 55 insertions(+), 25 deletions(-) create mode 100644 test/avian/testing/annotations/Color.java create mode 100644 test/avian/testing/annotations/Test.java create mode 100644 test/avian/testing/annotations/TestEnum.java create mode 100644 test/avian/testing/annotations/TestInteger.java diff --git a/classpath/avian/VMMethod.java b/classpath/avian/VMMethod.java index e68d725242..843dd6012e 100644 --- a/classpath/avian/VMMethod.java +++ b/classpath/avian/VMMethod.java @@ -24,4 +24,8 @@ public class VMMethod { public MethodAddendum addendum; public VMClass class_; public Object code; + + public boolean hasAnnotations() { + return addendum != null && addendum.annotationTable != null; + } } diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index 2c0addfaae..f90ed311a5 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -170,7 +170,7 @@ public class Method extends AccessibleObject implements Member { } public T getAnnotation(Class class_) { - if (vmMethod.addendum.annotationTable != null) { + if (vmMethod.hasAnnotations()) { Object[] table = (Object[]) vmMethod.addendum.annotationTable; for (int i = 0; i < table.length; ++i) { Object[] a = (Object[]) table[i]; @@ -183,7 +183,7 @@ public class Method extends AccessibleObject implements Member { } public Annotation[] getAnnotations() { - if (vmMethod.addendum.annotationTable != null) { + if (vmMethod.hasAnnotations()) { Object[] table = (Object[]) vmMethod.addendum.annotationTable; Annotation[] array = new Annotation[table.length]; for (int i = 0; i < table.length; ++i) { diff --git a/classpath/java/lang/reflect/Proxy.java b/classpath/java/lang/reflect/Proxy.java index 06805fc72c..cfc35a6077 100644 --- a/classpath/java/lang/reflect/Proxy.java +++ b/classpath/java/lang/reflect/Proxy.java @@ -358,7 +358,7 @@ public class Proxy { int[] interfaceIndexes = new int[interfaces.length]; for (int i = 0; i < interfaces.length; ++i) { interfaceIndexes[i] = ConstantPool.addClass - (pool, interfaces[i].getName()); + (pool, interfaces[i].getName().replace('.', '/')); } Map virtualMap = new HashMap(); diff --git a/makefile b/makefile index 86bc33e9b1..42ef1b95e7 100755 --- a/makefile +++ b/makefile @@ -685,7 +685,10 @@ vm-classes = \ avian/*.class \ avian/resource/*.class +test-support-sources = $(shell find $(test)/avian/ -name '*.java') test-sources = $(wildcard $(test)/*.java) +test-sources += $(test-support-sources) +test-support-classes = $(call java-classes, $(test-support-sources),$(test),$(test-build)) test-classes = $(call java-classes,$(test-sources),$(test),$(test-build)) test-dep = $(test-build).dep @@ -765,7 +768,7 @@ vg: build test: build $(library-path) /bin/sh $(test)/test.sh 2>/dev/null \ $(test-executable) $(mode) "$(test-flags)" \ - $(call class-names,$(test-build),$(test-classes)) \ + $(call class-names,$(test-build),$(filter-out $(test-support-classes), $(test-classes))) \ $(continuation-tests) $(tail-tests) .PHONY: tarball diff --git a/test/Annotations.java b/test/Annotations.java index 17929065d1..c0234d21c0 100644 --- a/test/Annotations.java +++ b/test/Annotations.java @@ -1,7 +1,10 @@ -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; +import avian.testing.annotations.Color; +import avian.testing.annotations.Test; +import avian.testing.annotations.TestEnum; +import avian.testing.annotations.TestInteger; + public class Annotations { private static void expect(boolean v) { if (! v) throw new RuntimeException(); @@ -18,6 +21,12 @@ public class Annotations { .equals(Color.Red)); expect(((TestInteger) m.getAnnotation(TestInteger.class)).value() == 42); + + expect(m.getAnnotations().length == 3); + + Method noAnno = Annotations.class.getMethod("noAnnotation"); + expect(noAnno.getAnnotation(Test.class) == null); + expect(noAnno.getAnnotations().length == 0); } @Test("couscous") @@ -26,24 +35,8 @@ public class Annotations { public static void foo() { } - - @Retention(RetentionPolicy.RUNTIME) - private @interface Test { - public String value(); + + public static void noAnnotation() { + } - - @Retention(RetentionPolicy.RUNTIME) - private @interface TestEnum { - public Color value(); - } - - @Retention(RetentionPolicy.RUNTIME) - private @interface TestInteger { - public int value(); - } - - private static enum Color { - Red, Yellow, Blue - } - } diff --git a/test/avian/testing/annotations/Color.java b/test/avian/testing/annotations/Color.java new file mode 100644 index 0000000000..f054b0420a --- /dev/null +++ b/test/avian/testing/annotations/Color.java @@ -0,0 +1,5 @@ +package avian.testing.annotations; + +public enum Color { + Red, Yellow, Blue +} \ No newline at end of file diff --git a/test/avian/testing/annotations/Test.java b/test/avian/testing/annotations/Test.java new file mode 100644 index 0000000000..f9ba919647 --- /dev/null +++ b/test/avian/testing/annotations/Test.java @@ -0,0 +1,9 @@ +package avian.testing.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface Test { + public String value(); +} diff --git a/test/avian/testing/annotations/TestEnum.java b/test/avian/testing/annotations/TestEnum.java new file mode 100644 index 0000000000..f8a252fd54 --- /dev/null +++ b/test/avian/testing/annotations/TestEnum.java @@ -0,0 +1,8 @@ +package avian.testing.annotations; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface TestEnum { + public Color value(); +} \ No newline at end of file diff --git a/test/avian/testing/annotations/TestInteger.java b/test/avian/testing/annotations/TestInteger.java new file mode 100644 index 0000000000..b7ec78d0bc --- /dev/null +++ b/test/avian/testing/annotations/TestInteger.java @@ -0,0 +1,8 @@ +package avian.testing.annotations; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface TestInteger { + public int value(); +} \ No newline at end of file From be869932d085db74bfa6829364a2c7eb94d26fac Mon Sep 17 00:00:00 2001 From: Mike Keesey Date: Tue, 22 May 2012 15:18:42 -0600 Subject: [PATCH 104/140] Adding @Target and the associated ElementType enum for specifying the type an annotation is. --- .../java/lang/annotation/ElementType.java | 22 +++++++++++++++++++ classpath/java/lang/annotation/Target.java | 17 ++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 classpath/java/lang/annotation/ElementType.java create mode 100644 classpath/java/lang/annotation/Target.java diff --git a/classpath/java/lang/annotation/ElementType.java b/classpath/java/lang/annotation/ElementType.java new file mode 100644 index 0000000000..974fb10d64 --- /dev/null +++ b/classpath/java/lang/annotation/ElementType.java @@ -0,0 +1,22 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.annotation; + +public enum ElementType { + ANNOTATION_TYPE, + CONSTRUCTOR, + FIELD, + LOCAL_VARIABLE, + METHOD, + PACKAGE, + PARAMETER, + TYPE +} diff --git a/classpath/java/lang/annotation/Target.java b/classpath/java/lang/annotation/Target.java new file mode 100644 index 0000000000..8d2550343c --- /dev/null +++ b/classpath/java/lang/annotation/Target.java @@ -0,0 +1,17 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.lang.annotation; + +@Retention(value=RetentionPolicy.RUNTIME) +@Target(value=ElementType.ANNOTATION_TYPE) +public @interface Target { + public ElementType[] value(); +} From 97ffc5b15eeba27e0b80c1ef21031259f10ad364 Mon Sep 17 00:00:00 2001 From: Mike Keesey Date: Tue, 22 May 2012 15:23:28 -0600 Subject: [PATCH 105/140] Adding java.util.Queue interface and java.util.AbstractQueue. --- classpath/java/util/AbstractQueue.java | 60 ++++++++++++++++++++++++++ classpath/java/util/Queue.java | 20 +++++++++ 2 files changed, 80 insertions(+) create mode 100644 classpath/java/util/AbstractQueue.java create mode 100644 classpath/java/util/Queue.java diff --git a/classpath/java/util/AbstractQueue.java b/classpath/java/util/AbstractQueue.java new file mode 100644 index 0000000000..19fa46aaa1 --- /dev/null +++ b/classpath/java/util/AbstractQueue.java @@ -0,0 +1,60 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public abstract class AbstractQueue extends AbstractCollection implements Queue { + + protected AbstractQueue() { + super(); + } + + public boolean add(T element) { + if (offer(element)) { + return true; + } else { + throw new IllegalStateException(); + } + } + + public boolean addAll(Collection collection) { + if (collection == null) { + throw new NullPointerException(); + } + + for (T element : collection) { + add(element); + } + + return true; + } + + public void clear() { + while (size() > 0) { + poll(); + } + } + + public T element() { + emptyCheck(); + return peek(); + } + + public T remove() { + emptyCheck(); + return poll(); + } + + private void emptyCheck() { + if (size() == 0) { + throw new NoSuchElementException(); + } + } +} diff --git a/classpath/java/util/Queue.java b/classpath/java/util/Queue.java new file mode 100644 index 0000000000..27855a7f61 --- /dev/null +++ b/classpath/java/util/Queue.java @@ -0,0 +1,20 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface Queue extends Collection, Iterable { + public boolean add(T element); + public T element(); + public boolean offer(T element); + public T peek(); + public T poll(); + public T remove(); +} From 1f7b1a74e8532e2aa7cccccc1e9ad5faa3222473 Mon Sep 17 00:00:00 2001 From: Mike Keesey Date: Tue, 22 May 2012 16:21:57 -0600 Subject: [PATCH 106/140] Adding java.util.SortedSet. --- classpath/java/util/SortedSet.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 classpath/java/util/SortedSet.java diff --git a/classpath/java/util/SortedSet.java b/classpath/java/util/SortedSet.java new file mode 100644 index 0000000000..1e1b2b923e --- /dev/null +++ b/classpath/java/util/SortedSet.java @@ -0,0 +1,20 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public interface SortedSet extends Collection, Iterable, Set { + public Comparator comparator(); + public T first(); + public SortedSet headSet(T toElement); + public T last(); + public SortedSet subSet(T fromElement, T toElement); + public SortedSet tailSet(T fromElement); +} From 20ee6604557c940dd155598e7225e5008ea2b544 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 22 May 2012 17:45:13 -0600 Subject: [PATCH 107/140] preserve classes needed for Unix filesystem access from ProGuard It seems that there are new classes loaded via reflection or JNI in OpenJDK needed for filesystem access, so we must tell ProGuard to retain them. --- openjdk.pro | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/openjdk.pro b/openjdk.pro index 953b5e205b..5a60ba1260 100644 --- a/openjdk.pro +++ b/openjdk.pro @@ -223,3 +223,21 @@ -keep class sun.util.resources.TimeZoneNames -keep class sun.text.resources.FormatData +# loaded via reflection from DefaultFileSystemProvider: +-keep class sun.nio.fs.LinuxFileSystemProvider +-keep class sun.nio.fs.BsdFileSystemProvider + +# loaded via JNI in UnixNativeDispatcher.c: +-keep class sun.nio.fs.UnixFileAttributes { + ; +} +-keep class sun.nio.fs.UnixFileStoreAttributes { + ; +} +-keep class sun.nio.fs.UnixMountEntry { + ; +} + +-keep class sun.nio.fs.UnixException { + UnixException(int); + } From 5d6899a8674cb86d297db518189823a120a97e45 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 24 May 2012 08:34:46 -0600 Subject: [PATCH 108/140] fix warning in disassembler code Apple's GCC is more picky about undefined ordering (and rightfully so)... --- src/machine.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/machine.cpp b/src/machine.cpp index fd4fed94c4..4c99de36de 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1649,7 +1649,10 @@ disassembleCode(const char* prefix, uint8_t* code, unsigned length) case monitorenter: fprintf(stderr, "monitorenter\n"); break; case monitorexit: fprintf(stderr, "monitorexit\n"); break; - case multianewarray: fprintf(stderr, "multianewarray %04x %02x\n", read16(code, ip), code[ip++]); break; + case multianewarray: { + unsigned type = read16(code, ip); + fprintf(stderr, "multianewarray %04x %02x\n", type, code[ip++]); + } break; case new_: fprintf(stderr, "new %04x\n", read16(code, ip)); break; From b78c772ffbb19e95a46d8150dc9f69656c9d5fa2 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 1 Jun 2012 11:46:56 -0600 Subject: [PATCH 109/140] fix C++11 narrowing conversion errors --- classpath/java-util-zip.cpp | 8 ++++++-- src/jnienv.cpp | 37 +++++++++++++++++++------------------ src/posix.cpp | 3 ++- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/classpath/java-util-zip.cpp b/classpath/java-util-zip.cpp index 9ae2833332..6fb471bdfd 100644 --- a/classpath/java-util-zip.cpp +++ b/classpath/java-util-zip.cpp @@ -76,7 +76,9 @@ Java_java_util_zip_Inflater_inflate int r = inflate(s, Z_SYNC_FLUSH); jint resultArray[3] - = { r, inputLength - s->avail_in, outputLength - s->avail_out }; + = { r, + static_cast(inputLength - s->avail_in), + static_cast(outputLength - s->avail_out) }; free(in); @@ -147,7 +149,9 @@ Java_java_util_zip_Deflater_deflate int r = deflate(s, finish ? Z_FINISH : Z_NO_FLUSH); jint resultArray[3] - = { r, inputLength - s->avail_in, outputLength - s->avail_out }; + = { r, + static_cast(inputLength - s->avail_in), + static_cast(outputLength - s->avail_out) }; free(in); diff --git a/src/jnienv.cpp b/src/jnienv.cpp index ffc0937789..1631d0f3bb 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -252,7 +252,8 @@ NewString(Thread* t, const jchar* chars, jsize size) { if (chars == 0) return 0; - uintptr_t arguments[] = { reinterpret_cast(chars), size }; + uintptr_t arguments[] = { reinterpret_cast(chars), + static_cast(size) }; return reinterpret_cast(run(t, newString, arguments)); } @@ -311,7 +312,7 @@ DefineClass(Thread* t, const char*, jobject loader, const jbyte* buffer, { uintptr_t arguments[] = { reinterpret_cast(loader), reinterpret_cast(buffer), - length }; + static_cast(length) }; return reinterpret_cast(run(t, defineClass, arguments)); } @@ -1495,7 +1496,7 @@ SetByteField(Thread* t, jobject o, jfieldID field, jbyte v) { uintptr_t arguments[] = { reinterpret_cast(o), field, - v }; + static_cast(v) }; run(t, setByteField, arguments); } @@ -1545,7 +1546,7 @@ SetShortField(Thread* t, jobject o, jfieldID field, jshort v) { uintptr_t arguments[] = { reinterpret_cast(o), field, - v }; + static_cast(v) }; run(t, setShortField, arguments); } @@ -1570,7 +1571,7 @@ SetIntField(Thread* t, jobject o, jfieldID field, jint v) { uintptr_t arguments[] = { reinterpret_cast(o), field, - v }; + static_cast(v) }; run(t, setIntField, arguments); } @@ -1975,7 +1976,7 @@ SetStaticByteField(Thread* t, jobject c, jfieldID field, jbyte v) { uintptr_t arguments[] = { reinterpret_cast(c), field, - v }; + static_cast(v) }; run(t, setStaticByteField, arguments); } @@ -2033,7 +2034,7 @@ SetStaticShortField(Thread* t, jobject c, jfieldID field, jshort v) { uintptr_t arguments[] = { reinterpret_cast(c), field, - v }; + static_cast(v) }; run(t, setStaticShortField, arguments); } @@ -2062,7 +2063,7 @@ SetStaticIntField(Thread* t, jobject c, jfieldID field, jint v) { uintptr_t arguments[] = { reinterpret_cast(c), field, - v }; + static_cast(v) }; run(t, setStaticIntField, arguments); } @@ -2261,7 +2262,7 @@ newObjectArray(Thread* t, uintptr_t* arguments) jobjectArray JNICALL NewObjectArray(Thread* t, jsize length, jclass class_, jobject init) { - uintptr_t arguments[] = { length, + uintptr_t arguments[] = { static_cast(length), reinterpret_cast(class_), reinterpret_cast(init) }; @@ -2302,7 +2303,7 @@ NewBooleanArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeBooleanArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2318,7 +2319,7 @@ NewByteArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeByteArray0)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2328,7 +2329,7 @@ NewCharArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeCharArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2338,7 +2339,7 @@ NewShortArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeShortArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2348,7 +2349,7 @@ NewIntArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeIntArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2358,7 +2359,7 @@ NewLongArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeLongArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2368,7 +2369,7 @@ NewFloatArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeFloatArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2378,7 +2379,7 @@ NewDoubleArray(Thread* t, jsize length) { uintptr_t arguments[] = { reinterpret_cast(voidPointer(makeDoubleArray)), - length }; + static_cast(length) }; return reinterpret_cast(run(t, newArray, arguments)); } @@ -2905,7 +2906,7 @@ RegisterNatives(Thread* t, jclass c, const JNINativeMethod* methods, { uintptr_t arguments[] = { reinterpret_cast(c), reinterpret_cast(methods), - methodCount }; + static_cast(methodCount) }; return run(t, registerNatives, arguments) ? 0 : -1; } diff --git a/src/posix.cpp b/src/posix.cpp index 3d0f525013..ea3f133d37 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -340,7 +340,8 @@ class MySystem: public System { // milliseconds) is infinity so as to avoid overflow: if (time and time < INT64_C(31536000000000000)) { int64_t then = s->now() + time; - timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 }; + timespec ts = { static_cast(then / 1000), + static_cast((then % 1000) * 1000 * 1000) }; int rv UNUSED = pthread_cond_timedwait (&(t->condition), &(t->mutex), &ts); expect(s, rv == 0 or rv == ETIMEDOUT or rv == EINTR); From 879df617df4b7905684646113b43a787372c64ae Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 1 Jun 2012 17:43:42 -0600 Subject: [PATCH 110/140] add use-clang option for building with LLVM Clang instead of GCC This also fixes several errors and warnings emitted by Clang. --- classpath/jni-util.h | 5 --- makefile | 37 +++++++++++----- readme.txt | 7 ++++ src/binaryToObject/elf.cpp | 15 +++---- src/binaryToObject/mach-o.cpp | 14 ++++--- src/binaryToObject/main.cpp | 2 +- src/binaryToObject/pe.cpp | 12 +++--- src/bootimage.cpp | 69 +++++++++++++----------------- src/compile.cpp | 8 ---- src/compiler.cpp | 66 ++++------------------------- src/heap.cpp | 7 ---- src/heapwalk.cpp | 10 ----- src/machine.cpp | 30 ------------- src/type-generator.cpp | 79 ----------------------------------- src/x86.cpp | 40 ------------------ 15 files changed, 94 insertions(+), 307 deletions(-) diff --git a/classpath/jni-util.h b/classpath/jni-util.h index 4973891704..57e545a14b 100644 --- a/classpath/jni-util.h +++ b/classpath/jni-util.h @@ -73,8 +73,6 @@ typedef unsigned __int64 uint64_t; #endif // not _MSC_VER -namespace { - inline void throwNew(JNIEnv* e, const char* class_, const char* message, ...) { @@ -149,7 +147,4 @@ class RuntimeArray { #endif // not _MSC_VER - -} // namespace - #endif//JNI_UTIL diff --git a/makefile b/makefile index 42ef1b95e7..b528fc2fb3 100755 --- a/makefile +++ b/makefile @@ -138,8 +138,13 @@ endif input = List -build-cxx = g++ -build-cc = gcc +ifeq ($(use-clang),true) + build-cxx = clang + build-cc = clang +else + build-cxx = g++ + build-cc = gcc +endif mflag = ifneq ($(platform),darwin) @@ -195,7 +200,8 @@ build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \ converter-cflags = -D__STDC_CONSTANT_MACROS -Isrc/binaryToObject -Isrc/ \ -fno-rtti -fno-exceptions \ -DAVIAN_TARGET_ARCH=AVIAN_ARCH_UNKNOWN \ - -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_UNKNOWN + -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_UNKNOWN \ + -Wall -Wextra -Werror -Wunused-parameter -Winit-self cflags = $(build-cflags) @@ -446,23 +452,32 @@ ifeq ($(mode),stress-major) strip = : endif ifeq ($(mode),fast) - optimization-cflags = -O3 -g3 -DNDEBUG + optimization-cflags = -O4 -g3 -DNDEBUG use-lto = true endif ifeq ($(mode),small) - optimization-cflags = -Os -g3 -DNDEBUG + ifeq ($(use-clang),true) + optimization-cflags = -Oz -g3 -DNDEBUG + else + optimization-cflags = -Os -g3 -DNDEBUG + endif use-lto = true endif ifeq ($(use-lto),true) -# only try to use LTO when GCC 4.6.0 or greater is available - gcc-major := $(shell $(cc) -dumpversion | cut -f1 -d.) - gcc-minor := $(shell $(cc) -dumpversion | cut -f2 -d.) - ifeq ($(shell expr 4 \< $(gcc-major) \ - \| \( 4 \<= $(gcc-major) \& 6 \<= $(gcc-minor) \)),1) + ifeq ($(use-clang),true) optimization-cflags += -flto - no-lto = -fno-lto lflags += $(optimization-cflags) + else +# only try to use LTO when GCC 4.6.0 or greater is available + gcc-major := $(shell $(cc) -dumpversion | cut -f1 -d.) + gcc-minor := $(shell $(cc) -dumpversion | cut -f2 -d.) + ifeq ($(shell expr 4 \< $(gcc-major) \ + \| \( 4 \<= $(gcc-major) \& 6 \<= $(gcc-minor) \)),1) + optimization-cflags += -flto + no-lto = -fno-lto + lflags += $(optimization-cflags) + endif endif endif diff --git a/readme.txt b/readme.txt index 6c08030677..ac54ca700f 100644 --- a/readme.txt +++ b/readme.txt @@ -63,6 +63,7 @@ Build requirements include: * GNU make 3.80 or later * GCC 3.4 or later (4.5.1 or later for Windows/x86_64) + or LLVM Clang 3.1 or later (see use-clang option below) * JDK 1.5 or later * MinGW 3.4 or later (only if compiling for Windows) * zlib 1.2.3 or later @@ -83,6 +84,7 @@ certain flags described below, all of which are optional. heapdump={true,false} \ tails={true,false} \ continuations={true,false} \ + use-clang={true,false} \ openjdk= \ openjdk-src= @@ -134,6 +136,11 @@ certain flags described below, all of which are optional. only valid for process=compile builds. default: false + * use-clang - if true, use LLVM's clang instead of GCC to build. + Note that this does not currently affect cross compiles, only + native builds. + default: false + * openjdk - if set, use OpenJDK class library instead of the default Avian class library. See "Building with the OpenJDK Class Library" below for details. diff --git a/src/binaryToObject/elf.cpp b/src/binaryToObject/elf.cpp index caf7c9c545..b4e0025b02 100644 --- a/src/binaryToObject/elf.cpp +++ b/src/binaryToObject/elf.cpp @@ -131,8 +131,9 @@ unsigned getElfPlatform(PlatformInfo::Architecture arch) { return EM_ARM; case PlatformInfo::PowerPC: return EM_PPC; + default: + return ~0; } - return ~0; } const char* getSectionName(unsigned accessFlags, unsigned& sectionFlags) { @@ -255,8 +256,8 @@ public: SectionWriter(FileWriter& file): file(file), name(""), - data(0), - dataSize(0) + dataSize(0), + data(0) { memset(&header, 0, sizeof(SectionHeader)); file.sectionCount++; @@ -279,8 +280,8 @@ public: file(file), name(chname), - data(data), - dataSize(dataSize) + dataSize(dataSize), + data(data) { if(strcmp(chname, ".shstrtab") == 0) { file.sectionStringTableSectionNumber = file.sectionCount; @@ -359,11 +360,11 @@ public: file.writeHeader(out); - for(int i = 0; i < file.sectionCount; i++) { + for(unsigned i = 0; i < file.sectionCount; i++) { sections[i].writeHeader(out); } - for(int i = 0; i < file.sectionCount; i++) { + for(unsigned i = 0; i < file.sectionCount; i++) { sections[i].writeData(out); } diff --git a/src/binaryToObject/mach-o.cpp b/src/binaryToObject/mach-o.cpp index 50d7e56d78..dd89ddb304 100644 --- a/src/binaryToObject/mach-o.cpp +++ b/src/binaryToObject/mach-o.cpp @@ -183,14 +183,14 @@ public: FileHeader header = { V4(Magic), // magic - V4(cpuType), - V4(cpuSubType), + static_cast(V4(cpuType)), + static_cast(V4(cpuSubType)), V4(MH_OBJECT), // filetype, V4(2), // ncmds V4(sizeof(SegmentCommand) + sizeof(Section) + sizeof(SymtabCommand)), // sizeofcmds - V4(0) // flags + { V4(0) } // flags }; AddrTy finalSize = pad(data.count); @@ -206,8 +206,8 @@ public: + sizeof(Section) + sizeof(SymtabCommand))), // fileoff VANY(static_cast(finalSize)), // filesize - V4(7), // maxprot - V4(7), // initprot + static_cast(V4(7)), // maxprot + static_cast(V4(7)), // initprot V4(1), // nsects V4(0) // flags }; @@ -243,7 +243,7 @@ public: strings.write("_", 1); strings.add(sym->name); NList symbol = { - V4(offset), // n_un + { V4(offset) }, // n_un V1(N_SECT | N_EXT), // n_type V1(1), // n_sect V2(0), // n_desc @@ -281,6 +281,8 @@ public: out->writeChunk(symbolList.data, symbolList.length); out->writeChunk(strings.data, strings.length); + + return true; } MachOPlatform(PlatformInfo::Architecture arch): diff --git a/src/binaryToObject/main.cpp b/src/binaryToObject/main.cpp index d8f801a5e3..851a805bec 100644 --- a/src/binaryToObject/main.cpp +++ b/src/binaryToObject/main.cpp @@ -33,7 +33,7 @@ void* operator new(size_t size) { return malloc(size); } -void operator delete(void* mem) { abort(); } +void operator delete(void*) { abort(); } namespace { diff --git a/src/binaryToObject/pe.cpp b/src/binaryToObject/pe.cpp index 32f13cc4fa..69ca719bc1 100644 --- a/src/binaryToObject/pe.cpp +++ b/src/binaryToObject/pe.cpp @@ -129,11 +129,11 @@ public: void addSymbol(String name, unsigned addr, unsigned sectionNumber, unsigned type, unsigned storageClass) { unsigned nameOffset = strings.add(name); IMAGE_SYMBOL symbol = { - { 0 }, // Name + { { 0, 0 } }, // Name addr, // Value - sectionNumber, // SectionNumber - type, // Type - storageClass, // StorageClass + static_cast(sectionNumber), // SectionNumber + static_cast(type), // Type + static_cast(storageClass), // StorageClass 0, // NumberOfAuxSymbols }; symbol.N.Name.Long = nameOffset+4; @@ -165,9 +165,9 @@ public: size_t dataSize): file(file), - data(data), dataSize(dataSize), - finalSize(pad(dataSize)) + finalSize(pad(dataSize)), + data(data) { file.sectionCount++; file.dataStart += sizeof(IMAGE_SECTION_HEADER); diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 17a27f198d..a4555a9f6e 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -62,14 +62,6 @@ enum Type { class Field { public: - Field() { } - - Field(Type type, unsigned buildOffset, unsigned buildSize, - unsigned targetOffset, unsigned targetSize): - type(type), buildOffset(buildOffset), buildSize(buildSize), - targetOffset(targetOffset), targetSize(targetSize) - { } - Type type; unsigned buildOffset; unsigned buildSize; @@ -77,6 +69,17 @@ class Field { unsigned targetSize; }; +void +init(Field* f, Type type, unsigned buildOffset, unsigned buildSize, + unsigned targetOffset, unsigned targetSize) +{ + f->type = type; + f->buildOffset = buildOffset; + f->buildSize = buildSize; + f->targetOffset = targetOffset; + f->targetSize = targetSize; +} + class TypeMap { public: enum Kind { @@ -397,9 +400,9 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, map->targetFixedOffsets()[i * BytesPerWord] = i * TargetBytesPerWord; - new (map->fixedFields() + i) Field - (types[i], i * BytesPerWord, BytesPerWord, - i * TargetBytesPerWord, TargetBytesPerWord); + init(new (map->fixedFields() + i) Field, types[i], + i * BytesPerWord, BytesPerWord, i * TargetBytesPerWord, + TargetBytesPerWord); } hashMapInsert @@ -446,8 +449,8 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, ++ memberIndex; } } else { - new (memberFields) Field - (Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); + init(new (memberFields) Field, Type_object, 0, BytesPerWord, 0, + TargetBytesPerWord); memberIndex = 1; buildMemberOffset = BytesPerWord; @@ -456,12 +459,11 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, Field staticFields[count + 2]; - new (staticFields) Field - (Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); + init(new (staticFields) Field, Type_object, 0, BytesPerWord, 0, + TargetBytesPerWord); - new (staticFields + 1) Field - (Type_intptr_t, BytesPerWord, BytesPerWord, TargetBytesPerWord, - TargetBytesPerWord); + init(new (staticFields + 1) Field, Type_intptr_t, BytesPerWord, + BytesPerWord, TargetBytesPerWord, TargetBytesPerWord); unsigned staticIndex = 2; unsigned buildStaticOffset = BytesPerWord * 2; @@ -510,9 +512,9 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, buildStaticOffset = fieldOffset(t, field); - new (staticFields + staticIndex) Field - (type, buildStaticOffset, buildSize, targetStaticOffset, - targetSize); + init(new (staticFields + staticIndex) Field, type, + buildStaticOffset, buildSize, targetStaticOffset, + targetSize); targetStaticOffset += targetSize; @@ -524,9 +526,9 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, buildMemberOffset = fieldOffset(t, field); - new (memberFields + memberIndex) Field - (type, buildMemberOffset, buildSize, targetMemberOffset, - targetSize); + init(new (memberFields + memberIndex) Field, type, + buildMemberOffset, buildSize, targetMemberOffset, + targetSize); targetMemberOffset += targetSize; @@ -693,12 +695,6 @@ makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code, return constants; } -unsigned -objectSize(Thread* t, object o) -{ - return baseSize(t, o, objectClass(t, o)); -} - void visitRoots(Thread* t, BootImage* image, HeapWalker* w, object constants) { @@ -1267,12 +1263,6 @@ updateConstants(Thread* t, object constants, HeapMap* heapTable) } } -unsigned -offset(object a, uintptr_t* b) -{ - return reinterpret_cast(b) - reinterpret_cast(a); -} - BootImage::Thunk targetThunk(BootImage::Thunk t) { @@ -1347,7 +1337,8 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp Field fields[count]; - new (fields) Field(Type_object, 0, BytesPerWord, 0, TargetBytesPerWord); + init(new (fields) Field, Type_object, 0, BytesPerWord, 0, + TargetBytesPerWord); unsigned buildOffset = BytesPerWord; unsigned targetOffset = TargetBytesPerWord; @@ -1424,8 +1415,8 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp ++ targetOffset; } - new (fields + j) Field - (type, buildOffset, buildSize, targetOffset, targetSize); + init(new (fields + j) Field, type, buildOffset, buildSize, + targetOffset, targetSize); buildOffset += buildSize; targetOffset += targetSize; diff --git a/src/compile.cpp b/src/compile.cpp index 5e54cd8616..157f1fd24b 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -288,14 +288,6 @@ transition(MyThread* t, void* ip, void* stack, object continuation, MyThread::doTransition(t, ip, stack, continuation, trace); } -unsigned -parameterOffset(MyThread* t, object method) -{ - return methodParameterFootprint(t, method) - + t->arch->frameFooterSize() - + t->arch->frameReturnAddressSize() - 1; -} - object resolveThisPointer(MyThread* t, void* stack) { diff --git a/src/compiler.cpp b/src/compiler.cpp index 56a2709e42..e3e24103c6 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -579,27 +579,6 @@ cons(Context* c, void* value, Cell* next) return new (c->zone) Cell(next, value); } -Cell* -append(Context* c, Cell* first, Cell* second) -{ - if (first) { - if (second) { - Cell* start = cons(c, first->value, second); - Cell* end = start; - for (Cell* cell = first->next; cell; cell = cell->next) { - Cell* n = cons(c, cell->value, second); - end->next = n; - end = n; - } - return start; - } else { - return first; - } - } else { - return second; - } -} - Cell* reverseDestroy(Cell* cell) { @@ -992,25 +971,6 @@ valid(Read* r) return r and r->valid(); } -bool -hasBuddy(Context* c, Value* a, Value* b) -{ - if (a == b) { - return true; - } - - int i = 0; - for (Value* p = a->buddy; p != a; p = p->buddy) { - if (p == b) { - return true; - } - if (++i > 1000) { - abort(c); - } - } - return false; -} - Read* live(Context* c UNUSED, Value* v) { @@ -5302,16 +5262,17 @@ propagateJunctionSites(Context* c, Event* e) class SiteRecord { public: - SiteRecord(Site* site, Value* value): - site(site), value(value) - { } - - SiteRecord() { } - Site* site; Value* value; }; +void +init(SiteRecord* r, Site* s, Value* v) +{ + r->site = s; + r->value = v; +} + class SiteRecordList { public: SiteRecordList(SiteRecord* records, unsigned capacity): @@ -5329,7 +5290,7 @@ freeze(Context* c, SiteRecordList* frozen, Site* s, Value* v) assert(c, frozen->index < frozen->capacity); s->freeze(c, v); - new (frozen->records + (frozen->index ++)) SiteRecord(s, v); + init(new (frozen->records + (frozen->index ++)) SiteRecord, s, v); } void @@ -5866,17 +5827,6 @@ compile(Context* c, uintptr_t stackOverflowHandler, unsigned stackLimitOffset) c->firstBlock = firstBlock; } -unsigned -count(Stack* s) -{ - unsigned c = 0; - while (s) { - ++ c; - s = s->next; - } - return c; -} - void restore(Context* c, ForkState* state) { diff --git a/src/heap.cpp b/src/heap.cpp index b99de70de7..ed5d8777d4 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -60,7 +60,6 @@ void NO_RETURN abort(Context*); void assert(Context*, bool); #endif -System* system(Context*); void* tryAllocate(Context* c, unsigned size); void* allocate(Context* c, unsigned size); void free(Context* c, const void* p, unsigned size); @@ -689,12 +688,6 @@ class Context { int64_t totalTime; }; -inline System* -system(Context* c) -{ - return c->system; -} - const char* segment(Context* c, void* p) { diff --git a/src/heapwalk.cpp b/src/heapwalk.cpp index a34baf96dc..811382a825 100644 --- a/src/heapwalk.cpp +++ b/src/heapwalk.cpp @@ -231,16 +231,6 @@ get(object o, unsigned offsetInWords) (mask(cast(o, offsetInWords * BytesPerWord))); } -unsigned -objectSize(Thread* t, object o) -{ - unsigned n = baseSize(t, o, objectClass(t, o)); - if (objectExtended(t, o)) { - ++ n; - } - return n; -} - unsigned walk(Context* c, HeapVisitor* v, object p) { diff --git a/src/machine.cpp b/src/machine.cpp index 4c99de36de..53b6a0f66d 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -35,14 +35,6 @@ atomicIncrement(uint32_t* p, int v) } #endif -bool -find(Thread* t, Thread* o) -{ - return (t == o) - or (t->peer and find(t->peer, o)) - or (t->child and find(t->child, o)); -} - void join(Thread* t, Thread* o) { @@ -56,28 +48,6 @@ join(Thread* t, Thread* o) } } -unsigned -count(Thread* t, Thread* o) -{ - unsigned c = 0; - - if (t != o) ++ c; - if (t->peer) c += count(t->peer, o); - if (t->child) c += count(t->child, o); - - return c; -} - -Thread** -fill(Thread* t, Thread* o, Thread** array) -{ - if (t != o) *(array++) = t; - if (t->peer) array = fill(t->peer, o, array); - if (t->child) array = fill(t->child, o, array); - - return array; -} - void dispose(Thread* t, Thread* o, bool remove) { diff --git a/src/type-generator.cpp b/src/type-generator.cpp index ca5bd37056..813cce7dcd 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -70,12 +70,6 @@ equal(const char* a, const char* b) return strcmp(a, b) == 0; } -inline bool -startsWith(const char* a, const char* b) -{ - return strncmp(a, b, strlen(a)) == 0; -} - inline bool endsWith(const char* a, const char* b) { @@ -284,14 +278,6 @@ setCdr(Object* o, Object* v) static_cast(o)->cdr = v; } -unsigned -length(Object* o) -{ - unsigned c = 0; - for (; o; o = cdr(o)) ++c; - return c; -} - class List { public: Object* first; @@ -1078,53 +1064,6 @@ parseSubdeclaration(Object* t, Object* p, Object* declarations) } } -bool -memberEqual(Object* a, Object* b) -{ - if (a->type == b->type) { - switch (a->type) { - case Object::Scalar: - return equal(memberTypeName(a), memberTypeName(b)) - and memberNoAssert(a) == memberNoAssert(b) - and memberNoGC(a) == memberNoGC(b); - - // todo: compare array fields - - default: return false; - } - } else { - return false; - } -} - -bool -specEqual(Object* a, Object* b) -{ - if (a->type == Object::Type and - b->type == Object::Type) - { - MemberIterator ai(a); - MemberIterator bi(b); - while (ai.hasMore()) { - if (not bi.hasMore()) { - return false; - } - - if (not memberEqual(ai.next(), bi.next())) { - return false; - } - } - - if (bi.hasMore()) { - return false; - } else { - return true; - } - } else { - return false; - } -} - const char* append(const char* a, const char* b, const char* c, const char* d) { @@ -1725,13 +1664,6 @@ writeConstructorInitializations(Output* out, Object* t) } } -unsigned -typeMemberCount(Object* o) -{ - if (o == 0) return 0; - return length(typeMembers(o)) + typeMemberCount(typeSuper(o)); -} - void writeInitializerDeclarations(Output* out, Object* declarations) { @@ -1888,17 +1820,6 @@ writeEnums(Output* out, Object* declarations) } } -unsigned -memberCount(Object* o) -{ - unsigned c = 0; - for (MemberIterator it(o); it.hasMore();) { - it.next(); - ++c; - } - return c; -} - unsigned methodCount(Object* o) { diff --git a/src/x86.cpp b/src/x86.cpp index 095a567c63..6875449953 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -198,44 +198,12 @@ assert(ArchitectureContext* c, bool v) } #endif // not NDEBUG -void -expect(Context* c, bool v) -{ - expect(c->s, v); -} - ResolvedPromise* resolved(Context* c, int64_t value) { return new(c->zone) ResolvedPromise(value); } -class CodePromise: public Promise { - public: - CodePromise(Context* c, unsigned offset): c(c), offset(offset) { } - - virtual int64_t value() { - if (resolved()) { - return reinterpret_cast(c->result + offset); - } - - abort(c); - } - - virtual bool resolved() { - return c->result != 0; - } - - Context* c; - unsigned offset; -}; - -CodePromise* -codePromise(Context* c, unsigned offset) -{ - return new (c->zone) CodePromise(c, offset); -} - class Offset: public Promise { public: Offset(Context* c, MyBlock* block, unsigned offset, AlignmentPadding* limit): @@ -629,14 +597,6 @@ opcode(Context* c, uint8_t op1, uint8_t op2) c->code.append(op2); } -void -opcode(Context* c, uint8_t op1, uint8_t op2, uint8_t op3) -{ - c->code.append(op1); - c->code.append(op2); - c->code.append(op3); -} - void return_(Context* c) { From bd7ef247345d153c18cabbb5d09d33e7c9c577a6 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 1 Jun 2012 17:57:42 -0600 Subject: [PATCH 111/140] pass -std=c++11 to Clang for C++ code --- makefile | 2 +- src/compiler.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index b528fc2fb3..e8626126dd 100755 --- a/makefile +++ b/makefile @@ -139,7 +139,7 @@ endif input = List ifeq ($(use-clang),true) - build-cxx = clang + build-cxx = clang -std=c++11 build-cc = clang else build-cxx = g++ diff --git a/src/compiler.cpp b/src/compiler.cpp index e3e24103c6..812a38a9e9 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1578,7 +1578,7 @@ class ConstantSite: public Site { virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { if (value->resolved()) { return vm::snprintf - (buffer, bufferSize, "constant %"LLD, value->value()); + (buffer, bufferSize, "constant %" LLD, value->value()); } else { return vm::snprintf(buffer, bufferSize, "constant unresolved"); } @@ -1669,7 +1669,7 @@ class AddressSite: public Site { virtual unsigned toString(Context*, char* buffer, unsigned bufferSize) { if (address->resolved()) { return vm::snprintf - (buffer, bufferSize, "address %"LLD, address->value()); + (buffer, bufferSize, "address %" LLD, address->value()); } else { return vm::snprintf(buffer, bufferSize, "address unresolved"); } From 5d9f7b2bc33a2a10ef6e773b9b2584970b405585 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 2 Jun 2012 09:06:22 -0600 Subject: [PATCH 112/140] add optional LZMA support for compressing embedded JARs, boot images, and shared objects --- makefile | 94 +++++++++++++++++--- readme.txt | 24 +++++- src/bootimage-fields.cpp | 2 + src/bootimage.cpp | 44 ++++++++-- src/compile.cpp | 8 +- src/compiler.cpp | 23 +++++ src/finder.cpp | 36 +++++++- src/lzma-decode.cpp | 49 +++++++++++ src/lzma-encode.cpp | 71 +++++++++++++++ src/lzma-util.h | 53 ++++++++++++ src/lzma.h | 29 +++++++ src/lzma/load.cpp | 115 +++++++++++++++++++++++++ src/lzma/main.cpp | 182 +++++++++++++++++++++++++++++++++++++++ src/machine.cpp | 62 ++++++++++++- src/machine.h | 2 + 15 files changed, 764 insertions(+), 30 deletions(-) create mode 100644 src/lzma-decode.cpp create mode 100644 src/lzma-encode.cpp create mode 100644 src/lzma-util.h create mode 100644 src/lzma.h create mode 100644 src/lzma/load.cpp create mode 100644 src/lzma/main.cpp diff --git a/makefile b/makefile index e8626126dd..b0af8f8ae8 100755 --- a/makefile +++ b/makefile @@ -33,6 +33,9 @@ endif ifneq ($(mode),fast) options := $(options)-$(mode) endif +ifneq ($(lzma),) + options := $(options)-lzma +endif ifeq ($(bootimage),true) options := $(options)-bootimage endif @@ -532,6 +535,7 @@ ifdef msvc strip = : endif +c-objects = $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%.o,$(x))) cpp-objects = $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%.o,$(x))) asm-objects = $(foreach x,$(1),$(patsubst $(2)/%.S,$(3)/%-asm.o,$(x))) java-classes = $(foreach x,$(1),$(patsubst $(2)/%.java,$(3)/%.class,$(x))) @@ -594,7 +598,10 @@ ifeq ($(continuations),true) asmflags += -DAVIAN_CONTINUATIONS endif -bootimage-generator-sources = $(src)/bootimage.cpp +bootimage-generator-sources = $(src)/bootimage.cpp +ifneq ($(lzma),) + bootimage-generator-sources += $(src)/lzma-encode.cpp +endif bootimage-generator-objects = \ $(call cpp-objects,$(bootimage-generator-sources),$(src),$(build)) bootimage-generator = $(build)/bootimage-generator @@ -629,17 +636,62 @@ generator-sources = \ $(src)/type-generator.cpp \ $(src)/$(build-system).cpp \ $(src)/finder.cpp + +ifneq ($(lzma),) + common-cflags += -I$(lzma)/C -DAVIAN_USE_LZMA -D_7ZIP_ST + + vm-sources += \ + $(src)/lzma-decode.cpp + + generator-sources += \ + $(src)/lzma-decode.cpp + + lzma-decode-sources = \ + $(lzma)/C/LzmaDec.c + + lzma-decode-objects = \ + $(call c-objects,$(lzma-decode-sources),$(lzma)/C,$(build)) + + lzma-encode-sources = \ + $(lzma)/C/LzmaEnc.c \ + $(lzma)/C/LzFind.c + + lzma-encode-objects = \ + $(call c-objects,$(lzma-encode-sources),$(lzma)/C,$(build)) + + lzma-encoder = $(build)/lzma/lzma + + lzma-encoder-cflags = -D__STDC_CONSTANT_MACROS -fno-rtti -fno-exceptions \ + -I$(lzma)/C + + lzma-encoder-sources = \ + $(src)/lzma/main.cpp + + lzma-encoder-objects = \ + $(call cpp-objects,$(lzma-encoder-sources),$(src),$(build)) + + lzma-encoder-lzma-sources = $(lzma-encode-sources) $(lzma-decode-sources) + + lzma-encoder-lzma-objects = \ + $(call c-objects,$(lzma-encoder-lzma-sources),$(lzma)/C,$(build)) + + lzma-loader = $(build)/lzma/load.o +endif + generator-cpp-objects = \ $(foreach x,$(1),$(patsubst $(2)/%.cpp,$(3)/%-build.o,$(x))) +generator-c-objects = \ + $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%-build.o,$(x))) generator-objects = \ $(call generator-cpp-objects,$(generator-sources),$(src),$(build)) +generator-lzma-objects = \ + $(call generator-c-objects,$(lzma-decode-sources),$(lzma)/C,$(build)) generator = $(build)/generator converter-depends = \ $(src)/binaryToObject/tools.h \ $(src)/binaryToObject/endianness.h - converter-sources = \ $(src)/binaryToObject/tools.cpp \ $(src)/binaryToObject/elf.cpp \ @@ -760,7 +812,7 @@ test-flags = -cp $(build)/test test-args = $(test-flags) $(input) .PHONY: build -build: $(static-library) $(executable) $(dynamic-library) \ +build: $(static-library) $(executable) $(dynamic-library) $(lzma-loader) \ $(executable-dynamic) $(classpath-dep) $(test-dep) $(test-extra-dep) $(test-dep): $(classpath-dep) @@ -863,6 +915,9 @@ endef $(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) $(compile-object) +$(build)/%.o: $(lzma)/C/%.c + $(compile-object) + $(vm-asm-objects): $(build)/%-asm.o: $(src)/%.S $(compile-asm-object) @@ -894,6 +949,16 @@ $(converter-objects) $(converter-tool-objects): $(build)/binaryToObject/%.o: $(s $(converter): $(converter-objects) $(converter-tool-objects) $(build-cc) $(^) -g -o $(@) +$(lzma-encoder-objects): $(build)/lzma/%.o: $(src)/lzma/%.cpp + @mkdir -p $(dir $(@)) + $(build-cxx) $(lzma-encoder-cflags) -c $(<) -o $(@) + +$(lzma-encoder): $(lzma-encoder-objects) $(lzma-encoder-lzma-objects) + $(build-cc) $(^) -g -o $(@) + +$(lzma-loader): $(src)/lzma/load.cpp + $(compile-object) + $(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep) @echo "creating $(@)" (wd=$$(pwd) && \ @@ -916,18 +981,25 @@ $(javahome-object): $(build)/javahome.jar $(converter) $(converter) $(<) $(@) _binary_javahome_jar_start \ _binary_javahome_jar_end $(platform) $(arch) -$(generator-objects): $(generator-depends) -$(generator-objects): $(build)/%-build.o: $(src)/%.cpp +define compile-generator-object @echo "compiling $(@)" @mkdir -p $(dir $(@)) $(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \ -c $(<) -o $(@) +endef + +$(generator-objects): $(generator-depends) +$(generator-objects): $(build)/%-build.o: $(src)/%.cpp + $(compile-generator-object) + +$(generator-lzma-objects): $(build)/%-build.o: $(lzma)/C/%.c + $(compile-generator-object) $(jni-objects): $(build)/%.o: $(classpath-src)/%.cpp $(compile-object) $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ - $(javahome-object) $(boot-javahome-object) + $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) @echo "creating $(@)" rm -rf $(@) $(ar) cru $(@) $(^) @@ -940,7 +1012,7 @@ $(bootimage-object) $(codeimage-object): $(bootimage-generator) executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ - $(javahome-object) $(boot-javahome-object) + $(javahome-object) $(boot-javahome-object) $(lzma-decode-objects) $(executable): $(executable-objects) @echo "linking $(@)" @@ -976,7 +1048,8 @@ $(bootimage-generator): $(bootimage-generator-objects) $(build-bootimage-generator): \ $(vm-objects) $(classpath-object) $(classpath-objects) \ - $(heapwalk-objects) $(bootimage-generator-objects) $(converter-objects) + $(heapwalk-objects) $(bootimage-generator-objects) $(converter-objects) \ + $(lzma-decode-objects) $(lzma-encode-objects) @echo "linking $(@)" ifeq ($(platform),windows) ifdef msvc @@ -994,7 +1067,8 @@ endif $(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \ $(vm-heapwalk-objects) $(boot-object) $(vm-classpath-objects) \ - $(classpath-libraries) $(javahome-object) $(boot-javahome-object) + $(classpath-libraries) $(javahome-object) $(boot-javahome-object) \ + $(lzma-decode-objects) @echo "linking $(@)" ifdef msvc $(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \ @@ -1020,7 +1094,7 @@ else endif $(strip) $(strip-all) $(@) -$(generator): $(generator-objects) +$(generator): $(generator-objects) $(generator-lzma-objects) @echo "linking $(@)" $(build-ld) $(^) $(build-lflags) -o $(@) diff --git a/readme.txt b/readme.txt index ac54ca700f..ca43b1fa9e 100644 --- a/readme.txt +++ b/readme.txt @@ -79,6 +79,7 @@ certain flags described below, all of which are optional. arch={i386,x86_64,powerpc,arm} \ process={compile,interpret} \ mode={debug,debug-fast,fast,small} \ + lzma= \ ios={true,false} \ bootimage={true,false} \ heapdump={true,false} \ @@ -104,6 +105,13 @@ certain flags described below, all of which are optional. assertions default: fast + * lzma - if set, support use of LZMA to compress embedded JARs and + boot images. The value of this option should be a directory + containing a recent LZMA SDK (available at + http://www.7-zip.org/sdk.html). Currently, only version 9.20 of + the SDK has been tested, but other versions might work. + default: not set + * ios - if true, cross-compile for iOS on OS X. Note that non-jailbroken iOS devices do not allow JIT compilation, so only process=interpret or bootimage=true builds will run on such @@ -366,8 +374,20 @@ EOF Step 3: Make an object file out of the jar. - $ ../build/${platform}-${arch}/binaryToObject/binaryToObject boot.jar boot-jar.o \ - _binary_boot_jar_start _binary_boot_jar_end ${platform} ${arch} + $ ../build/${platform}-${arch}/binaryToObject/binaryToObject boot.jar \ + boot-jar.o _binary_boot_jar_start _binary_boot_jar_end ${platform} ${arch} + +If you've built Avian using the lzma option, you may optionally +compress the jar before generating the object: + + $ ../build/$(platform}-${arch}-lzma/lzma/lzma encode boot.jar boot.jar.lzma + && ../build/${platform}-${arch}-lzma/binaryToObject/binaryToObject \ + boot.jar.lzma boot-jar.o _binary_boot_jar_start _binary_boot_jar_end \ + ${platform} ${arch} + +Note that you'll need to specify "-Xbootclasspath:[lzma:bootJar]" +instead of "-Xbootclasspath:[bootJar]" in the next step if you've used +LZMA to compress the jar. Step 4: Write a driver which starts the VM and runs the desired main method. Note the bootJar function, which will be called by the VM to diff --git a/src/bootimage-fields.cpp b/src/bootimage-fields.cpp index 7638830585..a090268de2 100644 --- a/src/bootimage-fields.cpp +++ b/src/bootimage-fields.cpp @@ -5,6 +5,8 @@ FIELD(magic) +FIELD(initialized) + FIELD(heapSize) FIELD(codeSize) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index a4555a9f6e..2affc13f6f 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -17,6 +17,7 @@ #include "assembler.h" #include "target.h" #include "binaryToObject/tools.h" +#include "lzma.h" // since we aren't linking against libstdc++, we must implement this // ourselves: @@ -1275,7 +1276,8 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp BootImage* image, uint8_t* code, const char* className, const char* methodName, const char* methodSpec, const char* bootimageStart, const char* bootimageEnd, - const char* codeimageStart, const char* codeimageEnd) + const char* codeimageStart, const char* codeimageEnd, + bool useLZMA) { setRoot(t, Machine::OutOfMemoryError, make(t, type(t, Machine::OutOfMemoryErrorType))); @@ -1594,6 +1596,7 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp heapWalker->dispose(); image->magic = BootImage::Magic; + image->initialized = 0; fprintf(stderr, "class count %d string count %d call count %d\n" "heap size %d code size %d\n", @@ -1656,7 +1659,27 @@ writeBootImage2(Thread* t, OutputStream* bootimageOutput, OutputStream* codeOutp SymbolInfo(bootimageData.length, bootimageEnd) }; - platform->writeObject(bootimageOutput, Slice(bootimageSymbols, 2), Slice(bootimageData.data, bootimageData.length), Platform::Writable, TargetBytesPerWord); + uint8_t* bootimage; + unsigned bootimageLength; + if (useLZMA) { +#ifdef AVIAN_USE_LZMA + bootimage = encodeLZMA(t->m->system, t->m->heap, bootimageData.data, + bootimageData.length, &bootimageLength); + + fprintf(stderr, "compressed heap size %d\n", bootimageLength); +#else + abort(t); +#endif + } else { + bootimage = bootimageData.data; + bootimageLength = bootimageData.length; + } + + platform->writeObject(bootimageOutput, Slice(bootimageSymbols, 2), Slice(bootimage, bootimageLength), Platform::Writable, TargetBytesPerWord); + + if (useLZMA) { + t->m->heap->free(bootimage, bootimageLength); + } compilationHandler.symbols.add(SymbolInfo(0, codeimageStart)); compilationHandler.symbols.add(SymbolInfo(image->codeSize, codeimageEnd)); @@ -1684,10 +1707,12 @@ writeBootImage(Thread* t, uintptr_t* arguments) const char* bootimageEnd = reinterpret_cast(arguments[8]); const char* codeimageStart = reinterpret_cast(arguments[9]); const char* codeimageEnd = reinterpret_cast(arguments[10]); + bool useLZMA = arguments[11]; writeBootImage2 (t, bootimageOutput, codeOutput, image, code, className, methodName, - methodSpec, bootimageStart, bootimageEnd, codeimageStart, codeimageEnd); + methodSpec, bootimageStart, bootimageEnd, codeimageStart, codeimageEnd, + useLZMA); return 1; } @@ -1746,7 +1771,11 @@ bool ArgParser::parse(int ac, const char** av) { } for(Arg* arg = first; arg; arg = arg->next) { if(strcmp(arg->name, &av[i][1]) == 0) { - state = arg; + if (arg->desc == 0) { + arg->value = "true"; + } else { + state = arg; + } } } if(!state) { @@ -1801,6 +1830,8 @@ public: char* codeimageStart; char* codeimageEnd; + bool useLZMA; + bool maybeSplit(const char* src, char*& destA, char*& destB) { if(src) { const char* split = strchr(src, ':'); @@ -1830,6 +1861,7 @@ public: Arg entry(parser, false, "entry", "[.[]]"); Arg bootimageSymbols(parser, false, "bootimage-symbols", ":"); Arg codeimageSymbols(parser, false, "codeimage-symbols", ":"); + Arg useLZMA(parser, false, "use-lzma", 0); if(!parser.parse(ac, av)) { parser.printUsage(av[0]); @@ -1839,6 +1871,7 @@ public: this->classpath = classpath.value; this->bootimage = bootimage.value; this->codeimage = codeimage.value; + this->useLZMA = useLZMA.value != 0; if(entry.value) { if(const char* entryClassEnd = strchr(entry.value, '.')) { @@ -1988,7 +2021,8 @@ main(int ac, const char** av) reinterpret_cast(args.bootimageStart), reinterpret_cast(args.bootimageEnd), reinterpret_cast(args.codeimageStart), - reinterpret_cast(args.codeimageEnd) + reinterpret_cast(args.codeimageEnd), + reinterpret_cast(args.useLZMA) }; run(t, writeBootImage, arguments); diff --git a/src/compile.cpp b/src/compile.cpp index 157f1fd24b..86edcb033e 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -9631,9 +9631,7 @@ boot(MyThread* t, BootImage* image, uint8_t* code) // fprintf(stderr, "code from %p to %p\n", // code, code + image->codeSize); - static bool fixed = false; - - if (not fixed) { + if (not image->initialized) { fixupHeap(t, heapMap, heapMapSizeInWords, heap); } @@ -9680,7 +9678,7 @@ boot(MyThread* t, BootImage* image, uint8_t* code) findThunks(t, image, code); - if (fixed) { + if (image->initialized) { resetRuntimeState (t, classLoaderMap(t, root(t, Machine::BootLoader)), heap, image->heapSize); @@ -9703,7 +9701,7 @@ boot(MyThread* t, BootImage* image, uint8_t* code) (t, classLoaderMap(t, root(t, Machine::AppLoader)), image, code); } - fixed = true; + image->initialized = true; setRoot(t, Machine::BootstrapClassMap, makeHashMap(t, 0, 0)); } diff --git a/src/compiler.cpp b/src/compiler.cpp index 812a38a9e9..213c6e81ae 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -971,6 +971,29 @@ valid(Read* r) return r and r->valid(); } +#ifndef NDEBUG + +bool +hasBuddy(Context* c, Value* a, Value* b) +{ + if (a == b) { + return true; + } + + int i = 0; + for (Value* p = a->buddy; p != a; p = p->buddy) { + if (p == b) { + return true; + } + if (++i > 1000) { + abort(c); + } + } + return false; +} + +#endif // not NDEBUG + Read* live(Context* c UNUSED, Value* v) { diff --git a/src/finder.cpp b/src/finder.cpp index 1a08e65008..ba8aef75f4 100644 --- a/src/finder.cpp +++ b/src/finder.cpp @@ -12,6 +12,7 @@ #include "system.h" #include "tokenizer.h" #include "finder.h" +#include "lzma.h" using namespace vm; @@ -173,11 +174,12 @@ class DirectoryElement: public Element { class PointerRegion: public System::Region { public: PointerRegion(System* s, Allocator* allocator, const uint8_t* start, - size_t length): + size_t length, bool freePointer = false): s(s), allocator(allocator), start_(start), - length_(length) + length_(length), + freePointer(freePointer) { } virtual const uint8_t* start() { @@ -189,6 +191,9 @@ class PointerRegion: public System::Region { } virtual void dispose() { + if (freePointer) { + allocator->free(start_, length_); + } allocator->free(this, sizeof(*this)); } @@ -196,6 +201,7 @@ class PointerRegion: public System::Region { Allocator* allocator; const uint8_t* start_; size_t length_; + bool freePointer; }; class DataRegion: public System::Region { @@ -556,7 +562,10 @@ class BuiltinElement: public JarElement { virtual void init() { if (index == 0) { if (s->success(s->load(&library, libraryName))) { - void* p = library->resolve(name); + bool lzma = strncmp("lzma:", name, 5) == 0; + const char* symbolName = lzma ? name + 5 : name; + + void* p = library->resolve(symbolName); if (p) { uint8_t* (*function)(unsigned*); memcpy(&function, &p, BytesPerWord); @@ -564,10 +573,29 @@ class BuiltinElement: public JarElement { unsigned size; uint8_t* data = function(&size); if (data) { + bool freePointer; + if (lzma) { +#ifdef AVIAN_USE_LZMA + unsigned outSize; + data = decodeLZMA(s, allocator, data, size, &outSize); + size = outSize; + freePointer = true; +#else + abort(s); +#endif + } else { + freePointer = false; + } region = new (allocator->allocate(sizeof(PointerRegion))) - PointerRegion(s, allocator, data, size); + PointerRegion(s, allocator, data, size, freePointer); index = JarIndex::open(s, allocator, region); + } else if (DebugFind) { + fprintf(stderr, "%s in %s returned null\n", symbolName, + libraryName); } + } else if (DebugFind) { + fprintf(stderr, "unable to find %s in %s\n", symbolName, + libraryName); } } } diff --git a/src/lzma-decode.cpp b/src/lzma-decode.cpp new file mode 100644 index 0000000000..7710934ddd --- /dev/null +++ b/src/lzma-decode.cpp @@ -0,0 +1,49 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "lzma-util.h" +#include "LzmaDec.h" + +using namespace vm; + +namespace vm { + +uint8_t* +decodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, + unsigned* outSize) +{ + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + int32_t outSize32; + memcpy(&outSize32, in + PropHeaderSize, 4); + expect(s, outSize32 >= 0); + SizeT outSizeT = outSize32; + + uint8_t* out = static_cast(a->allocate(outSize32)); + + SizeT inSizeT = inSize; + LzmaAllocator allocator(a); + + ELzmaStatus status; + int result = LzmaDecode + (out, &outSizeT, in + HeaderSize, &inSizeT, in, PropHeaderSize, + LZMA_FINISH_END, &status, &(allocator.allocator)); + + expect(s, result == SZ_OK); + expect(s, status == LZMA_STATUS_FINISHED_WITH_MARK); + + *outSize = outSize32; + + return out; +} + +} // namespace vm + diff --git a/src/lzma-encode.cpp b/src/lzma-encode.cpp new file mode 100644 index 0000000000..d1b002476a --- /dev/null +++ b/src/lzma-encode.cpp @@ -0,0 +1,71 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#include "lzma-util.h" +#include "LzmaEnc.h" + +using namespace vm; + +namespace { + +SRes +myProgress(void*, UInt64, UInt64) +{ + return SZ_OK; +} + +} // namespace + +namespace vm { + +uint8_t* +encodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, + unsigned* outSize) +{ + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + unsigned bufferSize = inSize * 2; + + uint8_t* buffer = static_cast(a->allocate(bufferSize)); + + LzmaAllocator allocator(a); + + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = 9; + props.writeEndMark = 1; + + ICompressProgress progress = { myProgress }; + + SizeT propsSize = PropHeaderSize; + + int32_t inSize32 = inSize; + memcpy(buffer + PropHeaderSize, &inSize32, 4); + + SizeT outSizeT = bufferSize; + int result = LzmaEncode + (buffer + HeaderSize, &outSizeT, in, inSize, &props, buffer, + &propsSize, 1, &progress, &(allocator.allocator), &(allocator.allocator)); + + expect(s, result == SZ_OK); + + *outSize = outSizeT + HeaderSize; + + uint8_t* out = static_cast(a->allocate(*outSize)); + memcpy(out, buffer, *outSize); + + a->free(buffer, bufferSize); + + return out; +} + +} // namespace vm + diff --git a/src/lzma-util.h b/src/lzma-util.h new file mode 100644 index 0000000000..105a9e4077 --- /dev/null +++ b/src/lzma-util.h @@ -0,0 +1,53 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef LZMA_UTIL_H +#define LZMA_UTIL_H + +#include "lzma.h" +#include "Types.h" +#include "system.h" +#include "allocator.h" + +namespace vm { + +const unsigned Padding = 16; + +class LzmaAllocator { + public: + LzmaAllocator(Allocator* a): a(a) { + allocator.Alloc = allocate; + allocator.Free = free; + } + + ISzAlloc allocator; + Allocator* a; + + static void* allocate(void* allocator, size_t size) { + uint8_t* p = static_cast + (static_cast(allocator)->a->allocate(size + Padding)); + int32_t size32 = size; + memcpy(p, &size32, 4); + return p + Padding; + } + + static void free(void* allocator, void* address) { + if (address) { + void* p = static_cast(address) - Padding; + int32_t size32; + memcpy(&size32, p, 4); + static_cast(allocator)->a->free(p, size32 + Padding); + } + } +}; + +} // namespace vm + +#endif // LZMA_UTIL_H diff --git a/src/lzma.h b/src/lzma.h new file mode 100644 index 0000000000..5e6ba35a82 --- /dev/null +++ b/src/lzma.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2012, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef LZMA_H +#define LZMA_H + +#include "system.h" +#include "allocator.h" + +namespace vm { + +uint8_t* +decodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, + unsigned* outSize); + +uint8_t* +encodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, + unsigned* outSize); + +} // namespace vm + +#endif // LZMA_H diff --git a/src/lzma/load.cpp b/src/lzma/load.cpp new file mode 100644 index 0000000000..f4fc57965c --- /dev/null +++ b/src/lzma/load.cpp @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "LzmaDec.h" + +#ifdef __MINGW32__ +# define EXPORT __declspec(dllexport) +#else +# define EXPORT __attribute__ ((visibility("default"))) +#endif + +#if defined __MINGW32__ && ! defined __x86_64__ +# define SYMBOL(x) binary_exe_##x +#else +# define SYMBOL(x) _binary_exe_##x +#endif + +extern "C" { + + extern const uint8_t SYMBOL(start)[]; + extern const uint8_t SYMBOL(end)[]; + +} // extern "C" + +namespace { + +void* +myAllocate(void*, size_t size) +{ + return malloc(size); +} + +void +myFree(void*, void* address) +{ + free(address); +} + +} // namespace + +int +main(int ac, const char** av) +{ + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + SizeT inSize = SYMBOL(end) - SYMBOL(start); + + int32_t outSize32; + memcpy(&outSize32, SYMBOL(start) + PropHeaderSize, 4); + SizeT outSize = outSize32; + + uint8_t* out = static_cast(malloc(outSize)); + if (out) { + ISzAlloc allocator = { myAllocate, myFree }; + ELzmaStatus status = LZMA_STATUS_NOT_SPECIFIED; + + if (SZ_OK == LzmaDecode + (out, &outSize, SYMBOL(start) + HeaderSize, &inSize, SYMBOL(start), + PropHeaderSize, LZMA_FINISH_END, &status, &allocator)) + { + char name[L_tmpnam]; + if (tmpnam(name)) { + int file = open(name, O_CREAT | O_EXCL | O_WRONLY, S_IRWXU); + if (file != -1) { + SizeT result = write(file, out, outSize); + free(out); + + if (close(file) == 0 and outSize == result) { + void* library = dlopen(name, RTLD_LAZY | RTLD_GLOBAL); + unlink(name); + + if (library) { + void* main = dlsym(library, "main"); + if (main) { + int (*mainFunction)(int, const char**); + memcpy(&mainFunction, &main, sizeof(void*)); + return mainFunction(ac, av); + } else { + fprintf(stderr, "unable to find main in %s", name); + } + } else { + fprintf(stderr, "unable to dlopen %s: %s\n", name, dlerror()); + } + } else { + unlink(name); + + fprintf(stderr, "close or write failed; tried %d, got %d; %s\n", + static_cast(outSize), static_cast(result), + strerror(errno)); + } + } else { + fprintf(stderr, "unable to open %s\n", name); + } + } else { + fprintf(stderr, "unable to make temporary file name\n"); + } + } else { + fprintf(stderr, "unable to decode LZMA data\n"); + } + } else { + fprintf(stderr, "unable to allocate buffer of size %d\n", + static_cast(outSize)); + } + + return -1; +} diff --git a/src/lzma/main.cpp b/src/lzma/main.cpp new file mode 100644 index 0000000000..a9a558d897 --- /dev/null +++ b/src/lzma/main.cpp @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#include +#ifdef WIN32 +#include +#else +#include +#include +#endif +#include + +#include "LzmaEnc.h" +#include "LzmaDec.h" + +namespace { + +void* +myAllocate(void*, size_t size) +{ + return malloc(size); +} + +void +myFree(void*, void* address) +{ + free(address); +} + +SRes +myProgress(void*, UInt64, UInt64) +{ + return SZ_OK; +} + +void +usageAndExit(const char* program) +{ + fprintf(stderr, + "usage: %s {encode|decode} " + "[]", program); + exit(-1); +} + +} // namespace + +int +main(int argc, const char** argv) +{ + if (argc < 4 or argc > 5) { + usageAndExit(argv[0]); + } + + bool encode = strcmp(argv[1], "encode") == 0; + + uint8_t* data = 0; + unsigned size; + int fd = open(argv[2], O_RDONLY); + if (fd != -1) { + struct stat s; + int r = fstat(fd, &s); + if (r != -1) { +#ifdef WIN32 + HANDLE fm; + HANDLE h = (HANDLE) _get_osfhandle (fd); + + fm = CreateFileMapping( + h, + NULL, + PAGE_READONLY, + 0, + 0, + NULL); + data = static_cast(MapViewOfFile( + fm, + FILE_MAP_READ, + 0, + 0, + s.st_size)); + + CloseHandle(fm); +#else + data = static_cast + (mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0)); +#endif + size = s.st_size; + } + close(fd); + } + + bool success = false; + + if (data) { + const unsigned PropHeaderSize = 5; + const unsigned HeaderSize = 13; + + SizeT outSize; + if (encode) { + outSize = size * 2; + } else { + int32_t outSize32; + memcpy(&outSize32, data + PropHeaderSize, 4); + if (outSize32 >= 0) { + outSize = outSize32; + } else if (argc == 5) { + outSize = atoi(argv[4]); + } else { + outSize = -1; + } + } + + if (outSize >= 0) { + uint8_t* out = static_cast(malloc(outSize)); + if (out) { + SizeT inSize = size; + ISzAlloc allocator = { myAllocate, myFree }; + ELzmaStatus status = LZMA_STATUS_NOT_SPECIFIED; + int result; + if (encode) { + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = 9; + props.writeEndMark = 1; + + ICompressProgress progress = { myProgress }; + + SizeT propsSize = PropHeaderSize; + + int32_t inSize32 = inSize; + memcpy(out + PropHeaderSize, &inSize32, 4); + + result = LzmaEncode + (out + HeaderSize, &outSize, data, inSize, &props, out, + &propsSize, 1, &progress, &allocator, &allocator); + + outSize += HeaderSize; + } else { + result = LzmaDecode + (out, &outSize, data + HeaderSize, &inSize, data, PropHeaderSize, + LZMA_FINISH_END, &status, &allocator); + } + + if (result == SZ_OK) { + FILE* outFile = fopen(argv[3], "wb"); + + if (outFile) { + if (fwrite(out, outSize, 1, outFile) == 1) { + success = true; + } else { + fprintf(stderr, "unable to write to %s\n", argv[3]); + } + + fclose(outFile); + } else { + fprintf(stderr, "unable to open %s\n", argv[3]); + } + } else { + fprintf(stderr, "unable to %s data: result %d status %d\n", + encode ? "encode" : "decode", result, status); + } + + free(out); + } else { + fprintf(stderr, "unable to allocate output buffer\n"); + } + } else { + fprintf(stderr, "unable to determine uncompressed size\n"); + } + +#ifdef WIN32 + UnmapViewOfFile(data); +#else + munmap(data, size); +#endif + } else { + perror(argv[0]); + } + + return (success ? 0 : -1); +} diff --git a/src/machine.cpp b/src/machine.cpp index 53b6a0f66d..6e242dd8b8 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -15,6 +15,7 @@ #include "constants.h" #include "processor.h" #include "arch.h" +#include "lzma.h" using namespace vm; @@ -48,6 +49,40 @@ join(Thread* t, Thread* o) } } +#ifndef NDEBUG + +bool +find(Thread* t, Thread* o) +{ + return (t == o) + or (t->peer and find(t->peer, o)) + or (t->child and find(t->child, o)); +} + +unsigned +count(Thread* t, Thread* o) +{ + unsigned c = 0; + + if (t != o) ++ c; + if (t->peer) c += count(t->peer, o); + if (t->child) c += count(t->child, o); + + return c; +} + +Thread** +fill(Thread* t, Thread* o, Thread** array) +{ + if (t != o) *(array++) = t; + if (t->peer) array = fill(t->peer, o, array); + if (t->child) array = fill(t->child, o, array); + + return array; +} + +#endif // not NDEBUG + void dispose(Thread* t, Thread* o, bool remove) { @@ -203,8 +238,8 @@ turnOffTheLights(Thread* t) Finder* af = m->appFinder; c->dispose(); - m->dispose(); h->disposeFixies(); + m->dispose(); p->dispose(); bf->dispose(); af->dispose(); @@ -2945,6 +2980,10 @@ Machine::dispose() heap->free(heapPool[i], ThreadHeapSizeInBytes); } + if (bootimage) { + heap->free(bootimage, bootimageSize); + } + heap->free(arguments, sizeof(const char*) * argumentCount); heap->free(properties, sizeof(const char*) * propertyCount); @@ -3000,13 +3039,28 @@ Thread::init() uint8_t* code = 0; const char* imageFunctionName = findProperty(m, "avian.bootimage"); if (imageFunctionName) { - void* imagep = m->libraries->resolve(imageFunctionName); + bool lzma = strncmp("lzma:", imageFunctionName, 5) == 0; + const char* symbolName + = lzma ? imageFunctionName + 5 : imageFunctionName; + + void* imagep = m->libraries->resolve(symbolName); if (imagep) { - BootImage* (*imageFunction)(unsigned*); + uint8_t* (*imageFunction)(unsigned*); memcpy(&imageFunction, &imagep, BytesPerWord); unsigned size; - image = imageFunction(&size); + uint8_t* imageBytes = imageFunction(&size); + if (lzma) { +#ifdef AVIAN_USE_LZMA + m->bootimage = image = reinterpret_cast + (decodeLZMA + (m->system, m->heap, imageBytes, size, &(m->bootimageSize))); +#else + abort(this); +#endif + } else { + image = reinterpret_cast(imageBytes); + } const char* codeFunctionName = findProperty(m, "avian.codeimage"); if (codeFunctionName) { diff --git a/src/machine.h b/src/machine.h index 05bc01b1e6..bb3b97a43c 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1316,6 +1316,7 @@ class Machine { System::Monitor* shutdownLock; System::Library* libraries; FILE* errorLog; + BootImage* bootimage; object types; object roots; object finalizers; @@ -1332,6 +1333,7 @@ class Machine { JNIEnvVTable jniEnvVTable; uintptr_t* heapPool[ThreadHeapPoolSize]; unsigned heapPoolIndex; + unsigned bootimageSize; }; void From f07a8c7ec48ef494354eb8590c943d899b242223 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 2 Jun 2012 13:23:52 -0600 Subject: [PATCH 113/140] make LZMA encoder by default --- makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index b0af8f8ae8..8ec37fdd50 100755 --- a/makefile +++ b/makefile @@ -813,7 +813,8 @@ test-args = $(test-flags) $(input) .PHONY: build build: $(static-library) $(executable) $(dynamic-library) $(lzma-loader) \ - $(executable-dynamic) $(classpath-dep) $(test-dep) $(test-extra-dep) + $(lzma-encoder) $(executable-dynamic) $(classpath-dep) $(test-dep) \ + $(test-extra-dep) $(test-dep): $(classpath-dep) From d61501453f4cf948ba7981d743fbb6282899dbc5 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 2 Jun 2012 15:43:42 -0600 Subject: [PATCH 114/140] add support for LZMA on Windows --- makefile | 20 ++++++--- src/compile.cpp | 2 +- src/lzma-decode.cpp | 2 +- src/lzma-encode.cpp | 2 +- src/lzma-util.h | 2 +- src/lzma/load.cpp | 104 ++++++++++++++++++++++++++++++++++++++------ src/machine.cpp | 1 + 7 files changed, 109 insertions(+), 24 deletions(-) diff --git a/makefile b/makefile index 8ec37fdd50..de21c012b8 100755 --- a/makefile +++ b/makefile @@ -71,6 +71,8 @@ ifeq ($(build-platform),cygwin) native-path = cygpath -m endif +windows-path = echo + path-separator = : ifneq (,$(filter mingw32 cygwin,$(build-platform))) @@ -500,8 +502,9 @@ ld := $(cc) build-ld := $(build-cc) ifdef msvc - windows-java-home := $(shell cygpath -m "$(JAVA_HOME)") - zlib := $(shell cygpath -m "$(win32)/msvc") + windows-path = $(native-path) + windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") + zlib := $(shell $(windows-path) "$(win32)/msvc") cxx = "$(msvc)/BIN/cl.exe" cc = $(cxx) ld = "$(msvc)/BIN/link.exe" @@ -512,6 +515,11 @@ ifdef msvc -Fd$(build)/$(name).pdb -I"$(zlib)/include" -I$(src) -I"$(build)" \ -I"$(windows-java-home)/include" -I"$(windows-java-home)/include/win32" \ -DTARGET_BYTES_PER_WORD=$(pointer-size) + + ifneq ($(lzma),) + cflags += -I$(shell $(windows-path) "$(lzma)") + endif + shared = -dll lflags = -nologo -LIBPATH:"$(zlib)/lib" -DEFAULTLIB:ws2_32 \ -DEFAULTLIB:zlib -MANIFEST -debug @@ -638,7 +646,7 @@ generator-sources = \ $(src)/finder.cpp ifneq ($(lzma),) - common-cflags += -I$(lzma)/C -DAVIAN_USE_LZMA -D_7ZIP_ST + common-cflags += -I$(lzma) -DAVIAN_USE_LZMA -D_7ZIP_ST vm-sources += \ $(src)/lzma-decode.cpp @@ -673,7 +681,7 @@ ifneq ($(lzma),) lzma-encoder-lzma-sources = $(lzma-encode-sources) $(lzma-decode-sources) lzma-encoder-lzma-objects = \ - $(call c-objects,$(lzma-encoder-lzma-sources),$(lzma)/C,$(build)) + $(call generator-c-objects,$(lzma-encoder-lzma-sources),$(lzma)/C,$(build)) lzma-loader = $(build)/lzma/load.o endif @@ -904,7 +912,7 @@ $(test-extra-dep): $(test-extra-sources) define compile-object @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(cxx) $(cflags) -c $(<) $(call output,$(@)) + $(cxx) $(cflags) -c $$($(windows-path) $(<)) $(call output,$(@)) endef define compile-asm-object @@ -993,7 +1001,7 @@ $(generator-objects): $(generator-depends) $(generator-objects): $(build)/%-build.o: $(src)/%.cpp $(compile-generator-object) -$(generator-lzma-objects): $(build)/%-build.o: $(lzma)/C/%.c +$(build)/%-build.o: $(lzma)/C/%.c $(compile-generator-object) $(jni-objects): $(build)/%.o: $(classpath-src)/%.cpp diff --git a/src/compile.cpp b/src/compile.cpp index 86edcb033e..ce67081480 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -10022,7 +10022,7 @@ compileVirtualThunk(MyThread* t, unsigned index, unsigned* size) sprintf(RUNTIME_ARRAY_BODY(virtualThunkName), "%s%d", virtualThunkBaseName, index); - logCompile(t, start, *size, 0, virtualThunkName, 0); + logCompile(t, start, *size, 0, RUNTIME_ARRAY_BODY(virtualThunkName), 0); return reinterpret_cast(start); } diff --git a/src/lzma-decode.cpp b/src/lzma-decode.cpp index 7710934ddd..f51b86af83 100644 --- a/src/lzma-decode.cpp +++ b/src/lzma-decode.cpp @@ -9,7 +9,7 @@ details. */ #include "lzma-util.h" -#include "LzmaDec.h" +#include "C/LzmaDec.h" using namespace vm; diff --git a/src/lzma-encode.cpp b/src/lzma-encode.cpp index d1b002476a..cc7f8ad178 100644 --- a/src/lzma-encode.cpp +++ b/src/lzma-encode.cpp @@ -9,7 +9,7 @@ details. */ #include "lzma-util.h" -#include "LzmaEnc.h" +#include "C/LzmaEnc.h" using namespace vm; diff --git a/src/lzma-util.h b/src/lzma-util.h index 105a9e4077..e7fc3093a0 100644 --- a/src/lzma-util.h +++ b/src/lzma-util.h @@ -12,7 +12,7 @@ #define LZMA_UTIL_H #include "lzma.h" -#include "Types.h" +#include "C/Types.h" #include "system.h" #include "allocator.h" diff --git a/src/lzma/load.cpp b/src/lzma/load.cpp index f4fc57965c..3584c50e6a 100644 --- a/src/lzma/load.cpp +++ b/src/lzma/load.cpp @@ -2,22 +2,31 @@ #include #include #include -#include -#include #include #include #include -#include -#include "LzmaDec.h" +#include "C/LzmaDec.h" -#ifdef __MINGW32__ +#if (defined __MINGW32__) || (defined _MSC_VER) # define EXPORT __declspec(dllexport) +# include +# define open _open +# define write _write +# define close _close +# ifdef _MSC_VER +# define S_IRWXU (_S_IREAD | _S_IWRITE) +# define and && +# endif #else # define EXPORT __attribute__ ((visibility("default"))) +# include +# include +# include +# define O_BINARY 0 #endif -#if defined __MINGW32__ && ! defined __x86_64__ +#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER)) # define SYMBOL(x) binary_exe_##x #else # define SYMBOL(x) _binary_exe_##x @@ -44,6 +53,70 @@ myFree(void*, void* address) free(address); } +#if (defined __MINGW32__) || (defined _MSC_VER) + +void* +openLibrary(const char* name) +{ + return LoadLibrary(name); +} + +void* +librarySymbol(void* library, const char* name) +{ + void* address; + FARPROC p = GetProcAddress(static_cast(library), name); + memcpy(&address, &p, sizeof(void*)); + return address; +} + +const char* +libraryError(void*) +{ + return "unknown error"; +} + +const char* +temporaryFileName(char* buffer, unsigned size) +{ + unsigned c = GetTempPathA(size, buffer); + if (c) { + if (GetTempFileNameA(buffer, "223", 0, buffer + c)) { + DeleteFileA(buffer + c); + return buffer + c; + } + } + return 0; +} + +#else + +void* +openLibrary(const char* name) +{ + return dlopen(name, RTLD_LAZY | RTLD_LOCAL); +} + +void* +librarySymbol(void* library, const char* name) +{ + return dlsym(library, name); +} + +const char* +libraryError(void*) +{ + return dlerror(); +} + +const char* +temporaryFileName(char* buffer, unsigned) +{ + return tmpnam(buffer); +} + +#endif + } // namespace int @@ -67,28 +140,31 @@ main(int ac, const char** av) (out, &outSize, SYMBOL(start) + HeaderSize, &inSize, SYMBOL(start), PropHeaderSize, LZMA_FINISH_END, &status, &allocator)) { - char name[L_tmpnam]; - if (tmpnam(name)) { - int file = open(name, O_CREAT | O_EXCL | O_WRONLY, S_IRWXU); + const unsigned BufferSize = 1024; + char buffer[BufferSize]; + const char* name = temporaryFileName(buffer, BufferSize); + if (name) { + int file = open(name, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, S_IRWXU); if (file != -1) { SizeT result = write(file, out, outSize); free(out); if (close(file) == 0 and outSize == result) { - void* library = dlopen(name, RTLD_LAZY | RTLD_GLOBAL); + void* library = openLibrary(name); unlink(name); if (library) { - void* main = dlsym(library, "main"); + void* main = librarySymbol(library, "avianMain"); if (main) { - int (*mainFunction)(int, const char**); + int (*mainFunction)(const char*, int, const char**); memcpy(&mainFunction, &main, sizeof(void*)); - return mainFunction(ac, av); + return mainFunction(name, ac, av); } else { fprintf(stderr, "unable to find main in %s", name); } } else { - fprintf(stderr, "unable to dlopen %s: %s\n", name, dlerror()); + fprintf(stderr, "unable to load %s: %s\n", name, + libraryError(library)); } } else { unlink(name); diff --git a/src/machine.cpp b/src/machine.cpp index 6e242dd8b8..67f70196fe 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2925,6 +2925,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, shutdownLock(0), libraries(0), errorLog(0), + bootimage(0), types(0), roots(0), finalizers(0), From 9520b03333764c57ebc8c99ecfb38162089d77cb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 2 Jun 2012 18:56:07 -0600 Subject: [PATCH 115/140] fix OS X build regressions --- makefile | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/makefile b/makefile index de21c012b8..128ce5ffb5 100755 --- a/makefile +++ b/makefile @@ -1,7 +1,7 @@ MAKEFLAGS = -s name = avian -version = 0.5 +version = 0.6 build-arch := $(shell uname -m \ | sed 's/^i.86$$/i386/' \ @@ -206,7 +206,7 @@ converter-cflags = -D__STDC_CONSTANT_MACROS -Isrc/binaryToObject -Isrc/ \ -fno-rtti -fno-exceptions \ -DAVIAN_TARGET_ARCH=AVIAN_ARCH_UNKNOWN \ -DAVIAN_TARGET_PLATFORM=AVIAN_PLATFORM_UNKNOWN \ - -Wall -Wextra -Werror -Wunused-parameter -Winit-self + -Wall -Wextra -Werror -Wunused-parameter -Winit-self -Wno-non-virtual-dtor cflags = $(build-cflags) @@ -457,7 +457,11 @@ ifeq ($(mode),stress-major) strip = : endif ifeq ($(mode),fast) - optimization-cflags = -O4 -g3 -DNDEBUG + ifeq ($(use-clang),true) + optimization-cflags = -O4 -g3 -DNDEBUG + else + optimization-cflags = -O3 -g3 -DNDEBUG + endif use-lto = true endif ifeq ($(mode),small) @@ -925,7 +929,9 @@ $(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) $(compile-object) $(build)/%.o: $(lzma)/C/%.c - $(compile-object) + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(cxx) $(cflags) -Wno-error -c $$($(windows-path) $(<)) $(call output,$(@)) $(vm-asm-objects): $(build)/%-asm.o: $(src)/%.S $(compile-asm-object) @@ -1002,7 +1008,10 @@ $(generator-objects): $(build)/%-build.o: $(src)/%.cpp $(compile-generator-object) $(build)/%-build.o: $(lzma)/C/%.c - $(compile-generator-object) + @echo "compiling $(@)" + @mkdir -p $(dir $(@)) + $(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \ + -Wno-error -c $(<) -o $(@) $(jni-objects): $(build)/%.o: $(classpath-src)/%.cpp $(compile-object) From 84034c00a84b1f54caacee3fe962bd3f6441435c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 2 Jun 2012 18:56:15 -0600 Subject: [PATCH 116/140] use GitHub URL for hello-ios.git link --- readme.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.txt b/readme.txt index ca43b1fa9e..e9185b2c85 100644 --- a/readme.txt +++ b/readme.txt @@ -115,8 +115,8 @@ certain flags described below, all of which are optional. * ios - if true, cross-compile for iOS on OS X. Note that non-jailbroken iOS devices do not allow JIT compilation, so only process=interpret or bootimage=true builds will run on such - devices. See git://oss.readytalk.com/hello-ios.git for an example - of an Xcode project for iOS which uses Avian. + devices. See https://github.com/ReadyTalk/hello-ios for an + example of an Xcode project for iOS which uses Avian. default: false * bootimage - if true, create a boot image containing the pre-parsed From 9ea6a283830ae8b6cf0099376971add8cd550697 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 4 Jun 2012 09:51:11 -0600 Subject: [PATCH 117/140] fix MSVC build regression --- makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index 128ce5ffb5..49c82a1bcf 100755 --- a/makefile +++ b/makefile @@ -230,6 +230,8 @@ so-suffix = .so shared = -shared +no-error = -Wno-error + openjdk-extra-cflags = -fvisibility=hidden bootimage-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size) @@ -506,6 +508,7 @@ ld := $(cc) build-ld := $(build-cc) ifdef msvc + no-error = windows-path = $(native-path) windows-java-home := $(shell $(windows-path) "$(JAVA_HOME)") zlib := $(shell $(windows-path) "$(win32)/msvc") @@ -931,7 +934,7 @@ $(vm-cpp-objects): $(build)/%.o: $(src)/%.cpp $(vm-depends) $(build)/%.o: $(lzma)/C/%.c @echo "compiling $(@)" @mkdir -p $(dir $(@)) - $(cxx) $(cflags) -Wno-error -c $$($(windows-path) $(<)) $(call output,$(@)) + $(cxx) $(cflags) $(no-error) -c $$($(windows-path) $(<)) $(call output,$(@)) $(vm-asm-objects): $(build)/%-asm.o: $(src)/%.S $(compile-asm-object) @@ -1011,7 +1014,7 @@ $(build)/%-build.o: $(lzma)/C/%.c @echo "compiling $(@)" @mkdir -p $(dir $(@)) $(build-cxx) -DPOINTER_SIZE=$(pointer-size) -O0 -g3 $(build-cflags) \ - -Wno-error -c $(<) -o $(@) + $(no-error) -c $(<) -o $(@) $(jni-objects): $(build)/%.o: $(classpath-src)/%.cpp $(compile-object) From 7d8def84e0d7d11780786e6792fad3ba145e6dfa Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 4 Jun 2012 09:52:06 -0600 Subject: [PATCH 118/140] fix build on old Xcode versions --- makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index 49c82a1bcf..9514d67dcf 100755 --- a/makefile +++ b/makefile @@ -326,8 +326,12 @@ ifeq ($(platform),darwin) endif version-script-flag = - lflags = $(common-lflags) -ldl -framework CoreFoundation \ - -Wl,-compatibility_version,1.0.0 + lflags = $(common-lflags) -ldl -framework CoreFoundation + + ifeq (,$(shell ld -v | grep cctools)) + lflags += -Wl,-compatibility_version,1.0.0 + endif + ifneq ($(arch),arm) lflags += -framework CoreServices -framework SystemConfiguration \ -framework Security From 11d750af70216afaa847c43442685ea9ef0a8b02 Mon Sep 17 00:00:00 2001 From: JET Date: Mon, 4 Jun 2012 12:39:53 -0600 Subject: [PATCH 119/140] single-precision hardfloat emission working anything involving doubles (including conversions and thunking from singles) is still broken --- src/arm.cpp | 154 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 96 insertions(+), 58 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index 885a320594..739faa0bef 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -57,8 +57,8 @@ inline int SWAP(int cond, int B, int Rn, int Rd, int Rm) { return cond<<28 | 1<<24 | B<<22 | Rn<<16 | Rd<<12 | 9<<4 | Rm; } inline int COOP(int cond, int opcode_1, int CRn, int CRd, int cp_num, int opcode_2, int CRm) { return cond<<28 | 0xe<<24 | opcode_1<<20 | CRn<<16 | CRd<<12 | cp_num<<8 | opcode_2<<5 | CRm; } -inline int COXFER(int cond, int P, int U, int N, int W, int L, int Rn, int CRd, int cp_num, int offset) -{ return cond<<28 | 0x6<<25 | P<<24 | U<<23 | N<<22 | W<<21 | L<<20 | Rn<<16 | CRd<<12 | cp_num<<8 | (offset&0xff); } +inline int COXFER(int cond, int P, int U, int N, int W, int L, int Rn, int CRd, int cp_num, int offset) // offset is in words, not bytes +{ return cond<<28 | 0x6<<25 | P<<24 | U<<23 | N<<22 | W<<21 | L<<20 | Rn<<16 | CRd<<12 | cp_num<<8 | (offset&0xff)>>2; } inline int COREG(int cond, int opcode_1, int L, int CRn, int Rd, int cp_num, int opcode_2, int CRm) { return cond<<28 | 0xe<<24 | opcode_1<<21 | L<<20 | CRn<<16 | Rd<<12 | cp_num<<8 | opcode_2<<5 | 1<<4 | CRm; } inline int COREG2(int cond, int L, int Rn, int Rd, int cp_num, int opcode, int CRm) @@ -270,14 +270,17 @@ const int N_GPRS = 16; const int N_FPRS = 16; const uint32_t GPR_MASK = 0xffff; const uint32_t FPR_MASK = 0xffff0000; +// for source-to-destination masks +const uint64_t GPR_MASK64 = GPR_MASK | (uint64_t)GPR_MASK << 32; +// making the following const somehow breaks debug symbol output in GDB +/* const */ uint64_t FPR_MASK64 = FPR_MASK | (uint64_t)FPR_MASK << 32; inline bool isFpr(Assembler::Register* reg) { return reg->low >= N_GPRS; } -inline int toFpr(Assembler::Register* reg) { - return reg->low - N_GPRS; -} +inline int fpr(Assembler::Register* reg) { return reg->low - N_GPRS; } +inline int fpr(int reg) { return reg - N_GPRS; } const unsigned FrameHeaderSize = 1; @@ -584,7 +587,7 @@ using namespace isa; inline void emit(Context* con, int code) { con->code.append4(code); } inline int newTemp(Context* con) { - return con->client->acquireTemporary(); + return con->client->acquireTemporary(GPR_MASK); } inline int newTemp(Context* con, unsigned mask) { @@ -920,13 +923,12 @@ moveRR(Context* con, unsigned srcSize, Assembler::Register* src, bool srcIsFpr = isFpr(src); bool dstIsFpr = isFpr(dst); if (srcIsFpr || dstIsFpr) { // floating-point register(s) involved - /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> %d <- %d\n", dst->low, src->low); // FPR to FPR - if (srcIsFpr && dstIsFpr) emit(con, fcpys(toFpr(dst), toFpr(src))); + if (srcIsFpr && dstIsFpr) emit(con, fcpys(fpr(dst), fpr(src))); // FPR to GPR - else if (srcIsFpr) emit(con, fmrs(dst->low, toFpr(src))); + else if (srcIsFpr) emit(con, fmrs(dst->low, fpr(src))); // GPR to FPR - else emit(con, fmsr(toFpr(dst), src->low)); + else emit(con, fmsr(fpr(dst), src->low)); return; } @@ -990,7 +992,6 @@ moveCR2(Context* con, unsigned size, Assembler::Constant* src, { if (isFpr(dst)) { // floating-point Assembler::Register tmp = makeTemp(con); - /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> %d <- 0x%llx\n", tmp.low, getValue(src)); moveCR2(con, size, src, &tmp, 0); moveRR(con, size, &tmp, size, dst); freeTemp(con, tmp); @@ -1096,88 +1097,86 @@ void multiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::R void floatAbsoluteRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { if (size == 8) { - emit(con, fabsd(b->low, a->low)); + emit(con, fabsd(fpr(b), fpr(a))); } else { - emit(con, fabss(b->low, a->low)); + emit(con, fabss(fpr(b), fpr(a))); } } void floatNegateRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { if (size == 8) { - /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> invalid 64-bit Scheiße\n"); - emit(con, fnegd(b->low, a->low)); + emit(con, fnegd(fpr(b), fpr(a))); } else { - /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> %d <- -%d\n", b->low, a->low); - emit(con, fnegs(b->low, a->low)); + emit(con, fnegs(fpr(b), fpr(a))); } } void float2FloatRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { if (size == 8) { - emit(con, fcvtsd(b->low, a->low)); + emit(con, fcvtsd(fpr(b), fpr(a))); } else { - emit(con, fcvtds(b->low, a->low)); + emit(con, fcvtds(fpr(b), fpr(a))); } } void float2IntRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { int tmp = newTemp(con, FPR_MASK); + int ftmp = fpr(tmp); if (size == 8) { // double to int - emit(con, ftosid(tmp, a->low)); + emit(con, ftosizd(ftmp, fpr(a))); } else { // float to int - emit(con, ftosis(tmp, a->low)); + emit(con, ftosizs(ftmp, fpr(a))); } // else thunked - emit(con, fmrs(b->low, tmp)); + emit(con, fmrs(b->low, ftmp)); freeTemp(con, tmp); } void int2FloatRR(Context* con, unsigned UNUSED, Assembler::Register* a, unsigned size, Assembler::Register* b) { - emit(con, fmsr(b->low, a->low)); + emit(con, fmsr(fpr(b), a->low)); if (size == 8) { // int to double - emit(con, fsitod(b->low, b->low)); + emit(con, fsitod(fpr(b), fpr(b))); } else { // int to float - emit(con, fsitos(b->low, b->low)); + emit(con, fsitos(fpr(b), fpr(b))); } // else thunked } void floatSqrtRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { - if (size == 8) { - emit(con, fsqrtd(b->low, a->low)); + if (size == 8) { + emit(con, fsqrtd(fpr(b), fpr(a))); } else { - emit(con, fsqrts(b->low, a->low)); + emit(con, fsqrts(fpr(b), fpr(a))); } } void floatAddR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { - if (size == 8) { - emit(con, faddd(t->low, a->low, b->low)); + if (size == 8) { + emit(con, faddd(fpr(t), fpr(a), fpr(b))); } else { - fprintf(stderr, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ %d <- %d + %d\n", toFpr(t), toFpr(a), toFpr(b)); - emit(con, fadds(toFpr(t), toFpr(a), toFpr(b))); + emit(con, fadds(fpr(t), fpr(a), fpr(b))); } } void floatSubtractR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { - if (size == 8) { - emit(con, fsubd(t->low, a->low, b->low)); + if (size == 8) { + emit(con, fsubd(fpr(t), fpr(b), fpr(a))); } else { - emit(con, fsubs(t->low, a->low, b->low)); + emit(con, fsubs(fpr(t), fpr(b), fpr(a))); } } void floatMultiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { if (size == 8) { - emit(con, fmuld(t->low, a->low, b->low)); + emit(con, fmuld(fpr(t), fpr(a), fpr(b))); } else { - emit(con, fmuls(t->low, a->low, b->low)); + emit(con, fmuls(fpr(t), fpr(a), fpr(b))); } } void floatDivideR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { if (size == 8) { - emit(con, fdivd(t->low, a->low, b->low)); + emit(con, fdivd(fpr(t), fpr(b), fpr(a))); } else { - emit(con, fdivs(t->low, a->low, b->low)); + emit(con, fdivs(fpr(t), fpr(b), fpr(a))); } } @@ -1242,12 +1241,11 @@ store(Context* con, unsigned size, Assembler::Register* src, if (isFpr(src)) { // floating-point store if (size == 4) { - /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> fpr store base-indexed\n"); Assembler::Register base_(base), normalized_(normalized), absAddr = makeTemp(con); addR(con, size, &base_, &normalized_, &absAddr); - emit(con, fsts(toFpr(src), absAddr.low)); + emit(con, fsts(fpr(src), absAddr.low)); freeTemp(con, absAddr); } else abort(con); @@ -1281,8 +1279,7 @@ store(Context* con, unsigned size, Assembler::Register* src, or (size != 2 and abs(offset) == (abs(offset) & 0xFFF))) { if (isFpr(src)) { - /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> [%d + 0x%x] <- %d\n", base, offset, src->low); - if (size == 4) emit(con, fsts(toFpr(src), base, offset)); + if (size == 4) emit(con, fsts(fpr(src), base, offset)); else abort(con); } else { switch (size) { @@ -1358,12 +1355,11 @@ load(Context* con, unsigned srcSize, int base, int offset, int index, if (isFpr(dst)) { // floating-point store if (srcSize == 4) { - /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> fpr load base-indexed\n"); Assembler::Register base_(base), normalized_(normalized), absAddr = makeTemp(con); addR(con, srcSize, &base_, &normalized_, &absAddr); - emit(con, flds(toFpr(dst), absAddr.low)); + emit(con, flds(fpr(dst), absAddr.low)); freeTemp(con, absAddr); } else abort(con); @@ -1414,8 +1410,7 @@ load(Context* con, unsigned srcSize, int base, int offset, int index, and abs(offset) == (abs(offset) & 0xFFF))) { if (isFpr(dst)) { - /**/fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>> %d <- [%d + 0x%x]\n", dst->low, base, offset); - if (srcSize == 4) emit(con, flds(toFpr(dst), base, offset)); + if (srcSize == 4) emit(con, flds(fpr(dst), base, offset)); else abort(con); } else { switch (srcSize) { @@ -1581,14 +1576,15 @@ compareRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, unsigned bSize UNUSED, Assembler::Register* b) { assert(c, aSize == 4 and bSize == 4); - assert(c, b->low != a->low); assert(c, !(isFpr(a) ^ isFpr(b))); if (isFpr(a)) { - emit(c, fcmps(toFpr(b), toFpr(a))); + emit(c, fcmps(fpr(b), fpr(a))); emit(c, fmstat()); + } else { + assert(c, b->low != a->low); + emit(c, cmp(b->low, a->low)); } - else emit(c, cmp(b->low, a->low)); } void @@ -1699,6 +1695,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, switch (op) { case JumpIfEqual: + case JumpIfFloatEqual: next = c->code.length(); emit(c, bne(0)); @@ -1707,6 +1704,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, break; case JumpIfNotEqual: + case JumpIfFloatNotEqual: conditional(c, bne(0), target); compareSigned(c, 4, al, 4, bl); @@ -1714,6 +1712,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, break; case JumpIfLess: + case JumpIfFloatLess: conditional(c, blt(0), target); next = c->code.length(); @@ -1724,6 +1723,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, break; case JumpIfGreater: + case JumpIfFloatGreater: conditional(c, bgt(0), target); next = c->code.length(); @@ -1734,6 +1734,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, break; case JumpIfLessOrEqual: + case JumpIfFloatLessOrEqual: conditional(c, blt(0), target); next = c->code.length(); @@ -1744,6 +1745,7 @@ branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, break; case JumpIfGreaterOrEqual: + case JumpIfFloatGreaterOrEqual: conditional(c, bgt(0), target); next = c->code.length(); @@ -2326,13 +2328,16 @@ class MyArchitecture: public Assembler::Architecture { break; case Absolute: + *thunk = true; + break; + case FloatAbsolute: case FloatSquareRoot: case FloatNegate: case Float2Float: if (vfpSupported()) { *aTypeMask = (1 << RegisterOperand); - *aRegisterMask = FPR_MASK; + *aRegisterMask = FPR_MASK64; } else { *thunk = true; } @@ -2341,7 +2346,7 @@ class MyArchitecture: public Assembler::Architecture { case Float2Int: if (vfpSupported() && bSize == 4 && aSize == 4) { *aTypeMask = (1 << RegisterOperand); - *aRegisterMask = FPR_MASK; + *aRegisterMask = FPR_MASK64; } else { *thunk = true; } @@ -2350,7 +2355,7 @@ class MyArchitecture: public Assembler::Architecture { case Int2Float: if (vfpSupported() && aSize == 4 && bSize == 4) { *aTypeMask = (1 << RegisterOperand); - *aRegisterMask = FPR_MASK; + *aRegisterMask = GPR_MASK64; } else { *thunk = true; } @@ -2363,8 +2368,8 @@ class MyArchitecture: public Assembler::Architecture { virtual void planDestination (BinaryOperation op, - unsigned, uint8_t, uint64_t, - unsigned, uint8_t* bTypeMask, uint64_t* bRegisterMask) + unsigned, uint8_t aTypeMask, uint64_t, + unsigned , uint8_t* bTypeMask, uint64_t* bRegisterMask) { *bTypeMask = (1 << RegisterOperand) | (1 << MemoryOperand); *bRegisterMask = ~static_cast(0); @@ -2374,6 +2379,26 @@ class MyArchitecture: public Assembler::Architecture { *bTypeMask = (1 << RegisterOperand); break; + case FloatAbsolute: + case FloatSquareRoot: + case FloatNegate: + case Float2Float: + case Int2Float: + *bTypeMask = (1 << RegisterOperand); + *bRegisterMask = FPR_MASK64; + break; + + case Float2Int: + *bTypeMask = (1 << RegisterOperand); + *bRegisterMask = GPR_MASK64; + break; + + case Move: + if (!(aTypeMask & 1 << RegisterOperand)) { + *bTypeMask = 1 << RegisterOperand; + } + break; + default: break; } @@ -2382,7 +2407,7 @@ class MyArchitecture: public Assembler::Architecture { virtual void planMove (unsigned, uint8_t* srcTypeMask, uint64_t* srcRegisterMask, uint8_t* tmpTypeMask, uint64_t* tmpRegisterMask, - uint8_t dstTypeMask, uint64_t) + uint8_t dstTypeMask, uint64_t dstRegisterMask) { *srcTypeMask = ~0; *srcRegisterMask = ~static_cast(0); @@ -2394,6 +2419,11 @@ class MyArchitecture: public Assembler::Architecture { // can't move directly from memory or constant to memory *srcTypeMask = 1 << RegisterOperand; *tmpTypeMask = 1 << RegisterOperand; + *tmpRegisterMask = GPR_MASK64; + } else if (dstTypeMask & 1 << RegisterOperand && + dstRegisterMask & FPR_MASK) { + *srcTypeMask = *tmpTypeMask = 1 << RegisterOperand | + 1 << MemoryOperand; *tmpRegisterMask = ~static_cast(0); } } @@ -2429,6 +2459,7 @@ class MyArchitecture: public Assembler::Architecture { case Divide: case Remainder: + case FloatRemainder: *thunk = true; break; @@ -2436,7 +2467,14 @@ class MyArchitecture: public Assembler::Architecture { case FloatSubtract: case FloatMultiply: case FloatDivide: - case FloatRemainder: + if (vfpSupported()) { + *aTypeMask = *bTypeMask = (1 << RegisterOperand); + *aRegisterMask = *bRegisterMask = FPR_MASK64; + } else { + *thunk = true; + } + break; + case JumpIfFloatEqual: case JumpIfFloatNotEqual: case JumpIfFloatLess: @@ -2449,7 +2487,7 @@ class MyArchitecture: public Assembler::Architecture { case JumpIfFloatGreaterOrEqualOrUnordered: if (vfpSupported()) { *aTypeMask = *bTypeMask = (1 << RegisterOperand); - *aRegisterMask = *bRegisterMask = FPR_MASK; + *aRegisterMask = *bRegisterMask = FPR_MASK64; } else { *thunk = true; } From f6299fdfe613a9d24ac709f7170ef511693f1ebc Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 5 Jun 2012 13:33:29 -0600 Subject: [PATCH 120/140] fix bootimage build regression --- src/bootimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 2affc13f6f..8d5afff495 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -2022,7 +2022,7 @@ main(int ac, const char** av) reinterpret_cast(args.bootimageEnd), reinterpret_cast(args.codeimageStart), reinterpret_cast(args.codeimageEnd), - reinterpret_cast(args.useLZMA) + static_cast(args.useLZMA) }; run(t, writeBootImage, arguments); From ba6ca031bbe04a226d5a520403622fd84c1be45e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 5 Jun 2012 13:53:13 -0600 Subject: [PATCH 121/140] fix handling of no-argument options in bootimage.cpp --- src/bootimage.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 8d5afff495..8d403d0745 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1769,8 +1769,10 @@ bool ArgParser::parse(int ac, const char** av) { fprintf(stderr, "expected -parameter\n"); return false; } + bool found = false; for(Arg* arg = first; arg; arg = arg->next) { if(strcmp(arg->name, &av[i][1]) == 0) { + found = true; if (arg->desc == 0) { arg->value = "true"; } else { @@ -1778,7 +1780,7 @@ bool ArgParser::parse(int ac, const char** av) { } } } - if(!state) { + if (not found) { fprintf(stderr, "unrecognized parameter %s\n", av[i]); return false; } @@ -1806,8 +1808,10 @@ void ArgParser::printUsage(const char* exe) { const char* lineEnd = arg->next ? " \\" : ""; if(arg->required) { fprintf(stderr, " -%s\t%s%s\n", arg->name, arg->desc, lineEnd); - } else { + } else if (arg->desc) { fprintf(stderr, " [-%s\t%s]%s\n", arg->name, arg->desc, lineEnd); + } else { + fprintf(stderr, " [-%s]%s\n", arg->name, lineEnd); } } } From 165986841e6c34da8c08d34db01967d1e992e2f8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 6 Jun 2012 12:58:24 -0600 Subject: [PATCH 122/140] fix endianess bug in LZMA decoding --- makefile | 2 +- src/lzma-decode.cpp | 16 ++++++++++++++-- src/lzma/load.cpp | 12 ++++++++++-- src/lzma/main.cpp | 12 ++++++++++-- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/makefile b/makefile index 9514d67dcf..6e5f439d2f 100755 --- a/makefile +++ b/makefile @@ -328,7 +328,7 @@ ifeq ($(platform),darwin) version-script-flag = lflags = $(common-lflags) -ldl -framework CoreFoundation - ifeq (,$(shell ld -v | grep cctools)) + ifeq (,$(shell ld -v 2>&1 | grep cctools)) lflags += -Wl,-compatibility_version,1.0.0 endif diff --git a/src/lzma-decode.cpp b/src/lzma-decode.cpp index f51b86af83..874e6f584d 100644 --- a/src/lzma-decode.cpp +++ b/src/lzma-decode.cpp @@ -13,6 +13,19 @@ using namespace vm; +namespace { + +int32_t +read4(const uint8_t* in) +{ + return (static_cast(in[3]) << 24) + | (static_cast(in[2]) << 16) + | (static_cast(in[1]) << 8) + | (static_cast(in[0]) ); +} + +} // namespace + namespace vm { uint8_t* @@ -22,8 +35,7 @@ decodeLZMA(System* s, Allocator* a, uint8_t* in, unsigned inSize, const unsigned PropHeaderSize = 5; const unsigned HeaderSize = 13; - int32_t outSize32; - memcpy(&outSize32, in + PropHeaderSize, 4); + int32_t outSize32 = read4(in + PropHeaderSize); expect(s, outSize32 >= 0); SizeT outSizeT = outSize32; diff --git a/src/lzma/load.cpp b/src/lzma/load.cpp index 3584c50e6a..4a68466772 100644 --- a/src/lzma/load.cpp +++ b/src/lzma/load.cpp @@ -41,6 +41,15 @@ extern "C" { namespace { +int32_t +read4(const uint8_t* in) +{ + return (static_cast(in[3]) << 24) + | (static_cast(in[2]) << 16) + | (static_cast(in[1]) << 8) + | (static_cast(in[0]) ); +} + void* myAllocate(void*, size_t size) { @@ -127,8 +136,7 @@ main(int ac, const char** av) SizeT inSize = SYMBOL(end) - SYMBOL(start); - int32_t outSize32; - memcpy(&outSize32, SYMBOL(start) + PropHeaderSize, 4); + int32_t outSize32 = read4(SYMBOL(start) + PropHeaderSize); SizeT outSize = outSize32; uint8_t* out = static_cast(malloc(outSize)); diff --git a/src/lzma/main.cpp b/src/lzma/main.cpp index a9a558d897..f6baa39bb9 100644 --- a/src/lzma/main.cpp +++ b/src/lzma/main.cpp @@ -17,6 +17,15 @@ namespace { +int32_t +read4(const uint8_t* in) +{ + return (static_cast(in[3]) << 24) + | (static_cast(in[2]) << 16) + | (static_cast(in[1]) << 8) + | (static_cast(in[0]) ); +} + void* myAllocate(void*, size_t size) { @@ -100,8 +109,7 @@ main(int argc, const char** argv) if (encode) { outSize = size * 2; } else { - int32_t outSize32; - memcpy(&outSize32, data + PropHeaderSize, 4); + int32_t outSize32 = read4(data + PropHeaderSize); if (outSize32 >= 0) { outSize = outSize32; } else if (argc == 5) { From fa8ba2afc859a764ef38c79a5c5ccaafdb532510 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 11 Jun 2012 23:30:22 +0000 Subject: [PATCH 123/140] fix build for recent versions of OpenJDK 7 As of the latest code from the jdk7u-dev Mercurial repository, java.lang.String no longer has offset or length fields. Instead, the content fits exactly into the backing char array, so offset is implicitly zero and length is the length of the array. The VM previously relied on those fields being present, whereas this commit handles the case where they are not. In addition, I've made some changes to openjdk-src.mk to ensure that we can build against both a stock OpenJDK 7 and an IcedTea-patched version. --- openjdk-src.mk | 15 +++++++-------- src/classpath-openjdk.cpp | 16 ++++++++-------- src/machine.h | 33 +++++++++++++++++++++++++++++++++ src/type-generator.cpp | 5 +++++ 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/openjdk-src.mk b/openjdk-src.mk index 027b6a79b5..fbbce2e5e8 100644 --- a/openjdk-src.mk +++ b/openjdk-src.mk @@ -239,8 +239,7 @@ ifeq ($(platform),windows) -Ds6_bytes=_s6_bytes else openjdk-sources += \ - $(openjdk-src)/solaris/native/common/jdk_util_md.c \ - $(openjdk-src)/solaris/native/common/jni_util_md.c \ + $(shell find $(openjdk-src)/solaris/native/common -name '*.c') \ $(openjdk-src)/solaris/native/java/io/canonicalize_md.c \ $(openjdk-src)/solaris/native/java/io/Console_md.c \ $(openjdk-src)/solaris/native/java/io/FileDescriptor_md.c \ @@ -305,9 +304,6 @@ else ifeq ($(platform),linux) openjdk-sources += \ $(openjdk-src)/solaris/native/java/net/linux_close.c \ - $(openjdk-src)/solaris/native/common/deps/syscalls_fp.c \ - $(openjdk-src)/solaris/native/common/deps/gconf2/gconf_fp.c \ - $(openjdk-src)/solaris/native/common/deps/glib2/gio_fp.c \ $(openjdk-src)/solaris/native/sun/nio/ch/EPollArrayWrapper.c openjdk-headers-classes += \ @@ -316,6 +312,8 @@ else openjdk-cflags += \ "-I$(openjdk-src)/solaris/native/common/deps/glib2" \ "-I$(openjdk-src)/solaris/native/common/deps/gconf2" \ + "-I$(openjdk-src)/solaris/native/common/deps/fontconfig2" \ + "-I$(openjdk-src)/solaris/native/common/deps/gtk2" \ $(shell pkg-config --cflags glib-2.0) \ $(shell pkg-config --cflags gconf-2.0) endif @@ -341,12 +339,13 @@ openjdk-local-sources += \ $(src)/openjdk/my_net_util.c \ $(src)/openjdk/my_management.c -c-objects = $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%-openjdk.o,$(x))) +openjdk-c-objects = \ + $(foreach x,$(1),$(patsubst $(2)/%.c,$(3)/%-openjdk.o,$(x))) openjdk-objects = \ - $(call c-objects,$(openjdk-sources),$(openjdk-src),$(build)/openjdk) + $(call openjdk-c-objects,$(openjdk-sources),$(openjdk-src),$(build)/openjdk) openjdk-local-objects = \ - $(call c-objects,$(openjdk-local-sources),$(src)/openjdk,$(build)/openjdk) + $(call openjdk-c-objects,$(openjdk-local-sources),$(src)/openjdk,$(build)/openjdk) openjdk-headers-dep = $(build)/openjdk/headers.dep diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index fe9dbfdbfb..e05a71260e 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -562,6 +562,14 @@ class MyClasspath : public Classpath { expect(t, loadLibrary(t, libraryPath, "java", true, true)); #endif // not AVIAN_OPENJDK_SRC + { object assertionLock = resolveField + (t, type(t, Machine::ClassLoaderType), "assertionLock", + "Ljava/lang/Object;"); + + set(t, root(t, Machine::BootLoader), fieldOffset(t, assertionLock), + root(t, Machine::BootLoader)); + } + { object class_ = resolveClass (t, root(t, Machine::BootLoader), "java/util/Properties", true, Machine::NoClassDefFoundErrorType); @@ -594,14 +602,6 @@ class MyClasspath : public Classpath { root(t, Machine::BootLoader)); } - { object assertionLock = resolveField - (t, type(t, Machine::ClassLoaderType), "assertionLock", - "Ljava/lang/Object;"); - - set(t, root(t, Machine::BootLoader), fieldOffset(t, assertionLock), - root(t, Machine::BootLoader)); - } - { object scl = resolveField (t, type(t, Machine::ClassLoaderType), "scl", "Ljava/lang/ClassLoader;"); diff --git a/src/machine.h b/src/machine.h index bb3b97a43c..9671d6cf7c 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2233,6 +2233,39 @@ makeByteArray(Thread* t, const char* format, ...); object makeString(Thread* t, const char* format, ...); +#ifndef HAVE_StringOffset + +inline unsigned +stringLength(Thread* t, object string) +{ + return arrayLength(t, stringData(t, string)); +} + +inline unsigned +stringOffset(Thread*, object) +{ + return 0; +} + +inline object +makeString(Thread* t, object data, unsigned offset, unsigned length, unsigned) +{ + if (offset == 0 and length == arrayLength(t, data)) { + return makeString(t, data, 0, 0); + } else { + PROTECT(t, data); + + object array = makeCharArray(t, length); + + memcpy(&charArrayBody(t, array, 0), &charArrayBody(t, data, offset), + length * 2); + + return makeString(t, array, 0, 0); + } +} + +#endif // not HAVE_StringOffset + int stringUTFLength(Thread* t, object string, unsigned start, unsigned length); diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 813cce7dcd..f31b0f18c8 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -1384,6 +1384,11 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false) out->write(" = "); writeOffset(out, offset); out->write(";\n\n"); + + out->write("#define HAVE_"); + out->write(capitalize(local::typeName(memberOwner(member)))); + out->write(capitalize(memberName(member))); + out->write(" 1\n\n"); } out->write("inline "); From 06f7746dfd169cd3341f6d372598fb56c005283c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 12 Jun 2012 16:32:27 -0600 Subject: [PATCH 124/140] fix mode=debug build for recent OpenJDK versions --- src/machine.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/machine.h b/src/machine.h index 9671d6cf7c..b20913cd65 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2238,7 +2238,7 @@ makeString(Thread* t, const char* format, ...); inline unsigned stringLength(Thread* t, object string) { - return arrayLength(t, stringData(t, string)); + return charArrayLength(t, stringData(t, string)); } inline unsigned @@ -2250,7 +2250,7 @@ stringOffset(Thread*, object) inline object makeString(Thread* t, object data, unsigned offset, unsigned length, unsigned) { - if (offset == 0 and length == arrayLength(t, data)) { + if (offset == 0 and length == charArrayLength(t, data)) { return makeString(t, data, 0, 0); } else { PROTECT(t, data); From 9dd3d0432466fc0cea036e460dcc726d78e55a70 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 12 Jun 2012 16:32:53 -0600 Subject: [PATCH 125/140] fix unused parameter warning in interpret.cpp --- src/interpret.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interpret.cpp b/src/interpret.cpp index 6a66c1778b..c36ebde450 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -3067,7 +3067,7 @@ class MyProcessor: public Processor { abort(s); } - virtual void addCompilationHandler(CompilationHandler* handler) { + virtual void addCompilationHandler(CompilationHandler*) { abort(s); } From 7bfb5a62873d4e11ee8a3fa9da759d5bd8006d15 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 12 Jun 2012 16:33:31 -0600 Subject: [PATCH 126/140] fix native method name ambiguity sun.misc.Unsafe now has two native getByte methods: one which takes a long and another which takes an Object and a long. Thus, we need to decorate each version with its parameter signature so we don't accidentally call the wrong one at runtime. --- src/classpath-openjdk.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index e05a71260e..33c7095807 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2591,7 +2591,7 @@ Avian_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF } extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_getByte +Avian_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J (Thread*, object, uintptr_t* arguments) { object o = reinterpret_cast(arguments[1]); @@ -2601,14 +2601,15 @@ Avian_sun_misc_Unsafe_getByte } extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_getBoolean +Avian_sun_misc_Unsafe_getBoolean__Ljava_lang_Object_2J (Thread* t, object method, uintptr_t* arguments) { - return Avian_sun_misc_Unsafe_getByte(t, method, arguments); + return Avian_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J + (t, method, arguments); } extern "C" JNIEXPORT void JNICALL -Avian_sun_misc_Unsafe_putBoolean +Avian_sun_misc_Unsafe_putBoolean__Ljava_lang_Object_2JZ (Thread*, object, uintptr_t* arguments) { object o = reinterpret_cast(arguments[1]); From f0c4762ded9e91f3d5153d3fad57d254c18d60c6 Mon Sep 17 00:00:00 2001 From: JET Date: Tue, 12 Jun 2012 17:00:45 -0600 Subject: [PATCH 127/140] ARM VFP support: Almost finished. All but one test (and just one line therein) are passing. Several quirks and optimizations must also be addressed. --- src/arm.cpp | 951 +++++++++++++++++++++++++++------------------------- 1 file changed, 494 insertions(+), 457 deletions(-) diff --git a/src/arm.cpp b/src/arm.cpp index 739faa0bef..4f7c74b7d4 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -177,10 +177,12 @@ inline int fcpyd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 2, Dm); } inline int fabsd(int Dd, int Dm) { return COOP(AL, 0xb, 0, Dd, 11, 6, Dm); } inline int fnegd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 2, Dm); } inline int fsqrtd(int Dd, int Dm) { return COOP(AL, 0xb, 1, Dd, 11, 6, Dm); } +// double-precision comparison instructions inline int fcmpd(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 2, Dm); } inline int fcmped(int Dd, int Dm) { return COOP(AL, 0xb, 4, Dd, 11, 6, Dm); } inline int fcmpzd(int Dd) { return COOP(AL, 0xb, 5, Dd, 11, 2, 0); } inline int fcmpezd(int Dd) { return COOP(AL, 0xb, 5, Dd, 11, 6, 0); } +// double-precision conversion instructions inline int fcvtsd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 7, Sd>>1, 11, 6, Dm); } inline int fuitod(int Dd, int Sm) { return COOP(AL, 0xb, 8, Dd, 11, 2|(Sm&1), Sm>>1); } inline int fsitod(int Dd, int Sm) { return COOP(AL, 0xb, 8, Dd, 11, 6|(Sm&1), Sm>>1); } @@ -188,24 +190,31 @@ inline int ftouid(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 1 inline int ftouizd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xc, Sd>>1, 11, 6, Dm); } inline int ftosid(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 11, 2, Dm); } inline int ftosizd(int Sd, int Dm) { return COOP(AL, 0xb|(Sd&1)<<2, 0xd, Sd>>1, 11, 6, Dm); } +// these are the multiple load/store analogs for VFP, useless for now inline int fldms(int Rn, int Sd, int count) { return COXFER(AL, 0, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, count); } inline int fldmd(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, count<<1); } inline int fldmx(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 1, Rn, Dd, 11, count<<1|1); } inline int fstms(int Rn, int Sd, int count) { return COXFER(AL, 0, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, count); } inline int fstmd(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 0, Rn, Dd, 11, count<<1); } inline int fstmx(int Rn, int Dd, int count) { return COXFER(AL, 0, 1, 0, 0, 0, Rn, Dd, 11, count<<1|1); } +// single load/store instructions for both precision types inline int flds(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 1, Rn, Sd>>1, 10, offset); }; inline int fldd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 1, Rn, Dd, 11, offset); }; inline int fsts(int Sd, int Rn, int offset=0) { return COXFER(AL, 1, 1, Sd&1, 0, 0, Rn, Sd>>1, 10, offset); }; inline int fstd(int Dd, int Rn, int offset=0) { return COXFER(AL, 1, 1, 0, 0, 0, Rn, Dd, 11, offset); }; +// move between GPRs and FPRs inline int fmsr(int Sn, int Rd) { return mcr(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); } inline int fmrs(int Rd, int Sn) { return mrc(10, 0, Rd, Sn>>1, 0, (Sn&1)<<2); } +/* move to/from the low/high parts of double-precision registers, + seemingly redundant */ inline int fmdlr(int Dn, int Rd) { return mcr(11, 0, Rd, Dn, 0); } inline int fmrdl(int Rd, int Dn) { return mrc(11, 0, Rd, Dn, 0); } inline int fmdhr(int Dn, int Rd) { return mcr(11, 1, Rd, Dn, 0); } inline int fmrdh(int Rd, int Dn) { return mrc(11, 1, Rd, Dn, 0); } +// move to/from VFP system registers inline int fmxr(int reg, int Rd) { return mcr(10, 7, Rd, reg, 0); } inline int fmrx(int Rd, int reg) { return mrc(10, 7, Rd, reg, 0); } +// these move around pairs of single-precision registers inline int fmsrr(int Sm, int Rd, int Rn) { return mcrr(10, 1 | ((Sm&1)<<1), Rd, Rn, Sm>>1); } inline int fmrrs(int Rd, int Rn, int Sm) { return mrrc(10, 1 | ((Sm&1)<<1), Rd, Rn, Sm>>1); } inline int fmdrr(int Dm, int Rd, int Rn) { return mcrr(11, 1, Rd, Rn, Dm); } @@ -279,8 +288,10 @@ inline bool isFpr(Assembler::Register* reg) { return reg->low >= N_GPRS; } -inline int fpr(Assembler::Register* reg) { return reg->low - N_GPRS; } -inline int fpr(int reg) { return reg - N_GPRS; } +inline int fpr64(int reg) { return reg - N_GPRS; } +inline int fpr64(Assembler::Register* reg) { return fpr64(reg->low); } +inline int fpr32(int reg) { return fpr64(reg) << 1; } +inline int fpr32(Assembler::Register* reg) { return fpr64(reg) << 1; } const unsigned FrameHeaderSize = 1; @@ -368,7 +379,7 @@ class Task { public: Task(Task* next): next(next) { } - virtual void run(Context* c) = 0; + virtual void run(Context* con) = 0; Task* next; }; @@ -405,41 +416,41 @@ class ArchitectureContext { }; inline void NO_RETURN -abort(Context* c) +abort(Context* con) { - abort(c->s); + abort(con->s); } inline void NO_RETURN -abort(ArchitectureContext* c) +abort(ArchitectureContext* con) { - abort(c->s); + abort(con->s); } #ifndef NDEBUG inline void -assert(Context* c, bool v) +assert(Context* con, bool v) { - assert(c->s, v); + assert(con->s, v); } inline void -assert(ArchitectureContext* c, bool v) +assert(ArchitectureContext* con, bool v) { - assert(c->s, v); + assert(con->s, v); } #endif // not NDEBUG inline void -expect(Context* c, bool v) +expect(Context* con, bool v) { - expect(c->s, v); + expect(con->s, v); } class Offset: public Promise { public: - Offset(Context* c, MyBlock* block, unsigned offset, bool forTrace): - c(c), block(block), offset(offset), forTrace(forTrace) + Offset(Context* con, MyBlock* block, unsigned offset, bool forTrace): + con(con), block(block), offset(offset), forTrace(forTrace) { } virtual bool resolved() { @@ -447,23 +458,23 @@ class Offset: public Promise { } virtual int64_t value() { - assert(c, resolved()); + assert(con, resolved()); unsigned o = offset - block->offset; return block->start + padding (block, forTrace ? o - TargetBytesPerWord : o) + o; } - Context* c; + Context* con; MyBlock* block; unsigned offset; bool forTrace; }; Promise* -offset(Context* c, bool forTrace = false) +offset(Context* con, bool forTrace = false) { - return new(c->zone) Offset(c, c->lastBlock, c->code.length(), forTrace); + return new(con->zone) Offset(con, con->lastBlock, con->code.length(), forTrace); } bool @@ -513,13 +524,13 @@ class OffsetTask: public Task { instructionOffset(instructionOffset) { } - virtual void run(Context* c) { + virtual void run(Context* con) { if (promise->resolved()) { updateOffset - (c->s, c->result + instructionOffset->value(), promise->value()); + (con->s, con->result + instructionOffset->value(), promise->value()); } else { new (promise->listen(sizeof(OffsetListener))) - OffsetListener(c->s, c->result + instructionOffset->value()); + OffsetListener(con->s, con->result + instructionOffset->value()); } } @@ -528,9 +539,9 @@ class OffsetTask: public Task { }; void -appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset) +appendOffsetTask(Context* con, Promise* promise, Promise* instructionOffset) { - c->tasks = new(c->zone) OffsetTask(c->tasks, promise, instructionOffset); + con->tasks = new(con->zone) OffsetTask(con->tasks, promise, instructionOffset); } inline unsigned @@ -563,17 +574,17 @@ isFloatBranch(TernaryOperation op) } inline unsigned -index(ArchitectureContext* c UNUSED, +index(ArchitectureContext* con UNUSED, TernaryOperation operation, OperandType operand1) { - assert(c, not isBranch(operation)); + assert(con, not isBranch(operation)); return operation + (NonBranchTernaryOperationCount * operand1); } unsigned -branchIndex(ArchitectureContext* c UNUSED, OperandType operand1, +branchIndex(ArchitectureContext* con UNUSED, OperandType operand1, OperandType operand2) { return operand1 + (OperandTypeCount * operand2); @@ -598,8 +609,8 @@ inline void freeTemp(Context* con, int r) { con->client->releaseTemporary(r); } -inline int64_t getValue(Assembler::Constant* c) { - return c->value->value(); +inline int64_t getValue(Assembler::Constant* con) { + return con->value->value(); } inline Assembler::Register makeTemp(Context* con) { @@ -693,14 +704,14 @@ void unsignedShiftRightC(Context* con, unsigned size UNUSED, Assembler::Constant class ConstantPoolEntry: public Promise { public: - ConstantPoolEntry(Context* c, Promise* constant, ConstantPoolEntry* next, + ConstantPoolEntry(Context* con, Promise* constant, ConstantPoolEntry* next, Promise* callOffset): - c(c), constant(constant), next(next), callOffset(callOffset), + con(con), constant(constant), next(next), callOffset(callOffset), address(0) { } virtual int64_t value() { - assert(c, resolved()); + assert(con, resolved()); return reinterpret_cast(address); } @@ -709,7 +720,7 @@ class ConstantPoolEntry: public Promise { return address != 0; } - Context* c; + Context* con; Promise* constant; ConstantPoolEntry* next; Promise* callOffset; @@ -766,38 +777,38 @@ class PoolEvent { }; void -appendConstantPoolEntry(Context* c, Promise* constant, Promise* callOffset) +appendConstantPoolEntry(Context* con, Promise* constant, Promise* callOffset) { if (constant->resolved()) { // make a copy, since the original might be allocated on the // stack, and we need our copy to live until assembly is complete - constant = new(c->zone) ResolvedPromise(constant->value()); + constant = new(con->zone) ResolvedPromise(constant->value()); } - c->constantPool = new(c->zone) ConstantPoolEntry(c, constant, c->constantPool, callOffset); + con->constantPool = new(con->zone) ConstantPoolEntry(con, constant, con->constantPool, callOffset); - ++ c->constantPoolCount; + ++ con->constantPoolCount; - PoolOffset* o = new(c->zone) PoolOffset(c->lastBlock, c->constantPool, c->code.length() - c->lastBlock->offset); + PoolOffset* o = new(con->zone) PoolOffset(con->lastBlock, con->constantPool, con->code.length() - con->lastBlock->offset); if (DebugPool) { fprintf(stderr, "add pool offset %p %d to block %p\n", - o, o->offset, c->lastBlock); + o, o->offset, con->lastBlock); } - if (c->lastBlock->poolOffsetTail) { - c->lastBlock->poolOffsetTail->next = o; + if (con->lastBlock->poolOffsetTail) { + con->lastBlock->poolOffsetTail->next = o; } else { - c->lastBlock->poolOffsetHead = o; + con->lastBlock->poolOffsetHead = o; } - c->lastBlock->poolOffsetTail = o; + con->lastBlock->poolOffsetTail = o; } void -appendPoolEvent(Context* c, MyBlock* b, unsigned offset, PoolOffset* head, +appendPoolEvent(Context* con, MyBlock* b, unsigned offset, PoolOffset* head, PoolOffset* tail) { - PoolEvent* e = new(c->zone) PoolEvent(head, tail, offset); + PoolEvent* e = new(con->zone) PoolEvent(head, tail, offset); if (b->poolEventTail) { b->poolEventTail->next = e; @@ -835,24 +846,24 @@ padding(MyBlock* b, unsigned offset) void resolve(MyBlock* b) { - Context* c = b->context; + Context* con = b->context; if (b->poolOffsetHead) { - if (c->poolOffsetTail) { - c->poolOffsetTail->next = b->poolOffsetHead; + if (con->poolOffsetTail) { + con->poolOffsetTail->next = b->poolOffsetHead; } else { - c->poolOffsetHead = b->poolOffsetHead; + con->poolOffsetHead = b->poolOffsetHead; } - c->poolOffsetTail = b->poolOffsetTail; + con->poolOffsetTail = b->poolOffsetTail; } - if (c->poolOffsetHead) { + if (con->poolOffsetHead) { bool append; if (b->next == 0 or b->next->poolEventHead) { append = true; } else { int32_t v = (b->start + b->size + b->next->size + TargetBytesPerWord - 8) - - (c->poolOffsetHead->offset + c->poolOffsetHead->block->start); + - (con->poolOffsetHead->offset + con->poolOffsetHead->block->start); append = (v != (v & PoolOffsetMask)); @@ -863,57 +874,57 @@ resolve(MyBlock* b) b->next->size); fprintf(stderr, "offset %p %d is of distance %d to next block; append? %d\n", - c->poolOffsetHead, c->poolOffsetHead->offset, v, append); + con->poolOffsetHead, con->poolOffsetHead->offset, v, append); } } if (append) { #ifndef NDEBUG int32_t v = (b->start + b->size - 8) - - (c->poolOffsetHead->offset + c->poolOffsetHead->block->start); + - (con->poolOffsetHead->offset + con->poolOffsetHead->block->start); - expect(c, v == (v & PoolOffsetMask)); + expect(con, v == (v & PoolOffsetMask)); #endif // not NDEBUG - appendPoolEvent(c, b, b->size, c->poolOffsetHead, c->poolOffsetTail); + appendPoolEvent(con, b, b->size, con->poolOffsetHead, con->poolOffsetTail); if (DebugPool) { - for (PoolOffset* o = c->poolOffsetHead; o; o = o->next) { + for (PoolOffset* o = con->poolOffsetHead; o; o = o->next) { fprintf(stderr, "include %p %d in pool event %p at offset %d in block %p\n", o, o->offset, b->poolEventTail, b->size, b); } } - c->poolOffsetHead = 0; - c->poolOffsetTail = 0; + con->poolOffsetHead = 0; + con->poolOffsetTail = 0; } } } void -jumpR(Context* c, unsigned size UNUSED, Assembler::Register* target) +jumpR(Context* con, unsigned size UNUSED, Assembler::Register* target) { - assert(c, size == TargetBytesPerWord); - emit(c, bx(target->low)); + assert(con, size == TargetBytesPerWord); + emit(con, bx(target->low)); } void -moveRR(Context* c, unsigned srcSize, Assembler::Register* src, +moveRR(Context* con, unsigned srcSize, Assembler::Register* src, unsigned dstSize, Assembler::Register* dst); void -swapRR(Context* c, unsigned aSize, Assembler::Register* a, +swapRR(Context* con, unsigned aSize, Assembler::Register* a, unsigned bSize, Assembler::Register* b) { - assert(c, aSize == TargetBytesPerWord); - assert(c, bSize == TargetBytesPerWord); + assert(con, aSize == TargetBytesPerWord); + assert(con, bSize == TargetBytesPerWord); - Assembler::Register tmp(c->client->acquireTemporary()); - moveRR(c, aSize, a, bSize, &tmp); - moveRR(c, bSize, b, aSize, a); - moveRR(c, bSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveRR(con, aSize, a, bSize, &tmp); + moveRR(con, bSize, b, aSize, a); + moveRR(con, bSize, &tmp, bSize, b); + con->client->releaseTemporary(tmp.low); } void @@ -922,13 +933,19 @@ moveRR(Context* con, unsigned srcSize, Assembler::Register* src, { bool srcIsFpr = isFpr(src); bool dstIsFpr = isFpr(dst); - if (srcIsFpr || dstIsFpr) { // floating-point register(s) involved - // FPR to FPR - if (srcIsFpr && dstIsFpr) emit(con, fcpys(fpr(dst), fpr(src))); - // FPR to GPR - else if (srcIsFpr) emit(con, fmrs(dst->low, fpr(src))); - // GPR to FPR - else emit(con, fmsr(fpr(dst), src->low)); + if (srcIsFpr || dstIsFpr) { // FPR(s) involved + assert(con, srcSize == dstSize); + const bool dprec = srcSize == 8; + if (srcIsFpr && dstIsFpr) { // FPR to FPR + if (dprec) emit(con, fcpyd(fpr64(dst), fpr64(src))); // double + else emit(con, fcpys(fpr32(dst), fpr32(src))); // single + } else if (srcIsFpr) { // FPR to GPR + if (dprec) emit(con, fmrrd(dst->low, dst->high, fpr64(src))); + else emit(con, fmrs(dst->low, fpr32(src))); + } else { // GPR to FPR + if (dprec) emit(con, fmdrr(fpr64(dst->low), src->low, src->high)); + else emit(con, fmsr(fpr32(dst), src->low)); + } return; } @@ -973,37 +990,46 @@ moveRR(Context* con, unsigned srcSize, Assembler::Register* src, } void -moveZRR(Context* c, unsigned srcSize, Assembler::Register* src, +moveZRR(Context* con, unsigned srcSize, Assembler::Register* src, unsigned, Assembler::Register* dst) { switch (srcSize) { case 2: - emit(c, lsli(dst->low, src->low, 16)); - emit(c, lsri(dst->low, dst->low, 16)); + emit(con, lsli(dst->low, src->low, 16)); + emit(con, lsri(dst->low, dst->low, 16)); break; - default: abort(c); + default: abort(con); } } +void moveCR(Context* con, unsigned size, Assembler::Constant* src, + unsigned, Assembler::Register* dst); + void moveCR2(Context* con, unsigned size, Assembler::Constant* src, Assembler::Register* dst, Promise* callOffset) { if (isFpr(dst)) { // floating-point - Assembler::Register tmp = makeTemp(con); - moveCR2(con, size, src, &tmp, 0); + Assembler::Register tmp = size > 4 ? makeTemp64(con) : + makeTemp(con); + moveCR(con, size, src, size, &tmp); moveRR(con, size, &tmp, size, dst); freeTemp(con, tmp); - } else if (size <= 4) { - if (src->value->resolved() and isOfWidth(getValue(src), 8)) { - emit(con, movi(dst->low, lo8(getValue(src)))); - } else { - appendConstantPoolEntry(con, src->value, callOffset); - emit(con, ldri(dst->low, ProgramCounter, 0)); - } + } else if (size > 4) { + uint64_t value = (uint64_t)src->value->value(); + ResolvedPromise loBits(value & MASK_LO32); + Assembler::Constant srcLo(&loBits); + ResolvedPromise hiBits(value >> 32); + Assembler::Constant srcHi(&hiBits); + Assembler::Register dstHi(dst->high); + moveCR(con, 4, &srcLo, 4, dst); + moveCR(con, 4, &srcHi, 4, &dstHi); + } else if (src->value->resolved() and isOfWidth(getValue(src), 8)) { + emit(con, movi(dst->low, lo8(getValue(src)))); // fits in immediate } else { - abort(con); // todo + appendConstantPoolEntry(con, src->value, callOffset); + emit(con, ldri(dst->low, ProgramCounter, 0)); // load 32 bits } } @@ -1033,52 +1059,52 @@ void subR(Context* con, unsigned size, Assembler::Register* a, Assembler::Regist } void -addC(Context* c, unsigned size, Assembler::Constant* a, +addC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* dst) { - assert(c, size == TargetBytesPerWord); + assert(con, size == TargetBytesPerWord); int32_t v = a->value->value(); if (v) { if (v > 0 and v < 256) { - emit(c, addi(dst->low, b->low, v)); + emit(con, addi(dst->low, b->low, v)); } else if (v > 0 and v < 1024 and v % 4 == 0) { - emit(c, addi(dst->low, b->low, v >> 2, 15)); + emit(con, addi(dst->low, b->low, v >> 2, 15)); } else { // todo - abort(c); + abort(con); } } else { - moveRR(c, size, b, size, dst); + moveRR(con, size, b, size, dst); } } void -subC(Context* c, unsigned size, Assembler::Constant* a, +subC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* dst) { - assert(c, size == TargetBytesPerWord); + assert(con, size == TargetBytesPerWord); int32_t v = a->value->value(); if (v) { if (v > 0 and v < 256) { - emit(c, subi(dst->low, b->low, v)); + emit(con, subi(dst->low, b->low, v)); } else if (v > 0 and v < 1024 and v % 4 == 0) { - emit(c, subi(dst->low, b->low, v >> 2, 15)); + emit(con, subi(dst->low, b->low, v >> 2, 15)); } else { // todo - abort(c); + abort(con); } } else { - moveRR(c, size, b, size, dst); + moveRR(con, size, b, size, dst); } } void multiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { if (size == 8) { bool useTemporaries = b->low == t->low; - int tmpLow = useTemporaries ? con->client->acquireTemporary() : t->low; - int tmpHigh = useTemporaries ? con->client->acquireTemporary() : t->high; + int tmpLow = useTemporaries ? con->client->acquireTemporary(GPR_MASK) : t->low; + int tmpHigh = useTemporaries ? con->client->acquireTemporary(GPR_MASK) : t->high; emit(con, umull(tmpLow, tmpHigh, a->low, b->low)); emit(con, mla(tmpHigh, a->low, b->high, tmpHigh)); @@ -1095,98 +1121,98 @@ void multiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::R } } -void floatAbsoluteRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { +void floatAbsoluteRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { if (size == 8) { - emit(con, fabsd(fpr(b), fpr(a))); + emit(con, fabsd(fpr64(b), fpr64(a))); } else { - emit(con, fabss(fpr(b), fpr(a))); + emit(con, fabss(fpr32(b), fpr32(a))); } } -void floatNegateRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { +void floatNegateRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { if (size == 8) { - emit(con, fnegd(fpr(b), fpr(a))); + emit(con, fnegd(fpr64(b), fpr64(a))); } else { - emit(con, fnegs(fpr(b), fpr(a))); + emit(con, fnegs(fpr32(b), fpr32(a))); } } -void float2FloatRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { +void float2FloatRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { if (size == 8) { - emit(con, fcvtsd(fpr(b), fpr(a))); + emit(con, fcvtsd(fpr32(b), fpr64(a))); } else { - emit(con, fcvtds(fpr(b), fpr(a))); + emit(con, fcvtds(fpr64(b), fpr32(a))); } } -void float2IntRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { +void float2IntRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { int tmp = newTemp(con, FPR_MASK); - int ftmp = fpr(tmp); + int ftmp = fpr32(tmp); if (size == 8) { // double to int - emit(con, ftosizd(ftmp, fpr(a))); + emit(con, ftosizd(ftmp, fpr64(a))); } else { // float to int - emit(con, ftosizs(ftmp, fpr(a))); + emit(con, ftosizs(ftmp, fpr32(a))); } // else thunked emit(con, fmrs(b->low, ftmp)); freeTemp(con, tmp); } -void int2FloatRR(Context* con, unsigned UNUSED, Assembler::Register* a, unsigned size, Assembler::Register* b) { - emit(con, fmsr(fpr(b), a->low)); +void int2FloatRR(Context* con, unsigned, Assembler::Register* a, unsigned size, Assembler::Register* b) { + emit(con, fmsr(fpr32(b), a->low)); if (size == 8) { // int to double - emit(con, fsitod(fpr(b), fpr(b))); + emit(con, fsitod(fpr64(b), fpr32(b))); } else { // int to float - emit(con, fsitos(fpr(b), fpr(b))); + emit(con, fsitos(fpr32(b), fpr32(b))); } // else thunked } -void floatSqrtRR(Context* con, unsigned size, Assembler::Register* a, unsigned UNUSED, Assembler::Register* b) { +void floatSqrtRR(Context* con, unsigned size, Assembler::Register* a, unsigned, Assembler::Register* b) { if (size == 8) { - emit(con, fsqrtd(fpr(b), fpr(a))); + emit(con, fsqrtd(fpr64(b), fpr64(a))); } else { - emit(con, fsqrts(fpr(b), fpr(a))); + emit(con, fsqrts(fpr32(b), fpr32(a))); } } void floatAddR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { if (size == 8) { - emit(con, faddd(fpr(t), fpr(a), fpr(b))); + emit(con, faddd(fpr64(t), fpr64(a), fpr64(b))); } else { - emit(con, fadds(fpr(t), fpr(a), fpr(b))); + emit(con, fadds(fpr32(t), fpr32(a), fpr32(b))); } } void floatSubtractR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { if (size == 8) { - emit(con, fsubd(fpr(t), fpr(b), fpr(a))); + emit(con, fsubd(fpr64(t), fpr64(b), fpr64(a))); } else { - emit(con, fsubs(fpr(t), fpr(b), fpr(a))); + emit(con, fsubs(fpr32(t), fpr32(b), fpr32(a))); } } void floatMultiplyR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { if (size == 8) { - emit(con, fmuld(fpr(t), fpr(a), fpr(b))); + emit(con, fmuld(fpr64(t), fpr64(a), fpr64(b))); } else { - emit(con, fmuls(fpr(t), fpr(a), fpr(b))); + emit(con, fmuls(fpr32(t), fpr32(a), fpr32(b))); } } void floatDivideR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* t) { if (size == 8) { - emit(con, fdivd(fpr(t), fpr(b), fpr(a))); + emit(con, fdivd(fpr64(t), fpr64(b), fpr64(a))); } else { - emit(con, fdivs(fpr(t), fpr(b), fpr(a))); + emit(con, fdivs(fpr32(t), fpr32(b), fpr32(a))); } } int -normalize(Context* c, int offset, int index, unsigned scale, +normalize(Context* con, int offset, int index, unsigned scale, bool* preserveIndex, bool* release) { if (offset != 0 or scale != 1) { Assembler::Register normalizedIndex - (*preserveIndex ? c->client->acquireTemporary() : index); + (*preserveIndex ? con->client->acquireTemporary(GPR_MASK) : index); if (*preserveIndex) { *release = true; @@ -1203,7 +1229,7 @@ normalize(Context* c, int offset, int index, unsigned scale, ResolvedPromise scalePromise(log(scale)); Assembler::Constant scaleConstant(&scalePromise); - shiftLeftC(c, TargetBytesPerWord, &scaleConstant, + shiftLeftC(con, TargetBytesPerWord, &scaleConstant, &unscaledIndex, &normalizedIndex); scaled = normalizedIndex.low; @@ -1217,10 +1243,10 @@ normalize(Context* c, int offset, int index, unsigned scale, ResolvedPromise offsetPromise(offset); Assembler::Constant offsetConstant(&offsetPromise); - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, &tmp); - addR(c, TargetBytesPerWord, &tmp, &untranslatedIndex, &normalizedIndex); - c->client->releaseTemporary(tmp.low); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveCR(con, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, &tmp); + addR(con, TargetBytesPerWord, &tmp, &untranslatedIndex, &normalizedIndex); + con->client->releaseTemporary(tmp.low); } return normalizedIndex.low; @@ -1239,17 +1265,7 @@ store(Context* con, unsigned size, Assembler::Register* src, int normalized = normalize (con, offset, index, scale, &preserveIndex, &release); - if (isFpr(src)) { // floating-point store - if (size == 4) { - Assembler::Register base_(base), - normalized_(normalized), - absAddr = makeTemp(con); - addR(con, size, &base_, &normalized_, &absAddr); - emit(con, fsts(fpr(src), absAddr.low)); - freeTemp(con, absAddr); - } - else abort(con); - } else { + if (!isFpr(src)) { // GPR store switch (size) { case 1: emit(con, strb(src->low, base, normalized)); @@ -1263,7 +1279,7 @@ store(Context* con, unsigned size, Assembler::Register* src, emit(con, str(src->low, base, normalized)); break; - case 8: { + case 8: { // split into 2 32-bit stores Assembler::Register srcHigh(src->high); store(con, 4, &srcHigh, base, 0, normalized, 1, preserveIndex); store(con, 4, src, base, 4, normalized, 1, preserveIndex); @@ -1271,6 +1287,17 @@ store(Context* con, unsigned size, Assembler::Register* src, default: abort(con); } + } else { // FPR store + Assembler::Register base_(base), + normalized_(normalized), + absAddr = makeTemp(con); + // FPR stores have only bases, so we must add the index + addR(con, TargetBytesPerWord, &base_, &normalized_, &absAddr); + // double-precision + if (size == 8) emit(con, fstd(fpr64(src), absAddr.low)); + // single-precision + else emit(con, fsts(fpr32(src), absAddr.low)); + freeTemp(con, absAddr); } if (release) con->client->releaseTemporary(normalized); @@ -1278,10 +1305,7 @@ store(Context* con, unsigned size, Assembler::Register* src, or abs(offset) == (abs(offset) & 0xFF) or (size != 2 and abs(offset) == (abs(offset) & 0xFFF))) { - if (isFpr(src)) { - if (size == 4) emit(con, fsts(fpr(src), base, offset)); - else abort(con); - } else { + if (!isFpr(src)) { // GPR store switch (size) { case 1: emit(con, strbi(src->low, base, offset)); @@ -1295,7 +1319,7 @@ store(Context* con, unsigned size, Assembler::Register* src, emit(con, stri(src->low, base, offset)); break; - case 8: { + case 8: { // split into 2 32-bit stores Assembler::Register srcHigh(src->high); store(con, 4, &srcHigh, base, offset, NoRegister, 1, false); store(con, 4, src, base, offset + 4, NoRegister, 1, false); @@ -1303,9 +1327,14 @@ store(Context* con, unsigned size, Assembler::Register* src, default: abort(con); } + } else { // FPR store + // double-precision + if (size == 8) emit(con, fstd(fpr64(src), base, offset)); + // single-precision + else emit(con, fsts(fpr32(src), base, offset)); } } else { - Assembler::Register tmp(con->client->acquireTemporary()); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); ResolvedPromise offsetPromise(offset); Assembler::Constant offsetConstant(&offsetPromise); moveCR(con, TargetBytesPerWord, &offsetConstant, @@ -1318,28 +1347,28 @@ store(Context* con, unsigned size, Assembler::Register* src, } void -moveRM(Context* c, unsigned srcSize, Assembler::Register* src, +moveRM(Context* con, unsigned srcSize, Assembler::Register* src, unsigned dstSize UNUSED, Assembler::Memory* dst) { - assert(c, srcSize == dstSize); + assert(con, srcSize == dstSize); - store(c, srcSize, src, dst->base, dst->offset, dst->index, dst->scale, true); + store(con, srcSize, src, dst->base, dst->offset, dst->index, dst->scale, true); } void -moveAndUpdateRM(Context* c, unsigned srcSize UNUSED, Assembler::Register* src, +moveAndUpdateRM(Context* con, unsigned srcSize UNUSED, Assembler::Register* src, unsigned dstSize UNUSED, Assembler::Memory* dst) { - assert(c, srcSize == TargetBytesPerWord); - assert(c, dstSize == TargetBytesPerWord); + assert(con, srcSize == TargetBytesPerWord); + assert(con, dstSize == TargetBytesPerWord); if (dst->index == NoRegister) { - emit(c, stri(src->low, dst->base, dst->offset, dst->offset ? 1 : 0)); + emit(con, stri(src->low, dst->base, dst->offset, dst->offset ? 1 : 0)); } else { - assert(c, dst->offset == 0); - assert(c, dst->scale == 1); + assert(con, dst->offset == 0); + assert(con, dst->scale == 1); - emit(c, str(src->low, dst->base, dst->index, 1)); + emit(con, str(src->low, dst->base, dst->index, 1)); } } @@ -1353,17 +1382,7 @@ load(Context* con, unsigned srcSize, int base, int offset, int index, int normalized = normalize (con, offset, index, scale, &preserveIndex, &release); - if (isFpr(dst)) { // floating-point store - if (srcSize == 4) { - Assembler::Register base_(base), - normalized_(normalized), - absAddr = makeTemp(con); - addR(con, srcSize, &base_, &normalized_, &absAddr); - emit(con, flds(fpr(dst), absAddr.low)); - freeTemp(con, absAddr); - } - else abort(con); - } else { + if (!isFpr(dst)) { // GPR load switch (srcSize) { case 1: if (signExtend) { @@ -1400,6 +1419,17 @@ load(Context* con, unsigned srcSize, int base, int offset, int index, default: abort(con); } + } else { // FPR load + Assembler::Register base_(base), + normalized_(normalized), + absAddr = makeTemp(con); + // VFP loads only have bases, so we must add the index + addR(con, TargetBytesPerWord, &base_, &normalized_, &absAddr); + // double-precision + if (srcSize == 8) emit(con, fldd(fpr64(dst), absAddr.low)); + // single-precision + else emit(con, flds(fpr32(dst), absAddr.low)); + freeTemp(con, absAddr); } if (release) con->client->releaseTemporary(normalized); @@ -1409,10 +1439,7 @@ load(Context* con, unsigned srcSize, int base, int offset, int index, and (srcSize != 1 or not signExtend) and abs(offset) == (abs(offset) & 0xFFF))) { - if (isFpr(dst)) { - if (srcSize == 4) emit(con, flds(fpr(dst), base, offset)); - else abort(con); - } else { + if (!isFpr(dst)) { // GPR load switch (srcSize) { case 1: if (signExtend) { @@ -1448,9 +1475,14 @@ load(Context* con, unsigned srcSize, int base, int offset, int index, default: abort(con); } + } else { // FPR load + // double-precision + if (srcSize == 8) emit(con, fldd(fpr64(dst), base, offset)); + // single-precision + else emit(con, flds(fpr32(dst), base, offset)); } } else { - Assembler::Register tmp(con->client->acquireTemporary()); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); ResolvedPromise offsetPromise(offset); Assembler::Constant offsetConstant(&offsetPromise); moveCR(con, TargetBytesPerWord, &offsetConstant, TargetBytesPerWord, @@ -1464,31 +1496,31 @@ load(Context* con, unsigned srcSize, int base, int offset, int index, } void -moveMR(Context* c, unsigned srcSize, Assembler::Memory* src, +moveMR(Context* con, unsigned srcSize, Assembler::Memory* src, unsigned dstSize, Assembler::Register* dst) { - load(c, srcSize, src->base, src->offset, src->index, src->scale, + load(con, srcSize, src->base, src->offset, src->index, src->scale, dstSize, dst, true, true); } void -moveZMR(Context* c, unsigned srcSize, Assembler::Memory* src, +moveZMR(Context* con, unsigned srcSize, Assembler::Memory* src, unsigned dstSize, Assembler::Register* dst) { - load(c, srcSize, src->base, src->offset, src->index, src->scale, + load(con, srcSize, src->base, src->offset, src->index, src->scale, dstSize, dst, true, false); } void -andR(Context* c, unsigned size, Assembler::Register* a, +andR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* dst) { - if (size == 8) emit(c, and_(dst->high, a->high, b->high)); - emit(c, and_(dst->low, a->low, b->low)); + if (size == 8) emit(con, and_(dst->high, a->high, b->high)); + emit(con, and_(dst->low, a->low, b->low)); } void -andC(Context* c, unsigned size, Assembler::Constant* a, +andC(Context* con, unsigned size, Assembler::Constant* a, Assembler::Register* b, Assembler::Register* dst) { int64_t v = a->value->value(); @@ -1503,15 +1535,15 @@ andC(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register bh(b->high); Assembler::Register dh(dst->high); - andC(c, 4, &al, b, dst); - andC(c, 4, &ah, &bh, &dh); + andC(con, 4, &al, b, dst); + andC(con, 4, &ah, &bh, &dh); } else { uint32_t v32 = static_cast(v); if (v32 != 0xFFFFFFFF) { if ((v32 & 0xFFFFFF00) == 0xFFFFFF00) { - emit(c, bici(dst->low, b->low, (~(v32 & 0xFF)) & 0xFF)); + emit(con, bici(dst->low, b->low, (~(v32 & 0xFF)) & 0xFF)); } else if ((v32 & 0xFFFFFF00) == 0) { - emit(c, andi(dst->low, b->low, v32 & 0xFF)); + emit(con, andi(dst->low, b->low, v32 & 0xFF)); } else { // todo: there are other cases we can handle in one // instruction @@ -1519,28 +1551,28 @@ andC(Context* c, unsigned size, Assembler::Constant* a, bool useTemporary = b->low == dst->low; Assembler::Register tmp(dst->low); if (useTemporary) { - tmp.low = c->client->acquireTemporary(); + tmp.low = con->client->acquireTemporary(GPR_MASK); } - moveCR(c, 4, a, 4, &tmp); - andR(c, 4, b, &tmp, dst); + moveCR(con, 4, a, 4, &tmp); + andR(con, 4, b, &tmp, dst); if (useTemporary) { - c->client->releaseTemporary(tmp.low); + con->client->releaseTemporary(tmp.low); } } } else { - moveRR(c, size, b, size, dst); + moveRR(con, size, b, size, dst); } } } void -orR(Context* c, unsigned size, Assembler::Register* a, +orR(Context* con, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Register* dst) { - if (size == 8) emit(c, orr(dst->high, a->high, b->high)); - emit(c, orr(dst->low, a->low, b->low)); + if (size == 8) emit(con, orr(dst->high, a->high, b->high)); + emit(con, orr(dst->low, a->low, b->low)); } void @@ -1552,84 +1584,86 @@ xorR(Context* con, unsigned size, Assembler::Register* a, } void -moveAR2(Context* c, unsigned srcSize, Assembler::Address* src, +moveAR2(Context* con, unsigned srcSize, Assembler::Address* src, unsigned dstSize, Assembler::Register* dst) { - assert(c, srcSize == 4 and dstSize == 4); + assert(con, srcSize == 4 and dstSize == 4); Assembler::Constant constant(src->address); - moveCR(c, srcSize, &constant, dstSize, dst); + moveCR(con, srcSize, &constant, dstSize, dst); Assembler::Memory memory(dst->low, 0, -1, 0); - moveMR(c, dstSize, &memory, dstSize, dst); + moveMR(con, dstSize, &memory, dstSize, dst); } void -moveAR(Context* c, unsigned srcSize, Assembler::Address* src, +moveAR(Context* con, unsigned srcSize, Assembler::Address* src, unsigned dstSize, Assembler::Register* dst) { - moveAR2(c, srcSize, src, dstSize, dst); + moveAR2(con, srcSize, src, dstSize, dst); } void -compareRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, +compareRR(Context* con, unsigned aSize, Assembler::Register* a, unsigned bSize UNUSED, Assembler::Register* b) { - assert(c, aSize == 4 and bSize == 4); - assert(c, !(isFpr(a) ^ isFpr(b))); + assert(con, !(isFpr(a) ^ isFpr(b))); // regs must be of the same type - if (isFpr(a)) { - emit(c, fcmps(fpr(b), fpr(a))); - emit(c, fmstat()); - } else { - assert(c, b->low != a->low); - emit(c, cmp(b->low, a->low)); + if (!isFpr(a)) { // GPR compare + assert(con, aSize == 4 && bSize == 4); + /**///assert(con, b->low != a->low); + emit(con, cmp(b->low, a->low)); + } else { // FPR compare + assert(con, aSize == bSize); + if (aSize == 8) emit(con, fcmpd(fpr64(b), fpr64(a))); // double + else emit(con, fcmps(fpr32(b), fpr32(a))); // single + emit(con, fmstat()); } } void -compareCR(Context* c, unsigned aSize, Assembler::Constant* a, +compareCR(Context* con, unsigned aSize, Assembler::Constant* a, unsigned bSize, Assembler::Register* b) { - assert(c, aSize == 4 and bSize == 4); + assert(con, aSize == 4 and bSize == 4); if (!isFpr(b) && a->value->resolved() && isOfWidth(a->value->value(), 8)) { - emit(c, cmpi(b->low, a->value->value())); + emit(con, cmpi(b->low, a->value->value())); } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, aSize, a, bSize, &tmp); - compareRR(c, bSize, &tmp, bSize, b); - c->client->releaseTemporary(tmp.low); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveCR(con, aSize, a, bSize, &tmp); + compareRR(con, bSize, &tmp, bSize, b); + con->client->releaseTemporary(tmp.low); } } void -compareCM(Context* c, unsigned aSize, Assembler::Constant* a, +compareCM(Context* con, unsigned aSize, Assembler::Constant* a, unsigned bSize, Assembler::Memory* b) { - assert(c, aSize == 4 and bSize == 4); + assert(con, aSize == 4 and bSize == 4); - Assembler::Register tmp(c->client->acquireTemporary()); - moveMR(c, bSize, b, bSize, &tmp); - compareCR(c, aSize, a, bSize, &tmp); - c->client->releaseTemporary(tmp.low); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveMR(con, bSize, b, bSize, &tmp); + compareCR(con, aSize, a, bSize, &tmp); + con->client->releaseTemporary(tmp.low); } void -compareRM(Context* c, unsigned aSize, Assembler::Register* a, +compareRM(Context* con, unsigned aSize, Assembler::Register* a, unsigned bSize, Assembler::Memory* b) { - assert(c, aSize == 4 and bSize == 4); + assert(con, aSize == 4 and bSize == 4); - Assembler::Register tmp(c->client->acquireTemporary()); - moveMR(c, bSize, b, bSize, &tmp); - compareRR(c, aSize, a, bSize, &tmp); - c->client->releaseTemporary(tmp.low); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveMR(con, bSize, b, bSize, &tmp); + compareRR(con, aSize, a, bSize, &tmp); + con->client->releaseTemporary(tmp.low); } int32_t -branch(Context* c, TernaryOperation op) +branch(Context* con, TernaryOperation op) { switch (op) { case JumpIfEqual: @@ -1665,121 +1699,121 @@ branch(Context* c, TernaryOperation op) return bpl(0); default: - abort(c); + abort(con); } } void -conditional(Context* c, int32_t branch, Assembler::Constant* target) +conditional(Context* con, int32_t branch, Assembler::Constant* target) { - appendOffsetTask(c, target->value, offset(c)); - emit(c, branch); + appendOffsetTask(con, target->value, offset(con)); + emit(con, branch); } void -branch(Context* c, TernaryOperation op, Assembler::Constant* target) +branch(Context* con, TernaryOperation op, Assembler::Constant* target) { - conditional(c, branch(c, op), target); + conditional(con, branch(con, op), target); } void -branchLong(Context* c, TernaryOperation op, Assembler::Operand* al, +branchLong(Context* con, TernaryOperation op, Assembler::Operand* al, Assembler::Operand* ah, Assembler::Operand* bl, Assembler::Operand* bh, Assembler::Constant* target, BinaryOperationType compareSigned, BinaryOperationType compareUnsigned) { - compareSigned(c, 4, ah, 4, bh); + compareSigned(con, 4, ah, 4, bh); unsigned next = 0; switch (op) { case JumpIfEqual: case JumpIfFloatEqual: - next = c->code.length(); - emit(c, bne(0)); + next = con->code.length(); + emit(con, bne(0)); - compareSigned(c, 4, al, 4, bl); - conditional(c, beq(0), target); + compareSigned(con, 4, al, 4, bl); + conditional(con, beq(0), target); break; case JumpIfNotEqual: case JumpIfFloatNotEqual: - conditional(c, bne(0), target); + conditional(con, bne(0), target); - compareSigned(c, 4, al, 4, bl); - conditional(c, bne(0), target); + compareSigned(con, 4, al, 4, bl); + conditional(con, bne(0), target); break; case JumpIfLess: case JumpIfFloatLess: - conditional(c, blt(0), target); + conditional(con, blt(0), target); - next = c->code.length(); - emit(c, bgt(0)); + next = con->code.length(); + emit(con, bgt(0)); - compareUnsigned(c, 4, al, 4, bl); - conditional(c, blo(0), target); + compareUnsigned(con, 4, al, 4, bl); + conditional(con, blo(0), target); break; case JumpIfGreater: case JumpIfFloatGreater: - conditional(c, bgt(0), target); + conditional(con, bgt(0), target); - next = c->code.length(); - emit(c, blt(0)); + next = con->code.length(); + emit(con, blt(0)); - compareUnsigned(c, 4, al, 4, bl); - conditional(c, bhi(0), target); + compareUnsigned(con, 4, al, 4, bl); + conditional(con, bhi(0), target); break; case JumpIfLessOrEqual: case JumpIfFloatLessOrEqual: - conditional(c, blt(0), target); + conditional(con, blt(0), target); - next = c->code.length(); - emit(c, bgt(0)); + next = con->code.length(); + emit(con, bgt(0)); - compareUnsigned(c, 4, al, 4, bl); - conditional(c, bls(0), target); + compareUnsigned(con, 4, al, 4, bl); + conditional(con, bls(0), target); break; case JumpIfGreaterOrEqual: case JumpIfFloatGreaterOrEqual: - conditional(c, bgt(0), target); + conditional(con, bgt(0), target); - next = c->code.length(); - emit(c, blt(0)); + next = con->code.length(); + emit(con, blt(0)); - compareUnsigned(c, 4, al, 4, bl); - conditional(c, bhs(0), target); + compareUnsigned(con, 4, al, 4, bl); + conditional(con, bhs(0), target); break; default: - abort(c); + abort(con); } if (next) { updateOffset - (c->s, c->code.data + next, reinterpret_cast - (c->code.data + c->code.length())); + (con->s, con->code.data + next, reinterpret_cast + (con->code.data + con->code.length())); } } void -branchRR(Context* c, TernaryOperation op, unsigned size, +branchRR(Context* con, TernaryOperation op, unsigned size, Assembler::Register* a, Assembler::Register* b, Assembler::Constant* target) { - if (size > TargetBytesPerWord) { + if (!isFpr(a) && size > TargetBytesPerWord) { Assembler::Register ah(a->high); Assembler::Register bh(b->high); - branchLong(c, op, a, &ah, b, &bh, target, CAST2(compareRR), + branchLong(con, op, a, &ah, b, &bh, target, CAST2(compareRR), CAST2(compareRR)); } else { - compareRR(c, size, a, size, b); - branch(c, op, target); + compareRR(con, size, a, size, b); + branch(con, op, target); } } @@ -1834,106 +1868,106 @@ branchCM(Context* con, TernaryOperation op, unsigned size, } ShiftMaskPromise* -shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask) +shiftMaskPromise(Context* con, Promise* base, unsigned shift, int64_t mask) { - return new(c->zone) ShiftMaskPromise(base, shift, mask); + return new(con->zone) ShiftMaskPromise(base, shift, mask); } void -moveCM(Context* c, unsigned srcSize, Assembler::Constant* src, +moveCM(Context* con, unsigned srcSize, Assembler::Constant* src, unsigned dstSize, Assembler::Memory* dst) { switch (dstSize) { case 8: { Assembler::Constant srcHigh - (shiftMaskPromise(c, src->value, 32, 0xFFFFFFFF)); + (shiftMaskPromise(con, src->value, 32, 0xFFFFFFFF)); Assembler::Constant srcLow - (shiftMaskPromise(c, src->value, 0, 0xFFFFFFFF)); + (shiftMaskPromise(con, src->value, 0, 0xFFFFFFFF)); Assembler::Memory dstLow (dst->base, dst->offset + 4, dst->index, dst->scale); - moveCM(c, 4, &srcLow, 4, &dstLow); - moveCM(c, 4, &srcHigh, 4, dst); + moveCM(con, 4, &srcLow, 4, &dstLow); + moveCM(con, 4, &srcHigh, 4, dst); } break; default: - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, srcSize, src, dstSize, &tmp); - moveRM(c, dstSize, &tmp, dstSize, dst); - c->client->releaseTemporary(tmp.low); + Assembler::Register tmp(con->client->acquireTemporary(GPR_MASK)); + moveCR(con, srcSize, src, dstSize, &tmp); + moveRM(con, dstSize, &tmp, dstSize, dst); + con->client->releaseTemporary(tmp.low); } } void -negateRR(Context* c, unsigned srcSize, Assembler::Register* src, +negateRR(Context* con, unsigned srcSize, Assembler::Register* src, unsigned dstSize UNUSED, Assembler::Register* dst) { - assert(c, srcSize == dstSize); + assert(con, srcSize == dstSize); - emit(c, mvn(dst->low, src->low)); - emit(c, SETS(addi(dst->low, dst->low, 1))); + emit(con, mvn(dst->low, src->low)); + emit(con, SETS(addi(dst->low, dst->low, 1))); if (srcSize == 8) { - emit(c, mvn(dst->high, src->high)); - emit(c, adci(dst->high, dst->high, 0)); + emit(con, mvn(dst->high, src->high)); + emit(con, adci(dst->high, dst->high, 0)); } } void -callR(Context* c, unsigned size UNUSED, Assembler::Register* target) +callR(Context* con, unsigned size UNUSED, Assembler::Register* target) { - assert(c, size == TargetBytesPerWord); - emit(c, blx(target->low)); + assert(con, size == TargetBytesPerWord); + emit(con, blx(target->low)); } void -callC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +callC(Context* con, unsigned size UNUSED, Assembler::Constant* target) { - assert(c, size == TargetBytesPerWord); + assert(con, size == TargetBytesPerWord); - appendOffsetTask(c, target->value, offset(c)); - emit(c, bl(0)); + appendOffsetTask(con, target->value, offset(con)); + emit(con, bl(0)); } void -longCallC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +longCallC(Context* con, unsigned size UNUSED, Assembler::Constant* target) { - assert(c, size == TargetBytesPerWord); + assert(con, size == TargetBytesPerWord); Assembler::Register tmp(4); - moveCR2(c, TargetBytesPerWord, target, &tmp, offset(c)); - callR(c, TargetBytesPerWord, &tmp); + moveCR2(con, TargetBytesPerWord, target, &tmp, offset(con)); + callR(con, TargetBytesPerWord, &tmp); } void -longJumpC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +longJumpC(Context* con, unsigned size UNUSED, Assembler::Constant* target) { - assert(c, size == TargetBytesPerWord); + assert(con, size == TargetBytesPerWord); Assembler::Register tmp(4); // a non-arg reg that we don't mind clobbering - moveCR2(c, TargetBytesPerWord, target, &tmp, offset(c)); - jumpR(c, TargetBytesPerWord, &tmp); + moveCR2(con, TargetBytesPerWord, target, &tmp, offset(con)); + jumpR(con, TargetBytesPerWord, &tmp); } void -jumpC(Context* c, unsigned size UNUSED, Assembler::Constant* target) +jumpC(Context* con, unsigned size UNUSED, Assembler::Constant* target) { - assert(c, size == TargetBytesPerWord); + assert(con, size == TargetBytesPerWord); - appendOffsetTask(c, target->value, offset(c)); - emit(c, b(0)); + appendOffsetTask(con, target->value, offset(con)); + emit(con, b(0)); } void -return_(Context* c) +return_(Context* con) { - emit(c, bx(LinkRegister)); + emit(con, bx(LinkRegister)); } void -trap(Context* c) +trap(Context* con) { - emit(c, bkpt(0)); + emit(con, bkpt(0)); } void @@ -1948,12 +1982,12 @@ argumentFootprint(unsigned footprint) } void -nextFrame(ArchitectureContext* c, uint32_t* start, unsigned size UNUSED, +nextFrame(ArchitectureContext* con, uint32_t* start, unsigned size UNUSED, unsigned footprint, void* link, bool, unsigned targetParameterFootprint UNUSED, void** ip, void** stack) { - assert(c, *ip >= start); - assert(c, *ip <= start + (size / TargetBytesPerWord)); + assert(con, *ip >= start); + assert(con, *ip <= start + (size / TargetBytesPerWord)); uint32_t* instruction = static_cast(*ip); @@ -1994,7 +2028,7 @@ nextFrame(ArchitectureContext* c, uint32_t* start, unsigned size UNUSED, switch (rotation) { case 0: offset -= value / TargetBytesPerWord; break; case 15: offset -= value; break; - default: abort(c); + default: abort(con); } } @@ -2006,18 +2040,18 @@ nextFrame(ArchitectureContext* c, uint32_t* start, unsigned size UNUSED, } void -populateTables(ArchitectureContext* c) +populateTables(ArchitectureContext* con) { const OperandType C = ConstantOperand; const OperandType A = AddressOperand; const OperandType R = RegisterOperand; const OperandType M = MemoryOperand; - OperationType* zo = c->operations; - UnaryOperationType* uo = c->unaryOperations; - BinaryOperationType* bo = c->binaryOperations; - TernaryOperationType* to = c->ternaryOperations; - BranchOperationType* bro = c->branchOperations; + OperationType* zo = con->operations; + UnaryOperationType* uo = con->unaryOperations; + BinaryOperationType* bo = con->binaryOperations; + TernaryOperationType* to = con->ternaryOperations; + BranchOperationType* bro = con->branchOperations; zo[Return] = return_; zo[LoadBarrier] = memoryBarrier; @@ -2025,87 +2059,87 @@ populateTables(ArchitectureContext* c) zo[StoreLoadBarrier] = memoryBarrier; zo[Trap] = trap; - uo[index(c, LongCall, C)] = CAST1(longCallC); + uo[index(con, LongCall, C)] = CAST1(longCallC); - uo[index(c, AlignedLongCall, C)] = CAST1(longCallC); + uo[index(con, AlignedLongCall, C)] = CAST1(longCallC); - uo[index(c, LongJump, C)] = CAST1(longJumpC); + uo[index(con, LongJump, C)] = CAST1(longJumpC); - uo[index(c, AlignedLongJump, C)] = CAST1(longJumpC); + uo[index(con, AlignedLongJump, C)] = CAST1(longJumpC); - uo[index(c, Jump, R)] = CAST1(jumpR); - uo[index(c, Jump, C)] = CAST1(jumpC); + uo[index(con, Jump, R)] = CAST1(jumpR); + uo[index(con, Jump, C)] = CAST1(jumpC); - uo[index(c, AlignedJump, R)] = CAST1(jumpR); - uo[index(c, AlignedJump, C)] = CAST1(jumpC); + uo[index(con, AlignedJump, R)] = CAST1(jumpR); + uo[index(con, AlignedJump, C)] = CAST1(jumpC); - uo[index(c, Call, C)] = CAST1(callC); - uo[index(c, Call, R)] = CAST1(callR); + uo[index(con, Call, C)] = CAST1(callC); + uo[index(con, Call, R)] = CAST1(callR); - uo[index(c, AlignedCall, C)] = CAST1(callC); - uo[index(c, AlignedCall, R)] = CAST1(callR); + uo[index(con, AlignedCall, C)] = CAST1(callC); + uo[index(con, AlignedCall, R)] = CAST1(callR); - bo[index(c, Move, R, R)] = CAST2(moveRR); - bo[index(c, Move, C, R)] = CAST2(moveCR); - bo[index(c, Move, C, M)] = CAST2(moveCM); - bo[index(c, Move, M, R)] = CAST2(moveMR); - bo[index(c, Move, R, M)] = CAST2(moveRM); - bo[index(c, Move, A, R)] = CAST2(moveAR); + bo[index(con, Move, R, R)] = CAST2(moveRR); + bo[index(con, Move, C, R)] = CAST2(moveCR); + bo[index(con, Move, C, M)] = CAST2(moveCM); + bo[index(con, Move, M, R)] = CAST2(moveMR); + bo[index(con, Move, R, M)] = CAST2(moveRM); + bo[index(con, Move, A, R)] = CAST2(moveAR); - bo[index(c, MoveZ, R, R)] = CAST2(moveZRR); - bo[index(c, MoveZ, M, R)] = CAST2(moveZMR); - bo[index(c, MoveZ, C, R)] = CAST2(moveCR); + bo[index(con, MoveZ, R, R)] = CAST2(moveZRR); + bo[index(con, MoveZ, M, R)] = CAST2(moveZMR); + bo[index(con, MoveZ, C, R)] = CAST2(moveCR); - bo[index(c, Negate, R, R)] = CAST2(negateRR); + bo[index(con, Negate, R, R)] = CAST2(negateRR); - bo[index(c, FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); - bo[index(c, FloatNegate, R, R)] = CAST2(floatNegateRR); - bo[index(c, Float2Float, R, R)] = CAST2(float2FloatRR); - bo[index(c, Float2Int, R, R)] = CAST2(float2IntRR); - bo[index(c, Int2Float, R, R)] = CAST2(int2FloatRR); - bo[index(c, FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); + bo[index(con, FloatAbsolute, R, R)] = CAST2(floatAbsoluteRR); + bo[index(con, FloatNegate, R, R)] = CAST2(floatNegateRR); + bo[index(con, Float2Float, R, R)] = CAST2(float2FloatRR); + bo[index(con, Float2Int, R, R)] = CAST2(float2IntRR); + bo[index(con, Int2Float, R, R)] = CAST2(int2FloatRR); + bo[index(con, FloatSquareRoot, R, R)] = CAST2(floatSqrtRR); - to[index(c, Add, R)] = CAST3(addR); + to[index(con, Add, R)] = CAST3(addR); - to[index(c, Subtract, R)] = CAST3(subR); + to[index(con, Subtract, R)] = CAST3(subR); - to[index(c, Multiply, R)] = CAST3(multiplyR); + to[index(con, Multiply, R)] = CAST3(multiplyR); - to[index(c, FloatAdd, R)] = CAST3(floatAddR); - to[index(c, FloatSubtract, R)] = CAST3(floatSubtractR); - to[index(c, FloatMultiply, R)] = CAST3(floatMultiplyR); - to[index(c, FloatDivide, R)] = CAST3(floatDivideR); + to[index(con, FloatAdd, R)] = CAST3(floatAddR); + to[index(con, FloatSubtract, R)] = CAST3(floatSubtractR); + to[index(con, FloatMultiply, R)] = CAST3(floatMultiplyR); + to[index(con, FloatDivide, R)] = CAST3(floatDivideR); - to[index(c, ShiftLeft, R)] = CAST3(shiftLeftR); - to[index(c, ShiftLeft, C)] = CAST3(shiftLeftC); + to[index(con, ShiftLeft, R)] = CAST3(shiftLeftR); + to[index(con, ShiftLeft, C)] = CAST3(shiftLeftC); - to[index(c, ShiftRight, R)] = CAST3(shiftRightR); - to[index(c, ShiftRight, C)] = CAST3(shiftRightC); + to[index(con, ShiftRight, R)] = CAST3(shiftRightR); + to[index(con, ShiftRight, C)] = CAST3(shiftRightC); - to[index(c, UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR); - to[index(c, UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC); + to[index(con, UnsignedShiftRight, R)] = CAST3(unsignedShiftRightR); + to[index(con, UnsignedShiftRight, C)] = CAST3(unsignedShiftRightC); - to[index(c, And, R)] = CAST3(andR); - to[index(c, And, C)] = CAST3(andC); + to[index(con, And, R)] = CAST3(andR); + to[index(con, And, C)] = CAST3(andC); - to[index(c, Or, R)] = CAST3(orR); + to[index(con, Or, R)] = CAST3(orR); - to[index(c, Xor, R)] = CAST3(xorR); + to[index(con, Xor, R)] = CAST3(xorR); - bro[branchIndex(c, R, R)] = CAST_BRANCH(branchRR); - bro[branchIndex(c, C, R)] = CAST_BRANCH(branchCR); - bro[branchIndex(c, C, M)] = CAST_BRANCH(branchCM); - bro[branchIndex(c, R, M)] = CAST_BRANCH(branchRM); + bro[branchIndex(con, R, R)] = CAST_BRANCH(branchRR); + bro[branchIndex(con, C, R)] = CAST_BRANCH(branchCR); + bro[branchIndex(con, C, M)] = CAST_BRANCH(branchCM); + bro[branchIndex(con, R, M)] = CAST_BRANCH(branchRM); } class MyArchitecture: public Assembler::Architecture { public: - MyArchitecture(System* system): c(system), referenceCount(0) { - populateTables(&c); + MyArchitecture(System* system): con(system), referenceCount(0) { + populateTables(&con); } virtual unsigned floatRegisterSize() { - return vfpSupported() ? 4 : 0; + return vfpSupported() ? 8 : 0; } virtual uint32_t generalRegisterMask() { @@ -2194,7 +2228,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual int argumentRegister(unsigned index) { - assert(&c, index < argumentRegisterCount()); + assert(&con, index < argumentRegisterCount()); return index; } @@ -2224,7 +2258,7 @@ class MyArchitecture: public Assembler::Architecture { case Jump: case AlignedCall: case AlignedJump: { - updateOffset(c.s, static_cast(returnAddress) - 4, + updateOffset(con.s, static_cast(returnAddress) - 4, reinterpret_cast(newTarget)); } break; @@ -2237,7 +2271,7 @@ class MyArchitecture: public Assembler::Architecture { = newTarget; } break; - default: abort(&c); + default: abort(&con); } } @@ -2259,7 +2293,7 @@ class MyArchitecture: public Assembler::Architecture { unsigned targetParameterFootprint, void** ip, void** stack) { - ::nextFrame(&c, static_cast(start), size, footprint, link, + ::nextFrame(&con, static_cast(start), size, footprint, link, mostRecent, targetParameterFootprint, ip, stack); } @@ -2325,6 +2359,7 @@ class MyArchitecture: public Assembler::Architecture { switch (op) { case Negate: *aTypeMask = (1 << RegisterOperand); + *aRegisterMask = GPR_MASK64; break; case Absolute: @@ -2344,7 +2379,7 @@ class MyArchitecture: public Assembler::Architecture { break; case Float2Int: - if (vfpSupported() && bSize == 4 && aSize == 4) { + if (vfpSupported() && bSize == 4) { *aTypeMask = (1 << RegisterOperand); *aRegisterMask = FPR_MASK64; } else { @@ -2353,7 +2388,7 @@ class MyArchitecture: public Assembler::Architecture { break; case Int2Float: - if (vfpSupported() && aSize == 4 && bSize == 4) { + if (vfpSupported() && aSize == 4) { *aTypeMask = (1 << RegisterOperand); *aRegisterMask = GPR_MASK64; } else { @@ -2377,6 +2412,7 @@ class MyArchitecture: public Assembler::Architecture { switch (op) { case Negate: *bTypeMask = (1 << RegisterOperand); + *bRegisterMask = GPR_MASK64; break; case FloatAbsolute: @@ -2420,7 +2456,8 @@ class MyArchitecture: public Assembler::Architecture { *srcTypeMask = 1 << RegisterOperand; *tmpTypeMask = 1 << RegisterOperand; *tmpRegisterMask = GPR_MASK64; - } else if (dstTypeMask & 1 << RegisterOperand && + } else if (vfpSupported() && + dstTypeMask & 1 << RegisterOperand && dstRegisterMask & FPR_MASK) { *srcTypeMask = *tmpTypeMask = 1 << RegisterOperand | 1 << MemoryOperand; @@ -2435,10 +2472,10 @@ class MyArchitecture: public Assembler::Architecture { unsigned, bool* thunk) { *aTypeMask = (1 << RegisterOperand) | (1 << ConstantOperand); - *aRegisterMask = ~static_cast(0); + *aRegisterMask = GPR_MASK64; *bTypeMask = (1 << RegisterOperand); - *bRegisterMask = ~static_cast(0); + *bRegisterMask = GPR_MASK64; *thunk = false; @@ -2519,23 +2556,23 @@ class MyArchitecture: public Assembler::Architecture { virtual void release() { if (-- referenceCount == 0) { - c.s->free(this); + con.s->free(this); } } - ArchitectureContext c; + ArchitectureContext con; unsigned referenceCount; }; class MyAssembler: public Assembler { public: MyAssembler(System* s, Allocator* a, Zone* zone, MyArchitecture* arch): - c(s, a, zone), arch_(arch) + con(s, a, zone), arch_(arch) { } virtual void setClient(Client* client) { - assert(&c, c.client == 0); - c.client = client; + assert(&con, con.client == 0); + con.client = client; } virtual Architecture* arch() { @@ -2547,19 +2584,19 @@ class MyAssembler: public Assembler { { Register stack(StackRegister); Memory stackLimit(ThreadRegister, stackLimitOffsetFromThread); - Constant handlerConstant(new(c.zone) ResolvedPromise(handler)); - branchRM(&c, JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, + Constant handlerConstant(new(con.zone) ResolvedPromise(handler)); + branchRM(&con, JumpIfGreaterOrEqual, TargetBytesPerWord, &stack, &stackLimit, &handlerConstant); } virtual void saveFrame(unsigned stackOffset, unsigned ipOffset) { Register link(LinkRegister); Memory linkDst(ThreadRegister, ipOffset); - moveRM(&c, TargetBytesPerWord, &link, TargetBytesPerWord, &linkDst); + moveRM(&con, TargetBytesPerWord, &link, TargetBytesPerWord, &linkDst); Register stack(StackRegister); Memory stackDst(ThreadRegister, stackOffset); - moveRM(&c, TargetBytesPerWord, &stack, TargetBytesPerWord, &stackDst); + moveRM(&con, TargetBytesPerWord, &stack, TargetBytesPerWord, &stackDst); } virtual void pushFrame(unsigned argumentCount, ...) { @@ -2610,17 +2647,17 @@ class MyAssembler: public Assembler { // larger frames may require multiple subtract/add instructions // to allocate/deallocate, and nextFrame will need to be taught // how to handle them: - assert(&c, footprint < 256); + assert(&con, footprint < 256); Register stack(StackRegister); ResolvedPromise footprintPromise(footprint * TargetBytesPerWord); Constant footprintConstant(&footprintPromise); - subC(&c, TargetBytesPerWord, &footprintConstant, &stack, &stack); + subC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack); Register returnAddress(LinkRegister); Memory returnAddressDst (StackRegister, (footprint - 1) * TargetBytesPerWord); - moveRM(&c, TargetBytesPerWord, &returnAddress, TargetBytesPerWord, + moveRM(&con, TargetBytesPerWord, &returnAddress, TargetBytesPerWord, &returnAddressDst); } @@ -2628,7 +2665,7 @@ class MyAssembler: public Assembler { Register stack(StackRegister); ResolvedPromise differencePromise(difference * TargetBytesPerWord); Constant differenceConstant(&differencePromise); - subC(&c, TargetBytesPerWord, &differenceConstant, &stack, &stack); + subC(&con, TargetBytesPerWord, &differenceConstant, &stack, &stack); } virtual void popFrame(unsigned footprint) { @@ -2637,13 +2674,13 @@ class MyAssembler: public Assembler { Register returnAddress(LinkRegister); Memory returnAddressSrc (StackRegister, (footprint - 1) * TargetBytesPerWord); - moveMR(&c, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord, + moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord, &returnAddress); Register stack(StackRegister); ResolvedPromise footprintPromise(footprint * TargetBytesPerWord); Constant footprintConstant(&footprintPromise); - addC(&c, TargetBytesPerWord, &footprintConstant, &stack, &stack); + addC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack); } virtual void popFrameForTailCall(unsigned footprint, @@ -2651,7 +2688,7 @@ class MyAssembler: public Assembler { int returnAddressSurrogate, int framePointerSurrogate UNUSED) { - assert(&c, framePointerSurrogate == NoRegister); + assert(&con, framePointerSurrogate == NoRegister); if (TailCalls) { if (offset) { @@ -2660,27 +2697,27 @@ class MyAssembler: public Assembler { Register link(LinkRegister); Memory returnAddressSrc (StackRegister, (footprint - 1) * TargetBytesPerWord); - moveMR(&c, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord, + moveMR(&con, TargetBytesPerWord, &returnAddressSrc, TargetBytesPerWord, &link); Register stack(StackRegister); ResolvedPromise footprintPromise ((footprint - offset) * TargetBytesPerWord); Constant footprintConstant(&footprintPromise); - addC(&c, TargetBytesPerWord, &footprintConstant, &stack, &stack); + addC(&con, TargetBytesPerWord, &footprintConstant, &stack, &stack); if (returnAddressSurrogate != NoRegister) { - assert(&c, offset > 0); + assert(&con, offset > 0); Register ras(returnAddressSurrogate); Memory dst(StackRegister, (offset - 1) * TargetBytesPerWord); - moveRM(&c, TargetBytesPerWord, &ras, TargetBytesPerWord, &dst); + moveRM(&con, TargetBytesPerWord, &ras, TargetBytesPerWord, &dst); } } else { popFrame(footprint); } } else { - abort(&c); + abort(&con); } } @@ -2689,8 +2726,8 @@ class MyAssembler: public Assembler { { popFrame(frameFootprint); - assert(&c, argumentFootprint >= StackAlignmentInWords); - assert(&c, (argumentFootprint % StackAlignmentInWords) == 0); + assert(&con, argumentFootprint >= StackAlignmentInWords); + assert(&con, (argumentFootprint % StackAlignmentInWords) == 0); unsigned offset; if (TailCalls and argumentFootprint > StackAlignmentInWords) { @@ -2699,12 +2736,12 @@ class MyAssembler: public Assembler { Register stack(StackRegister); ResolvedPromise adjustmentPromise(offset * TargetBytesPerWord); Constant adjustment(&adjustmentPromise); - addC(&c, TargetBytesPerWord, &adjustment, &stack, &stack); + addC(&con, TargetBytesPerWord, &adjustment, &stack, &stack); } else { offset = 0; } - return_(&c); + return_(&con); } virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint, @@ -2714,28 +2751,28 @@ class MyAssembler: public Assembler { Register stack(StackRegister); Memory newStackSrc(ThreadRegister, stackOffsetFromThread); - moveMR(&c, TargetBytesPerWord, &newStackSrc, TargetBytesPerWord, &stack); + moveMR(&con, TargetBytesPerWord, &newStackSrc, TargetBytesPerWord, &stack); - return_(&c); + return_(&con); } virtual void apply(Operation op) { - arch_->c.operations[op](&c); + arch_->con.operations[op](&con); } virtual void apply(UnaryOperation op, unsigned aSize, OperandType aType, Operand* aOperand) { - arch_->c.unaryOperations[index(&(arch_->c), op, aType)] - (&c, aSize, aOperand); + arch_->con.unaryOperations[index(&(arch_->con), op, aType)] + (&con, aSize, aOperand); } virtual void apply(BinaryOperation op, unsigned aSize, OperandType aType, Operand* aOperand, unsigned bSize, OperandType bType, Operand* bOperand) { - arch_->c.binaryOperations[index(&(arch_->c), op, aType, bType)] - (&c, aSize, aOperand, bSize, bOperand); + arch_->con.binaryOperations[index(&(arch_->con), op, aType, bType)] + (&con, aSize, aOperand, bSize, bOperand); } virtual void apply(TernaryOperation op, @@ -2746,30 +2783,30 @@ class MyAssembler: public Assembler { Operand* cOperand) { if (isBranch(op)) { - assert(&c, aSize == bSize); - assert(&c, cSize == TargetBytesPerWord); - assert(&c, cType == ConstantOperand); + assert(&con, aSize == bSize); + assert(&con, cSize == TargetBytesPerWord); + assert(&con, cType == ConstantOperand); - arch_->c.branchOperations[branchIndex(&(arch_->c), aType, bType)] - (&c, op, aSize, aOperand, bOperand, cOperand); + arch_->con.branchOperations[branchIndex(&(arch_->con), aType, bType)] + (&con, op, aSize, aOperand, bOperand, cOperand); } else { - assert(&c, bSize == cSize); - assert(&c, bType == RegisterOperand); - assert(&c, cType == RegisterOperand); + assert(&con, bSize == cSize); + assert(&con, bType == RegisterOperand); + assert(&con, cType == RegisterOperand); - arch_->c.ternaryOperations[index(&(arch_->c), op, aType)] - (&c, bSize, aOperand, bOperand, cOperand); + arch_->con.ternaryOperations[index(&(arch_->con), op, aType)] + (&con, bSize, aOperand, bOperand, cOperand); } } virtual void setDestination(uint8_t* dst) { - c.result = dst; + con.result = dst; } virtual void write() { - uint8_t* dst = c.result; + uint8_t* dst = con.result; unsigned dstOffset = 0; - for (MyBlock* b = c.firstBlock; b; b = b->next) { + for (MyBlock* b = con.firstBlock; b; b = b->next) { if (DebugPool) { fprintf(stderr, "write block %p\n", b); } @@ -2777,7 +2814,7 @@ class MyAssembler: public Assembler { unsigned blockOffset = 0; for (PoolEvent* e = b->poolEventHead; e; e = e->next) { unsigned size = e->offset - blockOffset; - memcpy(dst + dstOffset, c.code.data + b->offset + blockOffset, size); + memcpy(dst + dstOffset, con.code.data + b->offset + blockOffset, size); blockOffset = e->offset; dstOffset += size; @@ -2800,7 +2837,7 @@ class MyAssembler: public Assembler { + padding(o->block, o->offset) + o->offset; int32_t v = (entry - 8) - instruction; - expect(&c, v == (v & PoolOffsetMask)); + expect(&con, v == (v & PoolOffsetMask)); int32_t* p = reinterpret_cast(dst + instruction); *p = (v & PoolOffsetMask) | ((~PoolOffsetMask) & *p); @@ -2820,22 +2857,22 @@ class MyAssembler: public Assembler { unsigned size = b->size - blockOffset; memcpy(dst + dstOffset, - c.code.data + b->offset + blockOffset, + con.code.data + b->offset + blockOffset, size); dstOffset += size; } - for (Task* t = c.tasks; t; t = t->next) { - t->run(&c); + for (Task* t = con.tasks; t; t = t->next) { + t->run(&con); } - for (ConstantPoolEntry* e = c.constantPool; e; e = e->next) { + for (ConstantPoolEntry* e = con.constantPool; e; e = e->next) { if (e->constant->resolved()) { *static_cast(e->address) = e->constant->value(); } else { new (e->constant->listen(sizeof(ConstantPoolListener))) - ConstantPoolListener(c.s, static_cast(e->address), + ConstantPoolListener(con.s, static_cast(e->address), e->callOffset ? dst + e->callOffset->value() + 8 : 0); @@ -2845,30 +2882,30 @@ class MyAssembler: public Assembler { } virtual Promise* offset(bool forTrace) { - return ::offset(&c, forTrace); + return ::offset(&con, forTrace); } virtual Block* endBlock(bool startNew) { - MyBlock* b = c.lastBlock; - b->size = c.code.length() - b->offset; + MyBlock* b = con.lastBlock; + b->size = con.code.length() - b->offset; if (startNew) { - c.lastBlock = new (c.zone) MyBlock(&c, c.code.length()); + con.lastBlock = new (con.zone) MyBlock(&con, con.code.length()); } else { - c.lastBlock = 0; + con.lastBlock = 0; } return b; } virtual void endEvent() { - MyBlock* b = c.lastBlock; - unsigned thisEventOffset = c.code.length() - b->offset; + MyBlock* b = con.lastBlock; + unsigned thisEventOffset = con.code.length() - b->offset; if (b->poolOffsetHead) { int32_t v = (thisEventOffset + TargetBytesPerWord - 8) - b->poolOffsetHead->offset; if (v > 0 and v != (v & PoolOffsetMask)) { appendPoolEvent - (&c, b, b->lastEventOffset, b->poolOffsetHead, + (&con, b, b->lastEventOffset, b->poolOffsetHead, b->lastPoolOffsetTail); if (DebugPool) { @@ -2894,7 +2931,7 @@ class MyAssembler: public Assembler { } virtual unsigned length() { - return c.code.length(); + return con.code.length(); } virtual unsigned footerSize() { @@ -2902,10 +2939,10 @@ class MyAssembler: public Assembler { } virtual void dispose() { - c.code.dispose(); + con.code.dispose(); } - Context c; + Context con; MyArchitecture* arch_; }; From 527526c5ea769ebdc9f79300c21632f9e73e2e95 Mon Sep 17 00:00:00 2001 From: Mike Keesey Date: Wed, 13 Jun 2012 08:41:15 -0600 Subject: [PATCH 128/140] Defer to underlying PersistentSet for size. --- classpath/java/util/TreeSet.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/classpath/java/util/TreeSet.java b/classpath/java/util/TreeSet.java index 0faac7ad12..1768d64843 100644 --- a/classpath/java/util/TreeSet.java +++ b/classpath/java/util/TreeSet.java @@ -15,7 +15,6 @@ import avian.Cell; public class TreeSet extends AbstractSet implements Collection { private PersistentSet> set; - private int size; public TreeSet(final Comparator comparator) { set = new PersistentSet(new Comparator>() { @@ -23,7 +22,6 @@ public class TreeSet extends AbstractSet implements Collection { return comparator.compare(a.value, b.value); } }); - size = 0; } public TreeSet() { @@ -66,7 +64,6 @@ public class TreeSet extends AbstractSet implements Collection { PersistentSet.Path> p = set.find(new Cell(value, null)); if (p.fresh()) { set = p.add(); - ++size; return true; } return false; @@ -76,7 +73,6 @@ public class TreeSet extends AbstractSet implements Collection { PersistentSet.Path> p = set.find(new Cell(value, null)); if (p.fresh()) { set = p.add(); - ++size; return null; } else { T old = p.value().value; @@ -100,8 +96,6 @@ public class TreeSet extends AbstractSet implements Collection { if (p.fresh()) { return null; } else { - --size; - Cell old = p.value(); if (p.value().next != null) { @@ -119,11 +113,11 @@ public class TreeSet extends AbstractSet implements Collection { } public int size() { - return size; + return set.size(); } public boolean isEmpty() { - return size == 0; + return set.size() != 0; } public boolean contains(Object value) { @@ -132,7 +126,6 @@ public class TreeSet extends AbstractSet implements Collection { public void clear() { set = new PersistentSet(set.comparator()); - size = 0; } private class MyIterator implements java.util.Iterator { @@ -180,8 +173,6 @@ public class TreeSet extends AbstractSet implements Collection { public void remove() { if (! canRemove) throw new IllegalStateException(); - --size; - if (prevPrevCell != null && prevPrevCell.next == prevCell) { // cell to remove is not the first in the list. prevPrevCell.next = prevCell.next; From 5a5a6a779530159b1d24ec28498668d9069bda9f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 13 Jun 2012 19:10:28 -0600 Subject: [PATCH 129/140] fix C++11 errors and aliasing warning --- src/classpath-openjdk.cpp | 18 ++++++++++-------- src/interpret.cpp | 5 +++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 33c7095807..bbdb4a547e 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2960,10 +2960,10 @@ EXPORT(JVM_ArrayCopy)(Thread* t, jclass, jobject src, jint srcOffset, jobject dst, jint dstOffset, jint length) { uintptr_t arguments[] = { reinterpret_cast(src), - srcOffset, + static_cast(srcOffset), reinterpret_cast(dst), - dstOffset, - length }; + static_cast(dstOffset), + static_cast(length) }; run(t, jvmArrayCopy, arguments); } @@ -3238,7 +3238,8 @@ jvmGetStackTraceElement(Thread* t, uintptr_t* arguments) extern "C" JNIEXPORT jobject JNICALL EXPORT(JVM_GetStackTraceElement)(Thread* t, jobject throwable, jint index) { - uintptr_t arguments[] = { reinterpret_cast(throwable), index }; + uintptr_t arguments[] = { reinterpret_cast(throwable), + static_cast(index) }; return reinterpret_cast(run(t, jvmGetStackTraceElement, arguments)); } @@ -3646,7 +3647,7 @@ extern "C" JNIEXPORT jobject JNICALL EXPORT(JVM_GetArrayElement)(Thread* t, jobject array, jint index) { uintptr_t arguments[] = { reinterpret_cast(array), - index }; + static_cast(index) }; return reinterpret_cast(run(t, jvmGetArrayElement, arguments)); } @@ -3740,7 +3741,7 @@ extern "C" JNIEXPORT jobject JNICALL EXPORT(JVM_NewArray)(Thread* t, jclass elementClass, jint length) { uintptr_t arguments[] = { reinterpret_cast(elementClass), - length }; + static_cast(length) }; return reinterpret_cast(run(t, jvmNewArray, arguments)); } @@ -3946,7 +3947,7 @@ EXPORT(JVM_DefineClass)(Thread* t, const char*, jobject loader, { uintptr_t arguments[] = { reinterpret_cast(loader), reinterpret_cast(data), - length }; + static_cast(length) }; return reinterpret_cast(run(t, jvmDefineClass, arguments)); } @@ -4710,7 +4711,8 @@ jvmConstantPoolGetUTF8At(Thread* t, uintptr_t* arguments) extern "C" JNIEXPORT jstring JNICALL EXPORT(JVM_ConstantPoolGetUTF8At)(Thread* t, jobject, jobject pool, jint index) { - uintptr_t arguments[] = { reinterpret_cast(pool), index }; + uintptr_t arguments[] = { reinterpret_cast(pool), + static_cast(index) }; return reinterpret_cast (run(t, jvmConstantPoolGetUTF8At, arguments)); diff --git a/src/interpret.cpp b/src/interpret.cpp index c36ebde450..fe166dedcd 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -158,7 +158,7 @@ peekObject(Thread* t, unsigned index) assert(t, index < stackSizeInWords(t) / 2); assert(t, t->stack[index * 2] == ObjectTag); - return *reinterpret_cast(t->stack + (index * 2) + 1); + return reinterpret_cast(t->stack[(index * 2) + 1]); } inline uint32_t @@ -2706,7 +2706,8 @@ interpret(Thread* t) while (true) { bool success = false; - uintptr_t arguments[] = { base, reinterpret_cast(&success) }; + uintptr_t arguments[] = { static_cast(base), + reinterpret_cast(&success) }; uint64_t r = run(t, interpret2, arguments); if (success) { From f38f5699c6ba2e87d0b30f2d3197cec56dc8952e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 13 Jun 2012 19:33:11 -0600 Subject: [PATCH 130/140] preserve NetworkInterface fields since they're referenced from native code --- openjdk.pro | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openjdk.pro b/openjdk.pro index 5a60ba1260..8207016de5 100644 --- a/openjdk.pro +++ b/openjdk.pro @@ -114,6 +114,9 @@ private long handle; } +-keep class java.net.NetworkInterface { + ; + } -keep class java.net.InetAddress { ; } From c00f811a2f11bf293209cdb9d5d6c933b81f69d0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 14 Jun 2012 09:58:20 -0600 Subject: [PATCH 131/140] initialize count_ from starting point in MyStackWalker(MyStackWalker*) When we're initializing a stack walker based on an existing instance, we should initialize all the fields from that instance, including count_. --- src/compile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compile.cpp b/src/compile.cpp index ce67081480..1da37437b9 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -532,7 +532,7 @@ class MyStackWalker: public Processor::StackWalker { method_(w->method_), target(w->target), continuation(w->continuation), - count_(0), + count_(w->count_), protector(this) { } From 153b78f479502112cbae2d92ce0634e659bbc5fd Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 14 Jun 2012 10:55:03 -0600 Subject: [PATCH 132/140] fix ArrayList performance issue The ArrayList(Collection) constructor was allocating two arrays instead of one due to an off-by-one error in ArrayList.grow. This commit fixes that and makes grow and shrink more robust. --- classpath/java/util/ArrayList.java | 25 +++++++++++++------------ test/List.java | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/classpath/java/util/ArrayList.java b/classpath/java/util/ArrayList.java index d7a61d61ed..3935aa44ec 100644 --- a/classpath/java/util/ArrayList.java +++ b/classpath/java/util/ArrayList.java @@ -29,14 +29,15 @@ public class ArrayList extends AbstractList implements java.io.Serializabl addAll(source); } - private void grow() { - if (array == null || size >= array.length) { - resize(array == null ? MinimumCapacity : array.length * 2); + private void grow(int newSize) { + if (array == null || newSize > array.length) { + resize(Math.max(newSize, array == null + ? MinimumCapacity : array.length * 2)); } } - private void shrink() { - if (array.length / 2 >= MinimumCapacity && size <= array.length / 3) { + private void shrink(int newSize) { + if (array.length / 2 >= MinimumCapacity && newSize <= array.length / 3) { resize(array.length / 2); } } @@ -74,16 +75,15 @@ public class ArrayList extends AbstractList implements java.io.Serializabl } public void add(int index, T element) { - size = Math.max(size+1, index+1); - grow(); + int newSize = Math.max(size+1, index+1); + grow(newSize); + size = newSize; System.arraycopy(array, index, array, index+1, size-index-1); array[index] = element; } public boolean add(T element) { - ++ size; - grow(); - array[size - 1] = element; + add(size, element); return true; } @@ -137,8 +137,9 @@ public class ArrayList extends AbstractList implements java.io.Serializabl System.arraycopy(array, index + 1, array, index, size - index); } - -- size; - shrink(); + int newSize = size - 1; + shrink(newSize); + size = newSize; return v; } diff --git a/test/List.java b/test/List.java index 797aefbb7f..c7d73d93fc 100644 --- a/test/List.java +++ b/test/List.java @@ -131,6 +131,20 @@ public class List { expect(l.size() == 2); } + private static void testGrow() { + ArrayList foo = new ArrayList(2); + foo.add(0); + foo.add(1); + foo.add(2); // first grow + foo.add(3); + foo.add(4); // second grow + foo.add(5); + + for (int i = 0; i < foo.size(); i++) { + expect(i == foo.get(i)); + } + } + public static void main(String args[]) { ArrayList l = new ArrayList(); l.add(1); l.add(2); l.add(3); l.add(4); l.add(5); @@ -155,5 +169,6 @@ public class List { testIterators2(new ArrayList()); testIterators2(new LinkedList()); + testGrow(); } } From 4512a9a38e839fbd2fdcba201d1e3e183b9781eb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 15 Jun 2012 17:41:40 -0600 Subject: [PATCH 133/140] implement NewObjectA, GetMethodA, and GetStaticMethodA --- src/common.h | 44 ++++++ src/compile.cpp | 71 ++++++++++ src/interpret.cpp | 57 ++++++++ src/jnienv.cpp | 338 ++++++++++++++++++++++++++++++++++++++++++++-- src/machine.h | 44 ------ src/processor.h | 4 + 6 files changed, 501 insertions(+), 57 deletions(-) diff --git a/src/common.h b/src/common.h index 009b90226e..3bb319f767 100644 --- a/src/common.h +++ b/src/common.h @@ -562,6 +562,50 @@ struct Object { }; typedef Object* object; +typedef uint8_t jboolean; +typedef int8_t jbyte; +typedef uint16_t jchar; +typedef int16_t jshort; +typedef int32_t jint; +typedef int64_t jlong; +typedef float jfloat; +typedef double jdouble; + +typedef jint jsize; + +typedef object* jobject; + +typedef jobject jclass; +typedef jobject jthrowable; +typedef jobject jstring; +typedef jobject jweak; + +typedef jobject jarray; +typedef jarray jbooleanArray; +typedef jarray jbyteArray; +typedef jarray jcharArray; +typedef jarray jshortArray; +typedef jarray jintArray; +typedef jarray jlongArray; +typedef jarray jfloatArray; +typedef jarray jdoubleArray; +typedef jarray jobjectArray; + +typedef uintptr_t jfieldID; +typedef uintptr_t jmethodID; + +union jvalue { + jboolean z; + jbyte b; + jchar c; + jshort s; + jint i; + jlong j; + jfloat f; + jdouble d; + jobject l; +}; + } // namespace vm #endif//COMMON_H diff --git a/src/compile.cpp b/src/compile.cpp index 1da37437b9..127f643956 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -8221,6 +8221,47 @@ class ArgumentList { } } + ArgumentList(Thread* t, uintptr_t* array, unsigned size, bool* objectMask, + object this_, const char* spec, const jvalue* arguments): + t(static_cast(t)), + array(array), + objectMask(objectMask), + size(size), + position(0), + protector(this) + { + if (this_) { + addObject(this_); + } + + unsigned index = 0; + for (MethodSpecIterator it(t, spec); it.hasNext();) { + switch (*it.next()) { + case 'L': + case '[': { + object* v = arguments[index++].l; + addObject(v ? *v : 0); + } break; + + case 'J': + addLong(arguments[index++].j); + break; + + case 'D': + addLong(arguments[index++].d); + break; + + case 'F': + addLong(arguments[index++].f); + break; + + default: + addLong(arguments[index++].i); + break; + } + } + } + ArgumentList(Thread* t, uintptr_t* array, unsigned size, bool* objectMask, object this_, const char* spec, object arguments): t(static_cast(t)), @@ -8765,6 +8806,36 @@ class MyProcessor: public Processor { return local::invoke(t, method, &list); } + virtual object + invokeArray(Thread* t, object method, object this_, const jvalue* arguments) + { + assert(t, t->exception == 0); + + assert(t, t->state == Thread::ActiveState + or t->state == Thread::ExclusiveState); + + assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); + + method = findMethod(t, method, this_); + + const char* spec = reinterpret_cast + (&byteArrayBody(t, methodSpec(t, method), 0)); + + unsigned size = methodParameterFootprint(t, method); + THREAD_RUNTIME_ARRAY(t, uintptr_t, array, size); + THREAD_RUNTIME_ARRAY(t, bool, objectMask, size); + ArgumentList list + (t, RUNTIME_ARRAY_BODY(array), size, RUNTIME_ARRAY_BODY(objectMask), + this_, spec, arguments); + + PROTECT(t, method); + + compile(static_cast(t), + local::codeAllocator(static_cast(t)), 0, method); + + return local::invoke(t, method, &list); + } + virtual object invokeList(Thread* t, object method, object this_, bool indirectObjects, va_list arguments) diff --git a/src/interpret.cpp b/src/interpret.cpp index fe166dedcd..10cfb2c33e 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -2758,6 +2758,39 @@ pushArguments(Thread* t, object this_, const char* spec, bool indirectObjects, } } +void +pushArguments(Thread* t, object this_, const char* spec, + const jvalue* arguments) +{ + if (this_) { + pushObject(t, this_); + } + + unsigned index = 0; + for (MethodSpecIterator it(t, spec); it.hasNext();) { + switch (*it.next()) { + case 'L': + case '[': { + jobject v = arguments[index++].l; + pushObject(t, v ? *v : 0); + } break; + + case 'J': + case 'D': + pushLong(t, arguments[index++].j); + break; + + case 'F': { + pushFloat(t, arguments[index++].d); + } break; + + default: + pushInt(t, arguments[index++].i); + break; + } + } +} + void pushArguments(Thread* t, object this_, const char* spec, object a) { @@ -3009,6 +3042,30 @@ class MyProcessor: public Processor { return ::invoke(t, method); } + virtual object + invokeArray(vm::Thread* vmt, object method, object this_, + const jvalue* arguments) + { + Thread* t = static_cast(vmt); + + assert(t, t->state == Thread::ActiveState + or t->state == Thread::ExclusiveState); + + assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); + + if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1 + > stackSizeInWords(t) / 2)) + { + throwNew(t, Machine::StackOverflowErrorType); + } + + const char* spec = reinterpret_cast + (&byteArrayBody(t, methodSpec(t, method), 0)); + pushArguments(t, this_, spec, arguments); + + return ::invoke(t, method); + } + virtual object invokeList(vm::Thread* vmt, object method, object this_, bool indirectObjects, va_list arguments) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 1631d0f3bb..5846bea7b2 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -631,17 +631,41 @@ NewObject(Thread* t, jclass c, jmethodID m, ...) return r; } +uint64_t +newObjectA(Thread* t, uintptr_t* arguments) +{ + jclass c = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + object o = make(t, jclassVmClass(t, *c)); + PROTECT(t, o); + + t->m->processor->invokeArray(t, getMethod(t, m), o, a); + + return reinterpret_cast(makeLocalReference(t, o)); +} + +jobject JNICALL +NewObjectA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return reinterpret_cast(run(t, newObjectA, arguments)); +} + uint64_t callObjectMethodV(Thread* t, uintptr_t* arguments) { - jobject o = reinterpret_cast(arguments[0]); + jobject o = reinterpret_cast(arguments[0]); jmethodID m = arguments[1]; va_list* a = reinterpret_cast(arguments[2]); - object method = getMethod(t, m); return reinterpret_cast (makeLocalReference - (t, t->m->processor->invokeList(t, method, *o, true, *a))); + (t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a))); } jobject JNICALL @@ -667,15 +691,37 @@ CallObjectMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +uint64_t +callObjectMethodA(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + return reinterpret_cast + (makeLocalReference + (t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a))); +} + +jobject JNICALL +CallObjectMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return reinterpret_cast(run(t, callObjectMethodA, arguments)); +} + uint64_t callIntMethodV(Thread* t, uintptr_t* arguments) { - jobject o = reinterpret_cast(arguments[0]); + jobject o = reinterpret_cast(arguments[0]); jmethodID m = arguments[1]; va_list* a = reinterpret_cast(arguments[2]); - object method = getMethod(t, m); - return intValue(t, t->m->processor->invokeList(t, method, *o, true, *a)); + return intValue + (t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a)); } jboolean JNICALL @@ -701,6 +747,27 @@ CallBooleanMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +uint64_t +callIntMethodA(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + return intValue + (t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a)); +} + +jboolean JNICALL +CallBooleanMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return run(t, callIntMethodA, arguments) != 0; +} + jbyte JNICALL CallByteMethodV(Thread* t, jobject o, jmethodID m, va_list a) { @@ -724,6 +791,16 @@ CallByteMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +jbyte JNICALL +CallByteMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return run(t, callIntMethodA, arguments); +} + jchar JNICALL CallCharMethodV(Thread* t, jobject o, jmethodID m, va_list a) { @@ -747,6 +824,16 @@ CallCharMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +jchar JNICALL +CallCharMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return run(t, callIntMethodA, arguments); +} + jshort JNICALL CallShortMethodV(Thread* t, jobject o, jmethodID m, va_list a) { @@ -770,6 +857,16 @@ CallShortMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +jshort JNICALL +CallShortMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return run(t, callIntMethodA, arguments); +} + jint JNICALL CallIntMethodV(Thread* t, jobject o, jmethodID m, va_list a) { @@ -793,15 +890,25 @@ CallIntMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +jint JNICALL +CallIntMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return run(t, callIntMethodA, arguments); +} + uint64_t callLongMethodV(Thread* t, uintptr_t* arguments) { - jobject o = reinterpret_cast(arguments[0]); + jobject o = reinterpret_cast(arguments[0]); jmethodID m = arguments[1]; va_list* a = reinterpret_cast(arguments[2]); - object method = getMethod(t, m); - return longValue(t, t->m->processor->invokeList(t, method, *o, true, *a)); + return longValue + (t, t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a)); } jlong JNICALL @@ -827,6 +934,27 @@ CallLongMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +uint64_t +callLongMethodA(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + return longValue + (t, t->m->processor->invokeArray(t, getMethod(t, m), *o, a)); +} + +jlong JNICALL +CallLongMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return run(t, callLongMethodA, arguments); +} + jfloat JNICALL CallFloatMethodV(Thread* t, jobject o, jmethodID m, va_list a) { @@ -850,6 +978,16 @@ CallFloatMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +jfloat JNICALL +CallFloatMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return bitsToFloat(run(t, callIntMethodA, arguments)); +} + jdouble JNICALL CallDoubleMethodV(Thread* t, jobject o, jmethodID m, va_list a) { @@ -873,15 +1011,24 @@ CallDoubleMethod(Thread* t, jobject o, jmethodID m, ...) return r; } +jdouble JNICALL +CallDoubleMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + return bitsToDouble(run(t, callLongMethodA, arguments)); +} + uint64_t callVoidMethodV(Thread* t, uintptr_t* arguments) { - jobject o = reinterpret_cast(arguments[0]); + jobject o = reinterpret_cast(arguments[0]); jmethodID m = arguments[1]; va_list* a = reinterpret_cast(arguments[2]); - object method = getMethod(t, m); - t->m->processor->invokeList(t, method, *o, true, *a); + t->m->processor->invokeList(t, getMethod(t, m), *o, true, *a); return 0; } @@ -907,6 +1054,28 @@ CallVoidMethod(Thread* t, jobject o, jmethodID m, ...) va_end(a); } +uint64_t +callVoidMethodA(Thread* t, uintptr_t* arguments) +{ + jobject o = reinterpret_cast(arguments[0]); + jmethodID m = arguments[1]; + const jvalue* a = reinterpret_cast(arguments[2]); + + t->m->processor->invokeArray(t, getMethod(t, m), *o, a); + + return 0; +} + +void JNICALL +CallVoidMethodA(Thread* t, jobject o, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { reinterpret_cast(o), + m, + reinterpret_cast(a) }; + + run(t, callVoidMethodA, arguments); +} + object getStaticMethod(Thread* t, jmethodID m) { @@ -951,6 +1120,25 @@ CallStaticObjectMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +uint64_t +callStaticObjectMethodA(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + const jvalue* a = reinterpret_cast(arguments[1]); + + return reinterpret_cast + (makeLocalReference + (t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a))); +} + +jobject JNICALL +CallStaticObjectMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return reinterpret_cast(run(t, callStaticObjectMethodA, arguments)); +} + uint64_t callStaticIntMethodV(Thread* t, uintptr_t* arguments) { @@ -982,6 +1170,24 @@ CallStaticBooleanMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +uint64_t +callStaticIntMethodA(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + const jvalue* a = reinterpret_cast(arguments[1]); + + return intValue + (t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a)); +} + +jboolean JNICALL +CallStaticBooleanMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return run(t, callStaticIntMethodA, arguments) != 0; +} + jbyte JNICALL CallStaticByteMethodV(Thread* t, jclass, jmethodID m, va_list a) { @@ -1003,6 +1209,14 @@ CallStaticByteMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +jbyte JNICALL +CallStaticByteMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return run(t, callStaticIntMethodA, arguments); +} + jchar JNICALL CallStaticCharMethodV(Thread* t, jclass, jmethodID m, va_list a) { @@ -1024,6 +1238,14 @@ CallStaticCharMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +jchar JNICALL +CallStaticCharMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return run(t, callStaticIntMethodA, arguments); +} + jshort JNICALL CallStaticShortMethodV(Thread* t, jclass, jmethodID m, va_list a) { @@ -1045,6 +1267,14 @@ CallStaticShortMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +jshort JNICALL +CallStaticShortMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return run(t, callStaticIntMethodA, arguments); +} + jint JNICALL CallStaticIntMethodV(Thread* t, jclass, jmethodID m, va_list a) { @@ -1066,6 +1296,14 @@ CallStaticIntMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +jint JNICALL +CallStaticIntMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return run(t, callStaticIntMethodA, arguments); +} + uint64_t callStaticLongMethodV(Thread* t, uintptr_t* arguments) { @@ -1097,6 +1335,24 @@ CallStaticLongMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +uint64_t +callStaticLongMethodA(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + const jvalue* a = reinterpret_cast(arguments[1]); + + return longValue + (t, t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a)); +} + +jlong JNICALL +CallStaticLongMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return run(t, callStaticLongMethodA, arguments); +} + jfloat JNICALL CallStaticFloatMethodV(Thread* t, jclass, jmethodID m, va_list a) { @@ -1118,6 +1374,14 @@ CallStaticFloatMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +jfloat JNICALL +CallStaticFloatMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return bitsToFloat(run(t, callStaticIntMethodA, arguments)); +} + jdouble JNICALL CallStaticDoubleMethodV(Thread* t, jclass, jmethodID m, va_list a) { @@ -1139,6 +1403,14 @@ CallStaticDoubleMethod(Thread* t, jclass c, jmethodID m, ...) return r; } +jdouble JNICALL +CallStaticDoubleMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + return bitsToDouble(run(t, callStaticLongMethodA, arguments)); +} + uint64_t callStaticVoidMethodV(Thread* t, uintptr_t* arguments) { @@ -1169,6 +1441,25 @@ CallStaticVoidMethod(Thread* t, jclass c, jmethodID m, ...) va_end(a); } +uint64_t +callStaticVoidMethodA(Thread* t, uintptr_t* arguments) +{ + jmethodID m = arguments[0]; + const jvalue* a = reinterpret_cast(arguments[1]); + + t->m->processor->invokeArray(t, getStaticMethod(t, m), 0, a); + + return 0; +} + +void JNICALL +CallStaticVoidMethodA(Thread* t, jclass, jmethodID m, const jvalue* a) +{ + uintptr_t arguments[] = { m, reinterpret_cast(a) }; + + run(t, callStaticVoidMethodA, arguments); +} + jint fieldID(Thread* t, object field) { @@ -3105,47 +3396,68 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) envTable->GetFieldID = local::GetFieldID; envTable->GetMethodID = local::GetMethodID; envTable->GetStaticMethodID = local::GetStaticMethodID; - envTable->NewObject = local::NewObject; envTable->NewObjectV = local::NewObjectV; + envTable->NewObjectA = local::NewObjectA; + envTable->NewObject = local::NewObject; envTable->CallObjectMethodV = local::CallObjectMethodV; + envTable->CallObjectMethodA = local::CallObjectMethodA; envTable->CallObjectMethod = local::CallObjectMethod; envTable->CallBooleanMethodV = local::CallBooleanMethodV; + envTable->CallBooleanMethodA = local::CallBooleanMethodA; envTable->CallBooleanMethod = local::CallBooleanMethod; envTable->CallByteMethodV = local::CallByteMethodV; + envTable->CallByteMethodA = local::CallByteMethodA; envTable->CallByteMethod = local::CallByteMethod; envTable->CallCharMethodV = local::CallCharMethodV; + envTable->CallCharMethodA = local::CallCharMethodA; envTable->CallCharMethod = local::CallCharMethod; envTable->CallShortMethodV = local::CallShortMethodV; + envTable->CallShortMethodA = local::CallShortMethodA; envTable->CallShortMethod = local::CallShortMethod; envTable->CallIntMethodV = local::CallIntMethodV; + envTable->CallIntMethodA = local::CallIntMethodA; envTable->CallIntMethod = local::CallIntMethod; envTable->CallLongMethodV = local::CallLongMethodV; + envTable->CallLongMethodA = local::CallLongMethodA; envTable->CallLongMethod = local::CallLongMethod; envTable->CallFloatMethodV = local::CallFloatMethodV; + envTable->CallFloatMethodA = local::CallFloatMethodA; envTable->CallFloatMethod = local::CallFloatMethod; envTable->CallDoubleMethodV = local::CallDoubleMethodV; + envTable->CallDoubleMethodA = local::CallDoubleMethodA; envTable->CallDoubleMethod = local::CallDoubleMethod; envTable->CallVoidMethodV = local::CallVoidMethodV; + envTable->CallVoidMethodA = local::CallVoidMethodA; envTable->CallVoidMethod = local::CallVoidMethod; envTable->CallStaticObjectMethodV = local::CallStaticObjectMethodV; + envTable->CallStaticObjectMethodA = local::CallStaticObjectMethodA; envTable->CallStaticObjectMethod = local::CallStaticObjectMethod; envTable->CallStaticBooleanMethodV = local::CallStaticBooleanMethodV; + envTable->CallStaticBooleanMethodA = local::CallStaticBooleanMethodA; envTable->CallStaticBooleanMethod = local::CallStaticBooleanMethod; envTable->CallStaticByteMethodV = local::CallStaticByteMethodV; + envTable->CallStaticByteMethodA = local::CallStaticByteMethodA; envTable->CallStaticByteMethod = local::CallStaticByteMethod; envTable->CallStaticCharMethodV = local::CallStaticCharMethodV; + envTable->CallStaticCharMethodA = local::CallStaticCharMethodA; envTable->CallStaticCharMethod = local::CallStaticCharMethod; envTable->CallStaticShortMethodV = local::CallStaticShortMethodV; + envTable->CallStaticShortMethodA = local::CallStaticShortMethodA; envTable->CallStaticShortMethod = local::CallStaticShortMethod; envTable->CallStaticIntMethodV = local::CallStaticIntMethodV; + envTable->CallStaticIntMethodA = local::CallStaticIntMethodA; envTable->CallStaticIntMethod = local::CallStaticIntMethod; envTable->CallStaticLongMethodV = local::CallStaticLongMethodV; + envTable->CallStaticLongMethodA = local::CallStaticLongMethodA; envTable->CallStaticLongMethod = local::CallStaticLongMethod; envTable->CallStaticFloatMethodV = local::CallStaticFloatMethodV; + envTable->CallStaticFloatMethodA = local::CallStaticFloatMethodA; envTable->CallStaticFloatMethod = local::CallStaticFloatMethod; envTable->CallStaticDoubleMethodV = local::CallStaticDoubleMethodV; + envTable->CallStaticDoubleMethodA = local::CallStaticDoubleMethodA; envTable->CallStaticDoubleMethod = local::CallStaticDoubleMethod; envTable->CallStaticVoidMethodV = local::CallStaticVoidMethodV; + envTable->CallStaticVoidMethodA = local::CallStaticVoidMethodA; envTable->CallStaticVoidMethod = local::CallStaticVoidMethod; envTable->GetStaticFieldID = local::GetStaticFieldID; envTable->GetObjectField = local::GetObjectField; diff --git a/src/machine.h b/src/machine.h index b20913cd65..a9cba4024e 100644 --- a/src/machine.h +++ b/src/machine.h @@ -167,50 +167,6 @@ const unsigned ConstructorFlag = 1 << 1; typedef Machine JavaVM; typedef Thread JNIEnv; -typedef uint8_t jboolean; -typedef int8_t jbyte; -typedef uint16_t jchar; -typedef int16_t jshort; -typedef int32_t jint; -typedef int64_t jlong; -typedef float jfloat; -typedef double jdouble; - -typedef jint jsize; - -typedef object* jobject; - -typedef jobject jclass; -typedef jobject jthrowable; -typedef jobject jstring; -typedef jobject jweak; - -typedef jobject jarray; -typedef jarray jbooleanArray; -typedef jarray jbyteArray; -typedef jarray jcharArray; -typedef jarray jshortArray; -typedef jarray jintArray; -typedef jarray jlongArray; -typedef jarray jfloatArray; -typedef jarray jdoubleArray; -typedef jarray jobjectArray; - -typedef uintptr_t jfieldID; -typedef uintptr_t jmethodID; - -union jvalue { - jboolean z; - jbyte b; - jchar c; - jshort s; - jint i; - jlong j; - jfloat f; - jdouble d; - jobject l; -}; - struct JNINativeMethod { char* name; char* signature; diff --git a/src/processor.h b/src/processor.h index 4af110401f..c4c6fd9ad2 100644 --- a/src/processor.h +++ b/src/processor.h @@ -106,6 +106,10 @@ class Processor { virtual object invokeArray(Thread* t, object method, object this_, object arguments) = 0; + virtual object + invokeArray(Thread* t, object method, object this_, const jvalue* arguments) + = 0; + virtual object invokeList(Thread* t, object method, object this_, bool indirectObjects, va_list arguments) = 0; From 886dd184aafbcaa06b9a31e87a2c7f093fc2e5c4 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 18 Jun 2012 14:27:18 +0000 Subject: [PATCH 134/140] fix incorrect stack unwinding for asynchronous stack traces Our Thread.getStackTrace implementation is tricky because it might be invoked on a thread executing arbitrary native or Java code, and there are numerous edge cases to consider. Unsurprisingly, there were a few lingering, non-fatal bugs revealed by Valgrind recently, one involving the brief interval just before and after returning from invokeNative, and the other involving an off-by-one error in x86.cpp's nextFrame implementation. This commit fixes both. --- src/compile-arm.S | 10 +++++----- src/compile-powerpc.S | 8 ++++---- src/compile-x86.S | 4 ++-- src/compile.cpp | 8 +++++--- src/continuations-x86.S | 16 ++++++++-------- src/target.h | 30 ++++++++++++++++-------------- src/x86.cpp | 4 ++-- 7 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/compile-arm.S b/src/compile-arm.S index 8ce5cc3684..2dedb94af8 100644 --- a/src/compile-arm.S +++ b/src/compile-arm.S @@ -23,12 +23,12 @@ #endif #define THREAD_STACK 2148 -#define THREAD_SCRATCH 2152 -#define THREAD_CONTINUATION 2156 +#define THREAD_SCRATCH 2156 +#define THREAD_CONTINUATION 2160 #define THREAD_EXCEPTION 44 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2160 -#define THREAD_EXCEPTION_OFFSET 2164 -#define THREAD_EXCEPTION_HANDLER 2168 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2164 +#define THREAD_EXCEPTION_OFFSET 2168 +#define THREAD_EXCEPTION_HANDLER 2172 #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 diff --git a/src/compile-powerpc.S b/src/compile-powerpc.S index bd178c9117..170fe47dd0 100644 --- a/src/compile-powerpc.S +++ b/src/compile-powerpc.S @@ -30,11 +30,11 @@ #define ARGUMENT_BASE BYTES_PER_WORD * LINKAGE_AREA #define THREAD_STACK 2148 -#define THREAD_CONTINUATION 2156 +#define THREAD_CONTINUATION 2160 #define THREAD_EXCEPTION 44 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2160 -#define THREAD_EXCEPTION_OFFSET 2164 -#define THREAD_EXCEPTION_HANDLER 2168 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2164 +#define THREAD_EXCEPTION_OFFSET 2168 +#define THREAD_EXCEPTION_HANDLER 2172 #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 diff --git a/src/compile-x86.S b/src/compile-x86.S index 52bf411355..d81129765a 100644 --- a/src/compile-x86.S +++ b/src/compile-x86.S @@ -24,7 +24,7 @@ #ifdef __x86_64__ #define THREAD_STACK 2224 -#define THREAD_SCRATCH 2232 +#define THREAD_SCRATCH 2240 #ifdef AVIAN_USE_FRAME_POINTER # define ALIGNMENT_ADJUSTMENT 0 @@ -300,7 +300,7 @@ LOCAL(vmJumpAndInvoke_argumentTest): #elif defined __i386__ #define THREAD_STACK 2148 -#define THREAD_SCRATCH 2152 +#define THREAD_SCRATCH 2156 #ifdef AVIAN_USE_FRAME_POINTER # define ALIGNMENT_ADJUSTMENT 0 diff --git a/src/compile.cpp b/src/compile.cpp index 127f643956..6b7e4ea6f0 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -235,6 +235,7 @@ class MyThread: public Thread { Thread(m, javaThread, parent), ip(0), stack(0), + newStack(0), scratch(0), continuation(0), exceptionStackAdjustment(0), @@ -261,6 +262,7 @@ class MyThread: public Thread { void* ip; void* stack; + void* newStack; void* scratch; object continuation; uintptr_t exceptionStackAdjustment; @@ -7620,11 +7622,11 @@ invokeNative(MyThread* t) stack += t->arch->frameReturnAddressSize(); - transition(t, getIp(t), stack, t->continuation, t->trace); - t->trace->targetMethod = 0; t->trace->nativeMethod = 0; + t->newStack = stack; + return result; } @@ -9903,7 +9905,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) compileCall(t, &context, invokeNativeIndex); a->popFrameAndUpdateStackAndReturn - (t->arch->alignFrameSize(1), TargetThreadStack); + (t->arch->alignFrameSize(1), TargetThreadNewStack); p->thunks.native.length = a->endBlock(false)->resolve(0, 0); diff --git a/src/continuations-x86.S b/src/continuations-x86.S index eea08ed21e..6cb67e8c09 100644 --- a/src/continuations-x86.S +++ b/src/continuations-x86.S @@ -10,11 +10,11 @@ #ifdef __x86_64__ -#define THREAD_CONTINUATION 2240 +#define THREAD_CONTINUATION 2248 #define THREAD_EXCEPTION 80 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2248 -#define THREAD_EXCEPTION_OFFSET 2256 -#define THREAD_EXCEPTION_HANDLER 2264 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2256 +#define THREAD_EXCEPTION_OFFSET 2264 +#define THREAD_EXCEPTION_HANDLER 2272 #define CONTINUATION_NEXT 8 #define CONTINUATION_ADDRESS 32 @@ -91,11 +91,11 @@ LOCAL(vmInvoke_exit): #elif defined __i386__ -#define THREAD_CONTINUATION 2156 +#define THREAD_CONTINUATION 2160 #define THREAD_EXCEPTION 44 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2160 -#define THREAD_EXCEPTION_OFFSET 2164 -#define THREAD_EXCEPTION_HANDLER 2168 +#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2164 +#define THREAD_EXCEPTION_OFFSET 2168 +#define THREAD_EXCEPTION_HANDLER 2172 #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 diff --git a/src/target.h b/src/target.h index 509a574996..51b2d6bdaf 100644 --- a/src/target.h +++ b/src/target.h @@ -94,13 +94,14 @@ const unsigned TargetBytesPerWord = 8; const unsigned TargetThreadIp = 2216; const unsigned TargetThreadStack = 2224; -const unsigned TargetThreadTailAddress = 2272; -const unsigned TargetThreadVirtualCallTarget = 2280; -const unsigned TargetThreadVirtualCallIndex = 2288; -const unsigned TargetThreadHeapImage = 2296; -const unsigned TargetThreadCodeImage = 2304; -const unsigned TargetThreadThunkTable = 2312; -const unsigned TargetThreadStackLimit = 2360; +const unsigned TargetThreadNewStack = 2232; +const unsigned TargetThreadTailAddress = 2280; +const unsigned TargetThreadVirtualCallTarget = 2288; +const unsigned TargetThreadVirtualCallIndex = 2296; +const unsigned TargetThreadHeapImage = 2304; +const unsigned TargetThreadCodeImage = 2312; +const unsigned TargetThreadThunkTable = 2320; +const unsigned TargetThreadStackLimit = 2368; const unsigned TargetClassFixedSize = 12; const unsigned TargetClassArrayElementSize = 14; @@ -124,13 +125,14 @@ const unsigned TargetBytesPerWord = 4; const unsigned TargetThreadIp = 2144; const unsigned TargetThreadStack = 2148; -const unsigned TargetThreadTailAddress = 2172; -const unsigned TargetThreadVirtualCallTarget = 2176; -const unsigned TargetThreadVirtualCallIndex = 2180; -const unsigned TargetThreadHeapImage = 2184; -const unsigned TargetThreadCodeImage = 2188; -const unsigned TargetThreadThunkTable = 2192; -const unsigned TargetThreadStackLimit = 2216; +const unsigned TargetThreadNewStack = 2152; +const unsigned TargetThreadTailAddress = 2176; +const unsigned TargetThreadVirtualCallTarget = 2180; +const unsigned TargetThreadVirtualCallIndex = 2184; +const unsigned TargetThreadHeapImage = 2188; +const unsigned TargetThreadCodeImage = 2192; +const unsigned TargetThreadThunkTable = 2198; +const unsigned TargetThreadStackLimit = 2220; const unsigned TargetClassFixedSize = 8; const unsigned TargetClassArrayElementSize = 10; diff --git a/src/x86.cpp b/src/x86.cpp index 6875449953..2a6d39d0aa 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -2524,10 +2524,10 @@ nextFrame(ArchitectureContext* c UNUSED, uint8_t* start, unsigned size UNUSED, // skip stack overflow check, if present: if (TargetBytesPerWord == 4) { if (*start == 0x39) { - start += 11; + start += 12; } } else if (*start == 0x48 and start[1] == 0x39) { - start += 12; + start += 13; } if (instruction <= start) { From 65e7a911b58ac46da58f7c2c889b18b3710f3205 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 18 Jun 2012 19:25:01 -0600 Subject: [PATCH 135/140] fix incorrect 32-bit TargetThreadThunkTable value --- src/target.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target.h b/src/target.h index 51b2d6bdaf..071a4d743a 100644 --- a/src/target.h +++ b/src/target.h @@ -131,7 +131,7 @@ const unsigned TargetThreadVirtualCallTarget = 2180; const unsigned TargetThreadVirtualCallIndex = 2184; const unsigned TargetThreadHeapImage = 2188; const unsigned TargetThreadCodeImage = 2192; -const unsigned TargetThreadThunkTable = 2198; +const unsigned TargetThreadThunkTable = 2196; const unsigned TargetThreadStackLimit = 2220; const unsigned TargetClassFixedSize = 8; From fe1f069309b2e3cd38e3e390fd2560557d088d6e Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Wed, 20 Jun 2012 13:14:16 -0600 Subject: [PATCH 136/140] abort on startup if Thread field offset constants don't match the real runtime values --- makefile | 2 + src/compile-arm.S | 31 ++++++-------- src/compile-powerpc.S | 24 ++++------- src/compile-x86.S | 25 +++++------ src/compile.cpp | 98 +++++++++++++++++++++---------------------- src/target-fields.h | 63 ++++++++++++++++++++++++++++ src/target.h | 30 ++----------- 7 files changed, 147 insertions(+), 126 deletions(-) create mode 100644 src/target-fields.h diff --git a/makefile b/makefile index 6e5f439d2f..e97c24905d 100755 --- a/makefile +++ b/makefile @@ -192,6 +192,8 @@ common-cflags = $(warnings) -fno-rtti -fno-exceptions \ -DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \ -DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\" $(target-cflags) +asmflags = $(target-cflags) + ifneq (,$(filter i386 x86_64,$(arch))) ifeq ($(use-frame-pointer),true) common-cflags += -fno-omit-frame-pointer -DAVIAN_USE_FRAME_POINTER diff --git a/src/compile-arm.S b/src/compile-arm.S index 2dedb94af8..427378c1f8 100644 --- a/src/compile-arm.S +++ b/src/compile-arm.S @@ -9,6 +9,7 @@ details. */ #include "types.h" +#include "target-fields.h" .text @@ -22,14 +23,6 @@ # define GLOBAL(x) x #endif -#define THREAD_STACK 2148 -#define THREAD_SCRATCH 2156 -#define THREAD_CONTINUATION 2160 -#define THREAD_EXCEPTION 44 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2164 -#define THREAD_EXCEPTION_OFFSET 2168 -#define THREAD_EXCEPTION_HANDLER 2172 - #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 #define CONTINUATION_RETURN_ADDRESS_OFFSET 20 @@ -57,7 +50,7 @@ GLOBAL(vmInvoke): ldr r4, [sp, #4] str r4, [sp, #-4]! - str sp, [r0, #THREAD_SCRATCH] + str sp, [r0, #TARGET_THREAD_SCRATCH] // align stack, if necessary eor r4, sp, r3 @@ -88,7 +81,7 @@ LOCAL(vmInvoke_argumentTest): .align 2 GLOBAL(vmInvoke_returnAddress): // restore stack pointer - ldr sp, [r8, #THREAD_SCRATCH] + ldr sp, [r8, #TARGET_THREAD_SCRATCH] // clear MyThread::stack to avoid confusing another thread calling // java.lang.Thread.getStackTrace on this one. See @@ -96,7 +89,7 @@ GLOBAL(vmInvoke_returnAddress): // a reliable stack trace from a thread that might be interrupted at // any point in its execution. mov r5, #0 - str r5, [r8, #THREAD_STACK] + str r5, [r8, #TARGET_THREAD_STACK] .globl GLOBAL(vmInvoke_safeStack) .align 2 @@ -104,7 +97,7 @@ GLOBAL(vmInvoke_safeStack): #ifdef AVIAN_CONTINUATIONS // call the next continuation, if any - ldr r5,[r8,#THREAD_CONTINUATION] + ldr r5,[r8,#TARGET_THREAD_CONTINUATION] cmp r5,#0 beq LOCAL(vmInvoke_exit) @@ -138,10 +131,10 @@ LOCAL(vmInvoke_getAddress): str r11,[sp,r7] ldr r7,[r5,#CONTINUATION_NEXT] - str r7,[r8,#THREAD_CONTINUATION] + str r7,[r8,#TARGET_THREAD_CONTINUATION] // call the continuation unless we're handling an exception - ldr r7,[r8,#THREAD_EXCEPTION] + ldr r7,[r8,#TARGET_THREAD_EXCEPTION] cmp r7,#0 bne LOCAL(vmInvoke_handleException) ldr r7,[r5,#CONTINUATION_ADDRESS] @@ -150,22 +143,22 @@ LOCAL(vmInvoke_getAddress): LOCAL(vmInvoke_handleException): // we're handling an exception - call the exception handler instead mov r11,#0 - str r11,[r8,#THREAD_EXCEPTION] - ldr r11,[r8,#THREAD_EXCEPTION_STACK_ADJUSTMENT] + str r11,[r8,#TARGET_THREAD_EXCEPTION] + ldr r11,[r8,#TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT] ldr r9,[sp] neg r11,r11 str r9,[sp,r11]! - ldr r11,[r8,#THREAD_EXCEPTION_OFFSET] + ldr r11,[r8,#TARGET_THREAD_EXCEPTIONOFFSET] str r7,[sp,r11] - ldr r7,[r8,#THREAD_EXCEPTION_HANDLER] + ldr r7,[r8,#TARGET_THREAD_EXCEPTIONHANDLER] bx r7 LOCAL(vmInvoke_exit): #endif // AVIAN_CONTINUATIONS mov ip, #0 - str ip, [r8, #THREAD_STACK] + str ip, [r8, #TARGET_THREAD_STACK] // restore return type ldr ip, [sp], #4 diff --git a/src/compile-powerpc.S b/src/compile-powerpc.S index 170fe47dd0..667ae40ed7 100644 --- a/src/compile-powerpc.S +++ b/src/compile-powerpc.S @@ -9,6 +9,7 @@ details. */ #include "types.h" +#include "target-fields.h" .text @@ -28,13 +29,6 @@ #endif #define ARGUMENT_BASE BYTES_PER_WORD * LINKAGE_AREA - -#define THREAD_STACK 2148 -#define THREAD_CONTINUATION 2160 -#define THREAD_EXCEPTION 44 -#define THREAD_EXCEPTION_STACK_ADJUSTMENT 2164 -#define THREAD_EXCEPTION_OFFSET 2168 -#define THREAD_EXCEPTION_HANDLER 2172 #define CONTINUATION_NEXT 4 #define CONTINUATION_ADDRESS 16 @@ -121,14 +115,14 @@ GLOBAL(vmInvoke_returnAddress): // a reliable stack trace from a thread that might be interrupted at // any point in its execution. li r5,0 - stw r5,THREAD_STACK(r13) + stw r5,TARGET_THREAD_STACK(r13) .globl GLOBAL(vmInvoke_safeStack) GLOBAL(vmInvoke_safeStack): #ifdef AVIAN_CONTINUATIONS // call the next continuation, if any - lwz r5,THREAD_CONTINUATION(r13) + lwz r5,TARGET_THREAD_CONTINUATION(r13) cmplwi r5,0 beq LOCAL(vmInvoke_exit) @@ -171,10 +165,10 @@ LOCAL(vmInvoke_getPC): stw r7,0(r1) lwz r7,CONTINUATION_NEXT(r5) - stw r7,THREAD_CONTINUATION(r13) + stw r7,TARGET_THREAD_CONTINUATION(r13) // call the continuation unless we're handling an exception - lwz r7,THREAD_EXCEPTION(r13) + lwz r7,TARGET_THREAD_EXCEPTION(r13) cmpwi r7,0 bne LOCAL(vmInvoke_handleException) lwz r7,CONTINUATION_ADDRESS(r5) @@ -184,15 +178,15 @@ LOCAL(vmInvoke_getPC): LOCAL(vmInvoke_handleException): // we're handling an exception - call the exception handler instead li r8,0 - stw r8,THREAD_EXCEPTION(r13) - lwz r8,THREAD_EXCEPTION_STACK_ADJUSTMENT(r13) + stw r8,TARGET_THREAD_EXCEPTION(r13) + lwz r8,TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT(r13) lwz r9,0(r1) subfic r8,r8,0 stwux r9,r1,r8 - lwz r8,THREAD_EXCEPTION_OFFSET(r13) + lwz r8,TARGET_THREAD_EXCEPTIONOFFSET(r13) stwx r7,r1,r8 - lwz r7,THREAD_EXCEPTION_HANDLER(r13) + lwz r7,TARGET_THREAD_EXCEPTIONHANDLER(r13) mtctr r7 bctr diff --git a/src/compile-x86.S b/src/compile-x86.S index d81129765a..a5d0e1930f 100644 --- a/src/compile-x86.S +++ b/src/compile-x86.S @@ -9,6 +9,7 @@ details. */ #include "types.h" +#include "target-fields.h" #define LOCAL(x) .L##x @@ -23,9 +24,6 @@ #ifdef __x86_64__ -#define THREAD_STACK 2224 -#define THREAD_SCRATCH 2240 - #ifdef AVIAN_USE_FRAME_POINTER # define ALIGNMENT_ADJUSTMENT 0 #else @@ -53,7 +51,7 @@ GLOBAL(vmInvoke): // remember this stack position, since we won't be able to rely on // %rbp being restored when the call returns - movq %rsp,THREAD_SCRATCH(%rcx) + movq %rsp,TARGET_THREAD_SCRATCH(%rcx) // save callee-saved registers movq %rbx,0(%rsp) @@ -90,14 +88,14 @@ LOCAL(vmInvoke_argumentTest): .globl GLOBAL(vmInvoke_returnAddress) GLOBAL(vmInvoke_returnAddress): // restore stack pointer - movq THREAD_SCRATCH(%rbx),%rsp + movq TARGET_THREAD_SCRATCH(%rbx),%rsp // clear MyThread::stack to avoid confusing another thread calling // java.lang.Thread.getStackTrace on this one. See // MyProcess::getStackTrace in compile.cpp for details on how we get // a reliable stack trace from a thread that might be interrupted at // any point in its execution. - movq $0,THREAD_STACK(%rbx) + movq $0,TARGET_THREAD_STACK(%rbx) .globl GLOBAL(vmInvoke_safeStack) GLOBAL(vmInvoke_safeStack): @@ -188,7 +186,7 @@ GLOBAL(vmInvoke): // remember this stack position, since we won't be able to rely on // %rbp being restored when the call returns - movq %rsp,THREAD_SCRATCH(%rdi) + movq %rsp,TARGET_THREAD_SCRATCH(%rdi) // save callee-saved registers movq %rbx,0(%rsp) @@ -222,14 +220,14 @@ LOCAL(vmInvoke_argumentTest): .globl GLOBAL(vmInvoke_returnAddress) GLOBAL(vmInvoke_returnAddress): // restore stack pointer - movq THREAD_SCRATCH(%rbx),%rsp + movq TARGET_THREAD_SCRATCH(%rbx),%rsp // clear MyThread::stack to avoid confusing another thread calling // java.lang.Thread.getStackTrace on this one. See // MyProcess::getStackTrace in compile.cpp for details on how we get // a reliable stack trace from a thread that might be interrupted at // any point in its execution. - movq $0,THREAD_STACK(%rbx) + movq $0,TARGET_THREAD_STACK(%rbx) .globl GLOBAL(vmInvoke_safeStack) GLOBAL(vmInvoke_safeStack): @@ -299,9 +297,6 @@ LOCAL(vmJumpAndInvoke_argumentTest): #elif defined __i386__ -#define THREAD_STACK 2148 -#define THREAD_SCRATCH 2156 - #ifdef AVIAN_USE_FRAME_POINTER # define ALIGNMENT_ADJUSTMENT 0 #else @@ -328,7 +323,7 @@ GLOBAL(vmInvoke): // remember this stack position, since we won't be able to rely on // %rbp being restored when the call returns movl 8(%ebp),%eax - movl %esp,THREAD_SCRATCH(%eax) + movl %esp,TARGET_THREAD_SCRATCH(%eax) movl %ebx,0(%esp) movl %esi,4(%esp) @@ -360,14 +355,14 @@ LOCAL(vmInvoke_argumentTest): .globl GLOBAL(vmInvoke_returnAddress) GLOBAL(vmInvoke_returnAddress): // restore stack pointer - movl THREAD_SCRATCH(%ebx),%esp + movl TARGET_THREAD_SCRATCH(%ebx),%esp // clear MyThread::stack to avoid confusing another thread calling // java.lang.Thread.getStackTrace on this one. See // MyProcess::getStackTrace in compile.cpp for details on how we get // a reliable stack trace from a thread that might be interrupted at // any point in its execution. - movl $0,THREAD_STACK(%ebx) + movl $0,TARGET_THREAD_STACK(%ebx) .globl GLOBAL(vmInvoke_safeStack) GLOBAL(vmInvoke_safeStack): diff --git a/src/compile.cpp b/src/compile.cpp index 6b7e4ea6f0..d1518871d3 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1392,7 +1392,7 @@ class Frame { return c->add (TargetBytesPerWord, c->memory (c->register_(t->arch->thread()), Compiler::AddressType, - TargetThreadHeapImage), c->promiseConstant + TARGET_THREAD_HEAPIMAGE), c->promiseConstant (p, Compiler::AddressType)); } else { for (PoolElement* e = context->objectPool; e; e = e->next) { @@ -1622,7 +1622,7 @@ class Frame { ? c->add (TargetBytesPerWord, c->memory (c->register_(t->arch->thread()), Compiler::AddressType, - TargetThreadCodeImage), c->promiseConstant + TARGET_THREAD_CODEIMAGE), c->promiseConstant (new(&context->zone) OffsetPromise (p, - reinterpret_cast(codeAllocator(t)->base)), @@ -1932,8 +1932,7 @@ class Frame { subroutine->handle = c->startSubroutine(); this->subroutine = subroutine; - SubroutineCall* call = new - (context->zone.allocate(sizeof(SubroutineCall))) + SubroutineCall* call = new(&context->zone) SubroutineCall(subroutine, returnAddress); context->eventLog.append(PushSubroutineEvent); @@ -3380,7 +3379,7 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall, frame->absoluteAddressOperand(returnAddressPromise), TargetBytesPerWord, c->memory (c->register_(t->arch->thread()), Compiler::AddressType, - TargetThreadTailAddress)); + TARGET_THREAD_TAILADDRESS)); c->exit (c->constant @@ -5563,7 +5562,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, (context->bootContext ? c->add (TargetBytesPerWord, c->memory (c->register_(t->arch->thread()), Compiler::AddressType, - TargetThreadCodeImage), address) + TARGET_THREAD_CODEIMAGE), address) : address); Compiler::State* state = c->saveState(); @@ -6110,7 +6109,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, ? c->add (TargetBytesPerWord, c->memory (c->register_(t->arch->thread()), Compiler::AddressType, - TargetThreadCodeImage), entry) + TARGET_THREAD_CODEIMAGE), entry) : entry, TargetBytesPerWord)); @@ -7033,7 +7032,7 @@ finish(MyThread* t, FixedAllocator* allocator, Context* context) // of cycles if another thread compiles the same method in parallel, // which might be mitigated by fine-grained, per-method locking): c->compile(context->leaf ? 0 : stackOverflowThunk(t), - TargetThreadStackLimit); + TARGET_THREAD_STACKLIMIT); // we must acquire the class lock here at the latest @@ -8529,6 +8528,16 @@ public: Processor::CompilationHandler* handler; }; +template +int checkConstant(MyThread* t, size_t expected, T C::* field, const char* name) { + size_t actual = reinterpret_cast(&(t->*field)) - reinterpret_cast(t); + if(expected != actual) { + fprintf(stderr, "constant mismatch (%s): \n\tconstant says: %d\n\tc++ compiler says: %d\n", name, (unsigned) expected, (unsigned) actual); + return 1; + } + return 0; +} + class MyProcessor: public Processor { public: class Thunk { @@ -8605,38 +8614,25 @@ class MyProcessor: public Processor { t->codeImage = codeImage; t->thunkTable = thunkTable; - if (false) { - fprintf(stderr, "stack %d\n", - difference(&(t->stack), t)); - fprintf(stderr, "scratch %d\n", - difference(&(t->scratch), t)); - fprintf(stderr, "continuation %d\n", - difference(&(t->continuation), t)); - fprintf(stderr, "exception %d\n", - difference(&(t->exception), t)); - fprintf(stderr, "exceptionStackAdjustment %d\n", - difference(&(t->exceptionStackAdjustment), t)); - fprintf(stderr, "exceptionOffset %d\n", - difference(&(t->exceptionOffset), t)); - fprintf(stderr, "exceptionHandler %d\n", - difference(&(t->exceptionHandler), t)); - fprintf(stderr, "tailAddress %d\n", - difference(&(t->tailAddress), t)); - fprintf(stderr, "stackLimit %d\n", - difference(&(t->stackLimit), t)); - fprintf(stderr, "ip %d\n", - difference(&(t->ip), t)); - fprintf(stderr, "virtualCallTarget %d\n", - difference(&(t->virtualCallTarget), t)); - fprintf(stderr, "virtualCallIndex %d\n", - difference(&(t->virtualCallIndex), t)); - fprintf(stderr, "heapImage %d\n", - difference(&(t->heapImage), t)); - fprintf(stderr, "codeImage %d\n", - difference(&(t->codeImage), t)); - fprintf(stderr, "thunkTable %d\n", - difference(&(t->thunkTable), t)); - exit(0); + int mismatches = + checkConstant(t, TARGET_THREAD_EXCEPTION, &Thread::exception, "TARGET_THREAD_EXCEPTION") + + checkConstant(t, TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT, &MyThread::exceptionStackAdjustment, "TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT") + + checkConstant(t, TARGET_THREAD_EXCEPTIONOFFSET, &MyThread::exceptionOffset, "TARGET_THREAD_EXCEPTIONOFFSET") + + checkConstant(t, TARGET_THREAD_EXCEPTIONHANDLER, &MyThread::exceptionHandler, "TARGET_THREAD_EXCEPTIONHANDLER") + + checkConstant(t, TARGET_THREAD_IP, &MyThread::ip, "TARGET_THREAD_IP") + + checkConstant(t, TARGET_THREAD_STACK, &MyThread::stack, "TARGET_THREAD_STACK") + + checkConstant(t, TARGET_THREAD_NEWSTACK, &MyThread::newStack, "TARGET_THREAD_NEWSTACK") + + checkConstant(t, TARGET_THREAD_TAILADDRESS, &MyThread::tailAddress, "TARGET_THREAD_TAILADDRESS") + + checkConstant(t, TARGET_THREAD_VIRTUALCALLTARGET, &MyThread::virtualCallTarget, "TARGET_THREAD_VIRTUALCALLTARGET") + + checkConstant(t, TARGET_THREAD_VIRTUALCALLINDEX, &MyThread::virtualCallIndex, "TARGET_THREAD_VIRTUALCALLINDEX") + + checkConstant(t, TARGET_THREAD_HEAPIMAGE, &MyThread::heapImage, "TARGET_THREAD_HEAPIMAGE") + + checkConstant(t, TARGET_THREAD_CODEIMAGE, &MyThread::codeImage, "TARGET_THREAD_CODEIMAGE") + + checkConstant(t, TARGET_THREAD_THUNKTABLE, &MyThread::thunkTable, "TARGET_THREAD_THUNKTABLE") + + checkConstant(t, TARGET_THREAD_STACKLIMIT, &MyThread::stackLimit, "TARGET_THREAD_STACKLIMIT"); + + if(mismatches > 0) { + fprintf(stderr, "%d constant mismatches\n", mismatches); + abort(t); } t->init(); @@ -9801,7 +9797,7 @@ compileCall(MyThread* t, Context* c, ThunkIndex index, bool call = true) Assembler* a = c->assembler; if (processor(t)->bootImage) { - Assembler::Memory table(t->arch->thread(), TargetThreadThunkTable); + Assembler::Memory table(t->arch->thread(), TARGET_THREAD_THUNKTABLE); Assembler::Register scratch(t->arch->scratch()); a->apply(Move, TargetBytesPerWord, MemoryOperand, &table, TargetBytesPerWord, RegisterOperand, &scratch); @@ -9827,7 +9823,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) { Context context(t); Assembler* a = context.assembler; - a->saveFrame(TargetThreadStack, TargetThreadIp); + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.default_.frameSavedOffset = a->length(); @@ -9860,19 +9856,19 @@ compileThunks(MyThread* t, FixedAllocator* allocator) TargetBytesPerWord, RegisterOperand, &class_); Assembler::Memory virtualCallTargetDst - (t->arch->thread(), TargetThreadVirtualCallTarget); + (t->arch->thread(), TARGET_THREAD_VIRTUALCALLTARGET); a->apply(Move, TargetBytesPerWord, RegisterOperand, &class_, TargetBytesPerWord, MemoryOperand, &virtualCallTargetDst); Assembler::Register index(t->arch->virtualCallIndex()); Assembler::Memory virtualCallIndex - (t->arch->thread(), TargetThreadVirtualCallIndex); + (t->arch->thread(), TARGET_THREAD_VIRTUALCALLINDEX); a->apply(Move, TargetBytesPerWord, RegisterOperand, &index, TargetBytesPerWord, MemoryOperand, &virtualCallIndex); - a->saveFrame(TargetThreadStack, TargetThreadIp); + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.defaultVirtual.frameSavedOffset = a->length(); @@ -9895,7 +9891,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) { Context context(t); Assembler* a = context.assembler; - a->saveFrame(TargetThreadStack, TargetThreadIp); + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.native.frameSavedOffset = a->length(); @@ -9905,7 +9901,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) compileCall(t, &context, invokeNativeIndex); a->popFrameAndUpdateStackAndReturn - (t->arch->alignFrameSize(1), TargetThreadNewStack); + (t->arch->alignFrameSize(1), TARGET_THREAD_NEWSTACK); p->thunks.native.length = a->endBlock(false)->resolve(0, 0); @@ -9916,7 +9912,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) { Context context(t); Assembler* a = context.assembler; - a->saveFrame(TargetThreadStack, TargetThreadIp); + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.aioob.frameSavedOffset = a->length(); @@ -9934,7 +9930,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) { Context context(t); Assembler* a = context.assembler; - a->saveFrame(TargetThreadStack, TargetThreadIp); + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.stackOverflow.frameSavedOffset = a->length(); @@ -9952,7 +9948,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) { { Context context(t); Assembler* a = context.assembler; - a->saveFrame(TargetThreadStack, TargetThreadIp); + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); p->thunks.table.frameSavedOffset = a->length(); @@ -9971,7 +9967,7 @@ compileThunks(MyThread* t, FixedAllocator* allocator) Context context(t); \ Assembler* a = context.assembler; \ \ - a->saveFrame(TargetThreadStack, TargetThreadIp); \ + a->saveFrame(TARGET_THREAD_STACK, TARGET_THREAD_IP); \ \ p->thunks.table.frameSavedOffset = a->length(); \ \ diff --git a/src/target-fields.h b/src/target-fields.h new file mode 100644 index 0000000000..3481d4516e --- /dev/null +++ b/src/target-fields.h @@ -0,0 +1,63 @@ +/* Copyright (c) 2011, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +#ifndef AVIAN_TARGET_FIELDS_H +#define AVIAN_TARGET_FIELDS_H + + +#ifdef TARGET_BYTES_PER_WORD +# if (TARGET_BYTES_PER_WORD == 8) + +#define TARGET_THREAD_EXCEPTION 80 +#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2256 +#define TARGET_THREAD_EXCEPTIONOFFSET 2264 +#define TARGET_THREAD_EXCEPTIONHANDLER 2272 + +#define TARGET_THREAD_IP 2216 +#define TARGET_THREAD_STACK 2224 +#define TARGET_THREAD_NEWSTACK 2232 +#define TARGET_THREAD_SCRATCH 2240 +#define TARGET_THREAD_CONTINUATION 2248 +#define TARGET_THREAD_TAILADDRESS 2280 +#define TARGET_THREAD_VIRTUALCALLTARGET 2288 +#define TARGET_THREAD_VIRTUALCALLINDEX 2296 +#define TARGET_THREAD_HEAPIMAGE 2304 +#define TARGET_THREAD_CODEIMAGE 2312 +#define TARGET_THREAD_THUNKTABLE 2320 +#define TARGET_THREAD_STACKLIMIT 2368 + +# elif (TARGET_BYTES_PER_WORD == 4) + +#define TARGET_THREAD_EXCEPTION 44 +#define TARGET_THREAD_EXCEPTIONSTACKADJUSTMENT 2164 +#define TARGET_THREAD_EXCEPTIONOFFSET 2168 +#define TARGET_THREAD_EXCEPTIONHANDLER 2172 + +#define TARGET_THREAD_IP 2144 +#define TARGET_THREAD_STACK 2148 +#define TARGET_THREAD_NEWSTACK 2152 +#define TARGET_THREAD_SCRATCH 2156 +#define TARGET_THREAD_CONTINUATION 2160 +#define TARGET_THREAD_TAILADDRESS 2176 +#define TARGET_THREAD_VIRTUALCALLTARGET 2180 +#define TARGET_THREAD_VIRTUALCALLINDEX 2184 +#define TARGET_THREAD_HEAPIMAGE 2188 +#define TARGET_THREAD_CODEIMAGE 2192 +#define TARGET_THREAD_THUNKTABLE 2196 +#define TARGET_THREAD_STACKLIMIT 2220 + +# else +# error +# endif +#else +# error +#endif + +#endif \ No newline at end of file diff --git a/src/target.h b/src/target.h index 071a4d743a..996d76348f 100644 --- a/src/target.h +++ b/src/target.h @@ -11,6 +11,8 @@ #ifndef TARGET_H #define TARGET_H +#include "target-fields.h" + namespace vm { template @@ -90,19 +92,6 @@ targetVW(T v) typedef uint64_t target_uintptr_t; typedef int64_t target_intptr_t; -const unsigned TargetBytesPerWord = 8; - -const unsigned TargetThreadIp = 2216; -const unsigned TargetThreadStack = 2224; -const unsigned TargetThreadNewStack = 2232; -const unsigned TargetThreadTailAddress = 2280; -const unsigned TargetThreadVirtualCallTarget = 2288; -const unsigned TargetThreadVirtualCallIndex = 2296; -const unsigned TargetThreadHeapImage = 2304; -const unsigned TargetThreadCodeImage = 2312; -const unsigned TargetThreadThunkTable = 2320; -const unsigned TargetThreadStackLimit = 2368; - const unsigned TargetClassFixedSize = 12; const unsigned TargetClassArrayElementSize = 14; const unsigned TargetClassVtable = 128; @@ -121,19 +110,6 @@ targetVW(T v) typedef uint32_t target_uintptr_t; typedef int32_t target_intptr_t; -const unsigned TargetBytesPerWord = 4; - -const unsigned TargetThreadIp = 2144; -const unsigned TargetThreadStack = 2148; -const unsigned TargetThreadNewStack = 2152; -const unsigned TargetThreadTailAddress = 2176; -const unsigned TargetThreadVirtualCallTarget = 2180; -const unsigned TargetThreadVirtualCallIndex = 2184; -const unsigned TargetThreadHeapImage = 2188; -const unsigned TargetThreadCodeImage = 2192; -const unsigned TargetThreadThunkTable = 2196; -const unsigned TargetThreadStackLimit = 2220; - const unsigned TargetClassFixedSize = 8; const unsigned TargetClassArrayElementSize = 10; const unsigned TargetClassVtable = 68; @@ -147,6 +123,8 @@ const unsigned TargetFieldOffset = 8; # error #endif +const unsigned TargetBytesPerWord = TARGET_BYTES_PER_WORD; + const unsigned TargetBitsPerWord = TargetBytesPerWord * 8; const target_uintptr_t TargetPointerMask From cfd9dc6656c61e9e0b955308c6a9ef96b770ab61 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 26 Jun 2012 08:39:23 -0600 Subject: [PATCH 137/140] fix bug which failed to preserve source site during multi-word move The compiler was failing to freeze the source site containing the value of the second word in a multi-word move, leading to mis-compiled code in some cases. --- src/compiler.cpp | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 213c6e81ae..8e118008bb 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -3773,26 +3773,32 @@ class MoveEvent: public Event { and srcSelectSize >= dstSize) { if (dst->target) { - if (dstSize > TargetBytesPerWord - and src->source->registerSize(c) > TargetBytesPerWord) - { - apply(c, Move, srcSelectSize, src->source, src->source, - dstSize, dst->target, dst->target); - - if (live(c, dst) == 0) { - removeSite(c, dst, dst->target); - if (dstSize > TargetBytesPerWord) { - removeSite(c, dst->nextWord, dst->nextWord->target); + if (dstSize > TargetBytesPerWord) { + if (src->source->registerSize(c) > TargetBytesPerWord) { + apply(c, Move, srcSelectSize, src->source, src->source, + dstSize, dst->target, dst->target); + + if (live(c, dst) == 0) { + removeSite(c, dst, dst->target); + if (dstSize > TargetBytesPerWord) { + removeSite(c, dst->nextWord, dst->nextWord->target); + } } - } - } else { - maybeMove(c, Move, TargetBytesPerWord, TargetBytesPerWord, src, - TargetBytesPerWord, dst, dstLowMask); - if (dstSize > TargetBytesPerWord) { + } else { + src->nextWord->source->freeze(c, src->nextWord); + + maybeMove(c, Move, TargetBytesPerWord, TargetBytesPerWord, src, + TargetBytesPerWord, dst, dstLowMask); + + src->nextWord->source->thaw(c, src->nextWord); + maybeMove (c, Move, TargetBytesPerWord, TargetBytesPerWord, src->nextWord, TargetBytesPerWord, dst->nextWord, dstHighMask); } + } else { + maybeMove(c, Move, TargetBytesPerWord, TargetBytesPerWord, src, + TargetBytesPerWord, dst, dstLowMask); } } else { Site* low = pickSiteOrMove(c, src, dst, 0, 0); From 156644b8e5581703202d0839805db8a275e3f890 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 26 Jun 2012 10:43:47 -0600 Subject: [PATCH 138/140] fix incorrect array sizing in populateMultiArray We were assuming the array element size was always the native word size, which is not correct in general for primitive arrays, and this led to wasted space at best and memory corruption at worst. --- src/machine.cpp | 5 ++++- test/Floats.java | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/machine.cpp b/src/machine.cpp index 67f70196fe..964bfd5452 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -4889,7 +4889,10 @@ populateMultiArray(Thread* t, object array, int32_t* counts, PROTECT(t, class_); for (int32_t i = 0; i < counts[index]; ++i) { - object a = makeArray(t, counts[index + 1]); + object a = makeArray + (t, ceiling + (counts[index + 1] * classArrayElementSize(t, class_), BytesPerWord)); + arrayLength(t, a) = counts[index + 1]; setObjectClass(t, a, class_); set(t, array, ArrayBody + (i * BytesPerWord), a); diff --git a/test/Floats.java b/test/Floats.java index 2e869a9a87..723b899a1a 100644 --- a/test/Floats.java +++ b/test/Floats.java @@ -260,5 +260,17 @@ public class Floats { int result = Float.floatToIntBits(number); expect(result == orig); } + + for (int x = 0; x < 1000; ++x) { + int m = 100; + int n = 200; + double array[][] = new double[m][n]; + + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + array[i][j] = 1234567890.0; + } + } + } } } From e6e65ecfdc9d226ba06cd98d48c30150098d62d9 Mon Sep 17 00:00:00 2001 From: Mike Jensen Date: Wed, 14 Mar 2012 14:42:58 -0600 Subject: [PATCH 139/140] The file already contains the leading slash. hotspot URL.getFile() also returns a leading slash, so instead of removing the leading slash on the file, we just wont append an extra one here --- classpath/java/net/URLStreamHandler.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/classpath/java/net/URLStreamHandler.java b/classpath/java/net/URLStreamHandler.java index 0e08bf45da..181f8868df 100644 --- a/classpath/java/net/URLStreamHandler.java +++ b/classpath/java/net/URLStreamHandler.java @@ -72,9 +72,6 @@ public abstract class URLStreamHandler { } } if (url.getFile() != null) { - if (url.getHost() != null) { - sb.append("/"); - } sb.append(url.getFile()); } return sb.toString(); From 0c28fd828981853dd9728c1d58a8eee00e561c01 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 28 Jun 2012 10:30:49 -0600 Subject: [PATCH 140/140] fix C++11 errors in heapdump.cpp --- src/heapdump.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/heapdump.cpp b/src/heapdump.cpp index 2f70e80c5f..da283e61a1 100644 --- a/src/heapdump.cpp +++ b/src/heapdump.cpp @@ -34,7 +34,11 @@ write1(FILE* out, uint8_t v) void write4(FILE* out, uint32_t v) { - uint8_t b[] = { v >> 24, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF }; + uint8_t b[] = { static_cast( v >> 24 ), + static_cast((v >> 16) & 0xFF), + static_cast((v >> 8) & 0xFF), + static_cast( v & 0xFF) }; + size_t n UNUSED = fwrite(b, 4, 1, out); }