📄 sparcjitcodegen.java
字号:
/** use just-in-time compilation to generate code for methods * @version $Id: SPARCJITCodeGen.java,v 1.7 1999/04/06 03:30:37 pab Exp $ *//* This is part of the Just-In-Time compiler for the Toba system. */package toba.jit;/* We need the basic Toba runtime data structures, and the classfile * structures. */import toba.runtime.*;import toba.classfile.*;class JITCodeGen extends CodeGen { /** Initialize the CodeGen class so its generator points to us. * This must be done before anybody touches code generation, because * the system class loader is going to look at CodeGen.generator, * and if it's null will die a quick and painful death. */ public static void Initialize () { JITCodeGen jcg; System.err.println ("SPARC JIT code generation has not been updated for a very long time."); System.err.println ("Go through SPARCJITCodeGen.java and update all the REQUIRE statements."); System.exit (1); /* Verify our requirements */ CodeGen.verifyRequirements (); /* Set the global code generator to use one of us. */ CodeGen.setGenerator (jcg = new JITCodeGen ());// jcg.InitInstrumentation (); } /* Chances are, we'll have done this explicitly (since CodeGen.generator * can be examined without being an active use of JITCodeGen), but * just in case.... */ static { Initialize(); } /** Trivial constructor */ public JITCodeGen () { super(); } /** Return the native data address of a java array. * Toba hash code: _O_TCJx0 */ public native static long getArrayDataAddress (Object ap); /** Return a pointer to a C-format string containing this data. * Toba hash code: _S_Z43yi */ public native static long getStringAddress (String s); /* Primitive instrumentation support: counts the number of instructions * executed dynamically in code jit'd with this code generator, and * emits that information at the end of the program. */ private int instrcounts []; // Array of counts private long icaddr; // Native pointer to array data public void InitInstrumentation () { int i; instrcounts = new int [256]; i = instrcounts.length; while (0 <= --i) { instrcounts [i] = 0; } icaddr = getArrayDataAddress (instrcounts); } public void SummarizeInstrumentation () { int i; if (0 == icaddr) { return; } for (i = 0; i < instrcounts.length; i++) { if (0 != instrcounts [i]) { Opcode opc = Opcode.lookupOpcode (i); System.out.println (opc.name + ": " + instrcounts [i]); } } } /** Allocate a block of sz bytes in uncollectable memory. * @param sz number of bytes we need * @returns address of allocated block * Toba Hash: _i_qYFS3 */ private static native long allocUncolMemory (int sz); /* Function ID values to name functions. Must match the defs in * runtime/jit_JITCodeGen.c. */ static final int FID_new = 1; static final int FID_anewarray = 2; static final int FID_initclass = 3; static final int FID_vmnewarray = 4; static final int FID_getarraylen = 5; static final int FID_geteltoffs = 6; static final int FID_intdiv = 7; static final int FID_intrem = 8; static final int FID_longdiv = 9; static final int FID_longrem = 10; static final int FID_longmul = 11; static final int FID_remdr = 12; static final int FID_dtoi = 13; static final int FID_dtol = 14; static final int FID_longshift = 15; static final int FID_long2f = 16; static final int FID_long2d = 17; static final int FID_longcmp = 18; static final int FID_puts = 19; static final int FID_throwNPE = 20; static final int FID_mythread = 21; static final int FID_sthread_got_exc = 22; static final int FID_setjmp = 23; static final int FID_longjmp = 24; static final int FID_findhandler = 25; static final int FID_athrow = 26; static final int FID_monitorenter = 27; static final int FID_monitorexit = 28; static final int FID_throwCCE = 29; static final int FID_instanceof = 30; static final int FID_findinterface = 31; static final int FID_throwNASE = 32; static final int FID_enterclass = 33; static final int FID_exitclass = 34; static final int FID_backjumpfn = 35; /** Return some arbitrary function's address * @param fid an index naming the function we want * @returns address as long * Toba hash code: _i_m3SYh */ static native long getFuncAddr (int fid); static final int OID_mythread_jmpbuf = 1; static final int OID_mythread_exception = 2; static final int OID_class_flags = 3; static final int OID_class_nsupers = 4; static final int OID_class_supers = 5; static final int OID_mtgeneric_f = 6; /** Return the offset within a structure of a given field * @param oid an index naming the structure offset we want * @returns offset as int * Toba hash code: _i_N1XnB */ static native int getFieldOffset (int oid); /** Return a pointer to the cl_Foo structure for the primitive type * Foo. * @param tid Opcode.T_Foo code for type foo * @param getArray Return pointer to acl_Foo.C instead of cl_Foo * @returns address as long * Toba hash code: _ii_QHITB */ static native long getNPprimclass (int tid, int getArray); SPARC code; // Where the code is built up int frame_size; // Size of activation record /* To handle exceptions, we need the following local variables: * + struct mythread * tdata; * + void * oldbuf; * + volatile int pc; // or monitorheld, for syncwrappers * + jmp_buf newbuf; */ private static final int ARLV_NumVars = 6; private static final int ARLV_methname = 5; // char * methodname private static final int ARLV_insref = 4; // Object instance_ref, for sync method private static final int ARLV_tdata = 3; // struct mythread * private static final int ARLV_pc = 2; // volatile int (overlaid with monitorheld) private static final int ARLV_monitorheld = 2; // volatile int (overlaid with pc) private static final int ARLV_oldbuf = 1; // void * private static final int ARLV_newbuf = 0; // jmp_buf /* Probably the first few are one word, but maybe not. jmp_buf is a * pretty good sized structure. The first array of ints is * initialized to the sizes of these objects; the second to their * offsets within an activation record. */ private static int excOheadSize []; private static int excOheadOffs []; private static int excOheadTotal; /** Return the number of bytes required to hold each of the local * overhead variables. The order of storage must match the index * ordering of ARLV_foo above. * @returns array of ints with variable sizes. * Toba hash code: __Ds3WL */ private static native int[] getOverheadSize (); static { int offs; int i; excOheadSize = getOverheadSize (); excOheadOffs = new int [excOheadSize.length]; offs = 0; for (i = 0; i < excOheadSize.length; i++) { if (4 < excOheadSize [i]) { // 8-byte align large elements offs = (7 + offs) & ~0x07; } else { // 4-byte align normal elements offs = (3 + offs) & ~0x03; } excOheadOffs [i] = offs; offs += excOheadSize [i]; } // 8-byte align whatever follows excOheadTotal = (7 + offs) & ~0x07; /* Go through and update the offsets so we can get to values * at %fp[excOheadOffs[ARLV]]. */ for (i = 0; i < excOheadOffs.length; i++) { excOheadOffs [i] = - (excOheadTotal - excOheadOffs [i]); } } /* This is the overhead size for this code's AR: either 0 or * excOheadTotal */ int overheadSize; /** Convert from local variable number to an offset in bytes from the * frame pointer. * @param lvi The local variable offset; zero starts 4bytes+FPXFSIZ below %fp * @returns offset of local variable address */ private int LVOffs (int lvi) { return - (SPARC.ALUFPUXFERSIZE + overheadSize + 4 * (1 + lvi)); } /** Allocate activation record and preserve parameters. * Copies parameters using SPARC calling convention into the local * variable stack as well as (for safety, though we don't use it) * the standard register dump area. * @param m method for which we're generating code * @param ndata number of words to reserve for local data; -1 for normal method */ private void Prologue (Method m, // What we're generating code for int ndata) // Number of data words for special AR { int i; // General purpose index int maxcaw; // Maximum callee argument words int aw; // Callee argument words /* Allocate an activation record. We start with the minimum frame * for a SPARC AR. */ frame_size = SPARC.MINFRAME; /* What kind of AR are we generating? */ if (0 <= ndata) { /* If we were told a non-zero amount of local data to store, just do * that. We're probably generating the AR for a synchronization * wrapper. NB: The caller is responsible for setting overheadSize, * _before_ this function is called. */ frame_size += overheadSize; frame_size += 4 * ndata; } else { /* We're computing what's needed for the method under consideration. * Now, if there's an exception handler, we need to add local storage * for some support data. */ overheadSize = 0; if (0 < m.handlers.length) { overheadSize = excOheadTotal; } frame_size += overheadSize; /* Now add space for the evaluation stack; locals first, followed * by evaluation elements */ frame_size += 4 * (m.max_locals + m.max_stack); /* Determine the maximum number of argument words in any callee * of this procedure. */ maxcaw = 0; for (i = 0; i < m.instrs.length; i++) { if ((aw = m.instrs [i].argwords()) > maxcaw) { maxcaw = aw; } } /* Subtract off 6 for what we can fit in registers. If no call needs * more than 6 registers, set this to zero. */ maxcaw -= 6; if (0 > maxcaw) { maxcaw = 0; } /* Extend frame to handle overflow arguments, right above the * register dump area. */ frame_size += 4 * maxcaw;// System.out.println ("Frame size " + frame_size + " covering " + m.max_locals +// " locals, " + m.max_stack + " stack, " + maxcaw + " overflow args"); } /* Round frame size to be double-word aligned. */ if (4 == (frame_size % 8)) { frame_size += 4; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -