📄 codeblock.java
字号:
* copy stuff. We hack around that with setAllNativeCode * which prevents the installation copy, but it's not * absolutely clear that this code here and that in * JITCodeGen.java where the brLOADDynNative backpatch * is created are fully in sync. */ if (null != syncwrap_bpi) { syncwrap_bpi.setLongVal (addr); if (syncwrap_bpi.isDone) { syncwrap_bpi.isDone = false; doBackPatch (syncwrap_bpi); } } else { setMethodEntry (addr); setAllNativeCode (true); } break; default: throw new InternalError ("Unrecognized backpatch type " + bpi.brtype); } bpi.isDone = true; return; } /** Resolve all unresolved references and addresses in the code cache. */ protected void backpatchCode () { BackpatchInfo bpi; // Chain through backpatch records long addr; // Generic address /* Do all the normal backpatches we have queued up. */ bpi = bpinfo; while (null != bpi) { if (! bpi.isDone) { doBackPatch (bpi); } bpi = bpi.getNext (); } } /** Reserve space for code that will need a literal value only available after linking. * This version does something with a reference value. * @param brtype integer call code * @param ins instruction that evoked the reference * @param treg the target register for backpatches, where appropriate * @param or Reference to variable, method, or class; null if intra-function branch * @returns BackpatchInfo the structure encoding this backpatch */ public BackpatchInfo reserveCode (int brtype, // Type of reservation needed Instr ins, // Instruction evoking operation Object treg, // Target register of operation Object or) // Reference to decode { BackpatchInfo bpi; // Backpatch object generated here byte instr []; // Instructions to implement backpatch int nui; // Number of UNIMPs inserted so far /* No matter whether the target has been resolved or not, we can't * emit code now, because we don't know where our %pc will be, and * the call is often with a relative address. We also may not know * how many bytes it will take to perform this operation. So what * we do is lock the codeByte array, then evaluate the function * that will generate the actual instruction, with a dummy * argument, and count the number of bytes in what it returns. * That's how much space is required. */ setLockCodeBytes (true); switch (brtype) { case brLOAD: instr = evalBrLOAD (1000, treg); break; case brFIELDLOAD: instr = evalBrLOAD (1000, treg); break; case brCLREFLOAD: instr = evalBrLOAD (1000, treg); break; case brLOADNatCl: instr = evalBrLOAD (1000, treg); break; case brCALL: instr = evalBrCALL (1000); break; case brLOADDynNative: case brOverWriteCode: instr = null; break; default: throw new InternalError ("Unknown object backpatch reservation code " + brtype); } bpi = new BackpatchInfo (brtype, ins, treg, nextByteOffs(), or); bpinfo = bpi.setNext (bpinfo); setLockCodeBytes (false); if (null != instr) { bpi.setInsSeqLen (instr.length); /* Reserve as many bytes as the backpatch requires. Fill the * reserved memory with some instruction that will blow chow if * it gets executed. */ nui = 0; while (nui < instr.length) { byte rv[]; rv = UNIMP (nBackPatches); nui += rv.length; } if (nui != instr.length) { throw new InternalError ("x86: Blew it filling backpatch reservation."); } } ++nBackPatches; return bpi; } /** Reserve space for code that will need a literal value only available after linking. * This version does something with an integral value, usually pc-relative * @param brtype integer call code * @param ins instruction that evoked the reference * @param treg the target register for backpatches, where appropriate * @param lv long integer value * @returns BackpatchInfo the structure encoding this backpatch */ public BackpatchInfo reserveCode (int brtype, // Type of reservation needed Instr ins, // Instruction evoking operation Object treg, // Target register of operation long lv) // Integer value { BackpatchInfo bpi; // Backpatch object generated here byte instr []; // Instructions to implement backpatch int nui; // Number of UNIMPs inserted so far /* No matter whether the target has been resolved or not, we can't * emit code now, because we don't know where our %pc will be, and * the call is often with a relative address. We also may not know * how many bytes it will take to perform this operation. So what * we do is lock the codeByte array, then evaluate the function * that will generate the actual instruction, with a dummy * argument, and count the number of bytes in what it returns. * That's how much space is required. */ setLockCodeBytes (true); switch (brtype) { case brLOADCodeRel: instr = evalBrLOADCodeRel (1000, treg); break; case brLOADCodeLbl: instr = evalBrLOADCodeLbl (1000, treg); break; case brLOADCodeAbs: instr = evalBrLOADCodeAbs (1000, treg); break; case brJUMP: instr = evalBrACALL (1000); break; case brACALL: instr = evalBrACALL (1000); break; case brINITSwitchTable: instr = new byte [0]; break; default: throw new InternalError ("Unknown integral backpatch reservation code " + brtype); } bpi = new BackpatchInfo (brtype, ins, treg, nextByteOffs(), lv); bpinfo = bpi.setNext (bpinfo); bpi.setInsSeqLen (instr.length); /* Reserve as many bytes as the backpatch requires. Fill the * reserved memory with some instruction that will blow chow if * it gets executed. */ setLockCodeBytes (false); nui = 0; while (nui < instr.length) { byte rv[]; rv = UNIMP (nBackPatches); nui += rv.length; } if (nui != instr.length) { throw new InternalError ("x86: Blew it filling backpatch reservation."); } ++nBackPatches; return bpi; } /** Do whatever linking is required to make the code finally work. * For example, we may not have stored target addresses because we * didn't know enough to do them during code generation. */ public synchronized void resolveCode () { long bTime; if (isResolved) { /* In the presence of multiple threads, this routine might * get called multiple times for the same method. Since * it's synchronized, only one resolution will succeed, * but we need to check whether somebody snuck in ahead of * us, and return if so. */ return; } if (0 == mtentry) { throw new InternalError ("Attempt to link code w/o known address"); }// System.err.println ("CodeBlock.resolveCode: called on " + method.cl.name + "." + method.fl.name +// " at " + Long.toHexString (mtentry)); bTime = System.currentTimeMillis (); /* Backpatch the calls and static references that require true * addresses. Does the syncwrap stuff, too. */ try { backpatchCode (); } catch (InternalError e) { System.out.println ("Backpatch caught " + e + " in " + method); throw e; } /* Copy the code into the execution block */ installCode ();// System.err.println ("CodeBlock.resolveCode: installed " + method.cl.name + "." + method.fl.name); /* Build the exception handler table, if there is one. */ long htptr = handlerTableAddress; if (null != method.handlers) { for (int i = 0; i < method.handlers.length; i++) { /* exception handling table is defined in toba.h. If it * changes, fix this, and the EmitExceptHandle code in * the real code generator class. */ /* struct handler { Class class; // exception unsigned short start_pc; unsigned short end_pc; unsigned int handler_pc; // JIT requires this to be at least 32bit }; */ int cls = 0; /* Store the address of the C exception class handled by this range */ if (null != method.handlers [i].type) { ClassRef href = method.handlers [i].type; /* Handler type might not be resolved: make sure it is */ if (! href.isResolved (codeClassLoader)) { Resolve.resolveClassRef (href, codeClassLoader); } cls = (int) ClassRT.getNativeClass (href.getRefClass(codeClassLoader)); } short start_pc = (short) method.handlers [i].start; short end_pc = (short) method.handlers [i].end; int handler_pc = (int) (mtentry + instrToByteOffs [method.pcmap [method.handlers [i].jump]]); CodeGen.pokeInt (htptr, cls); htptr += 4; CodeGen.pokeShort (htptr, start_pc); htptr += 2; CodeGen.pokeShort (htptr, end_pc); htptr += 2; CodeGen.pokeInt (htptr, handler_pc); htptr += 4; } } /* Set the resolve flag, and update the entry point for this function * Don't do that before we're really finished, 'cuz the thread * start routine might read it and start running something before * we finish backpatching, if the resolution procedure is interrupted */ isResolved = true; Class jclass = method.cl.javaClass; Field jfield = method.fl; ClassRT.setMethodAddr (jclass, jfield, mtentry); if (shouldTimeCodegen) { resolveTime = (int) (System.currentTimeMillis () - bTime); System.err.println ("<" + method.cl.name + "." + method.fl.name + ": compile " + method.instrs.length + " instr in " + compileTime + "ms; resolve in " + resolveTime + "ms; " + numCodeBytes + " bytes at 0x" + Long.toHexString ((long) mtentry) + ">"); }// System.err.println ("CodeBlock.resolveCode: done at " + Long.toHexString ((long) mtentry)); return; } protected byte[] getCodeBlock () { byte rv []; rv = new byte [numCodeBytes]; System.arraycopy (codeBytes, 0, rv, 0, numCodeBytes); return rv; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -