?? intel86jitcodegen.java
字號:
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 (); /* Overhead initialization */ static { int offs; int i; /* Get the size of the local variables, then compute their offsets, * with necessary alignments. */ 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 %ebp[- (overheadOffs + excOheadOffs[ARLV])]. */ for (i = 0; i < excOheadOffs.length; i++) { excOheadOffs [i] = (excOheadTotal - excOheadOffs [i]);// System.out.println ("OH " + i + " is at " + excOheadOffs [i] + " of " + excOheadTotal); } } /* This is the offset from %ebp to where the overhead data starts. * Covers: %esi, %edi, %ebx */ private int overheadOffs = 3 * 4; /* This is the overhead size for this code's AR: either 0 or * excOheadTotal */ private int overheadSize; /** Convert from local variable number to a MemoryRef operand representing * a load from the AR. * @param lvi The local variable offset; starts from zero * @returns reference to stack location of local variable */ private MemoryRef LVOffs (int lvi) { return new MemoryRef (new Immediate (- (overheadOffs + overheadSize + 4 * (1 + lvi))), R_ebp); } private MemoryRef excOheadAddr (int arlv) {// System.out.println (arlv + " is " + (overheadOffs + excOheadOffs [arlv]) + " below %ebp"); return new MemoryRef (new Immediate (- (overheadOffs + excOheadOffs [arlv])), R_ebp); } /** Allocate activation record, preserve callee-saved registers, and * copy parameters onto Java stack. * @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// System.out.println ("Method argstack in: " + m.astack + " rstack " + m.rstack); /* Start by saving the old base pointer, and setting the new * one. */ code.PUSH (R_ebp); code.MOV (R_esp, R_ebp); /* Build up the frame size as we add things to the stack */ frame_size = 0; /* Save the basic offset for the overhead information */ overheadOffs = frame_size; /* 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 ((null != m.handlers) && (0 < m.handlers.length)) { overheadSize = excOheadTotal; } frame_size += overheadSize; /* Now add space for local Java variables */ frame_size += 4 * m.max_locals; /* Here's where the Java evaluation stack starts. Inform * the low-level code generator, so it can maintain the ES * pointer when it pushes and pops. */ code.setEStackBase (frame_size); /* Add space for the Java evaluation stack */ frame_size += 4 * m.max_stack; } /* Sanity checks: frame size must be word-aligned */ if (0 != (frame_size % 4)) { throw new InternalError ("frame size not multiple of 4"); } /* Set the stack pointer to be below what we've reserved. */ code.SUB (new Immediate (frame_size), R_esp); /* Presume we're going to modify all the callee-saved registers, so * save them now. */ code.PUSH (R_esi); code.PUSH (R_edi); code.PUSH (R_ebx); /* Stuff the name of this function in the standard location. * NB: We can only do this if there are exception handlers, because * otherwise we didn't allocate space for local variables on * the AR. */ if ((null != m.handlers) && (0 < m.handlers.length)) { code.MOV (new Immediate ((int)getStringAddress (m.cl.name + "." + m.fl.name)), excOheadAddr (ARLV_methname));// code.PUSH (excOheadAddr (ARLV_methname));// code.reserveCode (CodeBlock.brACALL, m.instrs[0], null, FA_puts);// code.ADD (new Immediate (2), R_esp); } /* If we're creating a standard frame for executing Java code, then * store the arguments into the local variable arena. If not, * whoever's creating us should take responsibility for preserving * arguments. */ if (0 > ndata) { int an; // Number of arguments moved int naw; // Number of argument words moved char c; // Char denoting argument type /* The problem here is that the JVM local variables are in the * wrong order relative to how the parameters are passed on * the Intel stack. We need to reverse them; but we can't * reverse the words in 64-bit entities. So we walk through * doing copies from the caller args into the JVM locals * based on the type of the parameters. Fortunately, all * parameters of 1 or 2 bytes are passed as full 4-byte words. */ /* Keep track of the number of words transferred so far. */ naw = 0; /* If this is an instance method, the first whosit is the * object reference. */ if (0 == (m.fl.access & ClassData.ACC_STATIC)) { code.MOV (new MemoryRef (IMM_8, R_ebp), R_eax); code.MOV (R_eax, LVOffs(0)); ++naw; } naw = 0; while (naw < m.astack.length()) { if ('x' == m.astack.charAt (naw)) { /* Copy over a double word, stored LSW MSW, and * preserve its order. */ code.MOV (new MemoryRef (new Immediate (8+4*naw), R_ebp), R_esi); // LSW code.MOV (new MemoryRef (new Immediate (12+4*naw), R_ebp), R_edi); // MSW code.MOV (R_esi, LVOffs (naw+1)); // LSW code.MOV (R_edi, LVOffs (naw)); // MSW naw += 2; } else { /* Copy over a single word */ code.MOV (new MemoryRef (new Immediate (8+4*naw), R_ebp), R_eax); code.MOV (R_eax, LVOffs (naw)); naw++; } } } /* Call the yield function if there is one */ if (null != m.instrs) { emitBackJumpCall (m.instrs[0]); } return; } /* Given an array structure at %ebx, and an index at %eax, make * sure the index is legitimate, and compute the address of the * desired element. The element address is returned in %ebx. */ private void emitEltOffsetCode (int esz, Instr ins) { int sf; /* Make sure the array reference isn't null. */ code.OR (R_ebx, R_ebx); code.Jccn (Intel86.CND_nz, IMM_0); int boffs = code.nextByteOffs (); /* Call throwNullPointerException (0) */ code.PUSH (IMM_0); code.reserveCode (CodeBlock.brACALL, ins, null, FA_throwNPE); /* No need to pop args; we never return here. */ code.UNIMP (0); // sure about that? /* Here's where we end up if we were nz */ code.PatchNearJump (boffs, code.nextByteOffs() - boffs); /* Make sure the index is in range. */ code.OR (R_eax, R_eax); code.Jccn (Intel86.CND_l, IMM_0); boffs = code.nextByteOffs (); /* ecx = ebx->length */ code.MOV (new MemoryRef (IO_barray_length, R_ebx), R_ecx); /* eax < ecx? */ code.CMP (R_ecx, R_eax); code.Jccn (Intel86.CND_l, IMM_0); code.PatchNearJump (boffs, code.nextByteOffs() - boffs); boffs = code.nextByteOffs (); code.PUSH (R_eax); code.PUSH (R_ebx); code.reserveCode (CodeBlock.brACALL, ins, null, FA_throwAIOBE); code.UNIMP (0); // sure about that? /* Here's where we end up if we were in range */ code.PatchNearJump (boffs, code.nextByteOffs() - boffs); code.LEA (new MemoryRef (IO_barray_data, R_ebx, esz, R_eax, 4), R_ebx); return; } /** Generate code to initialize a class if necessary, leaving the class * reference in %ebx. * @param i the instruction that induced the initialization requirement * @param or the reference to the object (FieldRef or ClassRef) that may need to be initialized */ private void emitClassInit (Instr i, Object or) { int boffs; /* Load the address of the native struct class object that is the * basis of the object referred to by fr. */ code.reserveCode (CodeBlock.brLOADNatCl, i, R_ebx, or); /* The first word of the class object is the flag indicating * whether it needs to be initialized. If that's zero, the class * has been initialized, and we skip over the call to the * initializer.*/ code.CMP (IMM_0, MR_ebx); code.Jccn (Intel86.CND_z, IMM_0); boffs = code.nextByteOffs (); code.PUSH (R_ebx); code.reserveCode (CodeBlock.brACALL, i, null, FA_initclass); code.ADD (IMM_4, R_esp); code.PatchNearJump (boffs, code.nextByteOffs() - boffs); } /** Push na arguments off the evaluation stack onto the code stack for * calling a C function. ES args are popped last to first, so first * arg is at top of C stack. MUST NOT TRASH %eax. * @param nwords number of words used as parameters * @returns int number of bytes pushed onto stack */ private int setCallArgs (int nwords) { int an; for (an = 0; an < nwords; an++) { code.PUSH (new MemoryRef (new Immediate (code.peekEStackOffs (an)), R_ebp)); } code.tossES (nwords); return 4*nwords; } /** Get arguments off evaluation stack and put them where they're * needed for the function call. * @param sig Signature of caller's parameters * @returns int number of bytes pushed onto stack */ private int setCallArgs (String sig) { int naw; // Number of words in arguments int an; // Argument word counter an = 0; naw = sig.length () - 1; while (0 <= naw) { if ((0 < naw) && ('x' == sig.charAt (naw-1))) { /* Copy over a double word, stored LSW MSW, and * preserve its order. */ code.PUSH (new MemoryRef (new Immediate (code.peekEStackOffs (an+1)), R_ebp)); // msw code.PUSH (new MemoryRef (new Immediate (code.peekEStackOffs (an)), R_ebp)); // lsw naw -= 2;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -