?? intel86jitcodegen.java
字號:
break; } /* If haven't already gotten the class address into reg, * put it there */ if (0 != cp) { code.MOV (new Immediate (cp), reg); } return; } /** Take a value of a particular type out of memory and push it onto * the evaluation stack. * @param areg Register containing memory address of value; _not_ %eax * @param tychar Encoded type of object at address */ private void pushFromMemory (Register areg, char tychar) { if (areg.equals (R_eax)) { throw new InternalError ("can't use %eax as address reg in popIntoMemory"); }/* code.freeReg (R_eax); */ /* Load the whosit at areg onto the evaluation stack. If the value * is less than one int, extend to an int, with or without sign, as * appropriate. */ switch (tychar) { default: throw new InternalError ("invalid pushFromMemory type " + tychar); case Field.FT_void: throw new InternalError ("invalid pushFromMemory void data."); case Field.FT_boolean: code.XOR (R_eax, R_eax); code.MOV (new MemoryRef (areg).setRefSize (1), R_al); code.pushES (R_eax); break; case Field.FT_byte: code.XOR (R_eax, R_eax); code.MOV (new MemoryRef (areg).setRefSize (1), R_al); code.PrefixOPSIZE (); code.CBW (); code.CBW (); code.pushES (R_eax); break; case Field.FT_char: code.XOR (R_eax, R_eax); code.PrefixOPSIZE (); code.MOV (new MemoryRef (areg), R_eax); code.pushES (R_eax); break; case Field.FT_short: code.XOR (R_eax, R_eax); code.PrefixOPSIZE (); code.MOV (new MemoryRef (areg).setRefSize (2), R_eax); code.CBW (); code.pushES (R_eax); break; case Field.FT_float: case Field.FT_int: case Field.FT_object: case Field.FT_array: code.MOV (new MemoryRef (areg), R_eax); code.pushES (R_eax); break; case Field.FT_double: case Field.FT_long: code.MOV (new MemoryRef (IMM_4, areg), R_eax); code.pushES (R_eax); // msw code.MOV (new MemoryRef (areg), R_eax); code.pushES (R_eax); // lsw break; } return; } /** Take a value of a particular type off the stack and store it into * memory. * @param areg Register containing memory address of value; _not_ %eax * @param tychar Encoded type of object to be stored at address */ private void popIntoMemory (Register areg, char tychar) { if (areg.equals (R_eax)) { throw new InternalError ("can't use %eax as address reg in popIntoMemory"); } /* Load the whosit at areg onto the evaluation stack. If the value * is less than one int, extend to an int, with or without sign, as * appropriate. */ code.popES (R_eax); switch (tychar) { default: throw new InternalError ("invalid popIntoMemory type " + tychar); case Field.FT_void: throw new InternalError ("invalid popIntoMemory void data."); case Field.FT_boolean: case Field.FT_byte: code.MOV (R_al, new MemoryRef (areg).setRefSize (1)); break; case Field.FT_char: case Field.FT_short: code.PrefixOPSIZE (); code.MOV (R_eax, new MemoryRef (areg)); break; case Field.FT_float: case Field.FT_int: case Field.FT_object: case Field.FT_array: code.MOV (R_eax, new MemoryRef (areg)); break; case Field.FT_double: case Field.FT_long: code.MOV (R_eax, new MemoryRef (areg)); // lsw code.popES (R_eax); code.MOV (R_eax, new MemoryRef (IMM_4, areg)); // msw break; } return; } /* %ebx has been initialized to an object reference. Return one or zero * in %eax depending on whether the object can be cast to the provided * class. */ private void EmitCkInstance (Instr i, ClassRef cr) { int iv; /* code.freeReg (R_eax); */ /* If the target type is Object, the cast always succeeds, whether * the object is of non-array or array class. */ if (cr.name.equals ("java.lang.Object")) { code.MOV (IMM_1, R_eax); return; }/* code.freeReg (); // all of them */ /* Get a pointer to the C class of the object into %o1. */ code.MOV (MR_ebx, R_esi); if (Field.FT_array != cr.name.charAt(0)) { /* Non array objects: if going to an interface, %esi must implement * it; if going to a class, %esi must be a subclass of it. We don't * know yet whether this is a class or an interface, so have to * make the decision at runtime. */ code.reserveCode (CodeBlock.brLOADNatCl, i, R_edi, cr); code.MOV (new MemoryRef (IO_class_flags, R_edi), R_eax); code.TEST (new Immediate (ClassRT.IS_INTERFACE), R_eax); code.Jccn (Intel86.CND_nz, IMM_0); int bo_isiface = code.nextByteOffs (); /* Is not an interface: we're OK iff o2 is a super class of %esi. */ code.MOV (new MemoryRef (IO_class_nsupers, R_esi), R_ecx); code.MOV (new MemoryRef (IO_class_nsupers, R_edi), R_edx); code.SUB (R_edx, R_ecx); code.Jccn (Intel86.CND_l, IMM_0); int bo_fail1 = code.nextByteOffs (); /* OK, %esi->nsupers >= o2->nsupers. See if the superclass up * that high is right. * %esi->supers[%esi->nsupers-%edi->nsupers] == o2 */ code.MOV (new MemoryRef (IO_class_supers, R_esi), R_esi); code.MOV (new MemoryRef (null, R_esi, 4, R_ecx, 4), R_ecx); code.CMP (R_ecx, R_edi); /* If not equal, jump to the failure point */ code.Jccn (Intel86.CND_ne, IMM_0); int bo_fail2 = code.nextByteOffs (); /* Are equal: cast is OK. */ code.MOV (IMM_1, R_eax); code.JMPn (IMM_0); int bo_exit1 = code.nextByteOffs (); /* OK, here on out it's an interface. Just call instanceof. */ code.PatchNearJump (bo_isiface, (code.nextByteOffs() - bo_isiface)); /* We already have %ebx as the object ref, %edi as the target * class pointer. Rearrange to meet the parameter requirements * of instanceof(Object,Class,ArrayDim). */ code.PUSH (IMM_0); code.PUSH (R_edi); code.PUSH (R_ebx); code.reserveCode (CodeBlock.brACALL, i, null, FA_instanceof); code.ADD (new Immediate (3*4), R_esp); /* Jump to exit */ code.JMPn (IMM_0); int bo_exit2 = code.nextByteOffs (); /* Fail: backpatch all fails, and clear the return value */ code.PatchNearJump (bo_fail1, (code.nextByteOffs() - bo_fail1)); code.PatchNearJump (bo_fail2, (code.nextByteOffs() - bo_fail2)); code.XOR (R_eax, R_eax); /* Exit: backpatch all exits */ code.PatchNearJump (bo_exit1, (code.nextByteOffs() - bo_exit1)); code.PatchNearJump (bo_exit2, (code.nextByteOffs() - bo_exit2)); return; } if ((Field.FT_array != cr.name.charAt(1)) && (Field.FT_object != cr.name.charAt(1))) { /* Array of primitive object: class has to be array of that * primitive object. Load the pointer to the appropriate class, * hiding inside the acl_Foo object. */ loadClassPointer (i, cr, 1, R_edi); /* Presume this will work, to simplify control flow */ code.MOV (IMM_1, R_eax); /* See if classes match */ code.CMP (R_esi, R_edi); code.Jccn (Intel86.CND_e, IMM_0); int bo_exit = code.nextByteOffs (); /* Nope, set to fail. */ code.XOR (R_eax, R_eax); /* Here's where we go out. */ code.PatchNearJump (bo_exit, (code.nextByteOffs() - bo_exit)); } /* General array of object. Count up the array depth, * and call instanceof checking against the base class of the * target class. */ int n = 0; while (Field.FT_array == cr.name.charAt(n)) { ++n; } if (Field.FT_object == cr.name.charAt(n)) { /* Problem: loadClassPointer can't get the base class, because * classes haven't been resolved yet. So just call as 0, and have * instanceof do the walk down the array chain. */ /* !!TOFIX!! We really need to be able to get ClassRefs that * will be resolved, when we only have a string name. */ n = 0; } /* Already have object reference in %ebx. Put class pointer into * %edi, presuming this loadClassPointer function will go down to * the base object. Put array rank into %edi. Call instanceof. */ code.PUSH (new Immediate (n)); loadClassPointer (i, cr, 0, R_eax); code.PUSH (R_eax); code.PUSH (R_ebx); code.reserveCode (CodeBlock.brACALL, i, null, FA_instanceof); code.ADD (new Immediate (3*4), R_esp); } /** Add the code for a JVM instruction to the code cache * @param i the instruction to generate code for * @param m the method that i appears in */ private void EmitCode (Method m, // Method we're in int idx) // Index of instruction to work with { Instr i; // Instruction we're working with Opcode opc; // Opcode for instruction int lvi; // Local variable index MethodRef mr; // MethodRef for operand VariableRef vr; // VariableRef for operand FieldRef fr; // FieldRef for operand Constant cn; // Constant for operand Class c; // Class for m Field f; // Field for m in c int aw; // Number of argwords int ab; // Number of arg bytes long adr; // Generic address value String opdtype; // Type of operand int iv; // Intermediate int value long lv; // Intermediate long value ClassRef cr; // Class reference value char tychar; // Type character, from Field.FT_* int boffs; // Branch offset, for local backpatching int boffs2; // Another branch offset, for local backpatching int boffs3; // Another branch offset, for local backpatching BackpatchInfo bpi; // Backpatch info structure created i = m.instrs [idx];// System.out.println (i.toString()); /* Mark where code related to this instruction starts. */ if (idx >= code.instrToByteOffs.length) { throw new InternalError ("EmitCode: idx " + idx + " but iTBO length " + code.instrToByteOffs.length + " with instr len " + m.instrs.length); } code.instrToByteOffs [idx] = code.nextByteOffs (); /* Tell the low-level generator where the evaluation stack * is at right now. For the most part, this will be either the same * as the previous instruction, or zero at the top of a basic block, * but in the presence of trinary operators it can be non-empty at * the start of a basic block. We have to assume that the evaluation * stack is in a check-pointed state then. */// int oesd = code.getEStackDepth ();// int nesd = i.before.length ();// if ((oesd != nesd) && (0 != nesd) && (Opcode.POP != i.opcode.code)) {// System.out.println ("In " + m.cl.name + "." + m.fl.name + " from:\n" + m.instrs[idx-1] + "\nset estack from " + code.getEStackDepth () + " to " + i.before.length () + " before:\n" + i);// } code.setEStackTop (i.before.length()); /* If we're doing exception handling, we need to update the pc * variable so we can tell where the exception was raised. */ if (0 < m.handlers.length) { code.MOV (new Immediate (i.pc), excOheadAddr (ARLV_pc)); } /* If instrumentation is enabled, increment the counter for this * instruction. */ if (null != instrcounts) { code.INC (new MemoryRef (new Immediate ((int) (icaddr + 4 * i.opcode.code)), null)); } /* We can often deal with a bunch of instructions at once, so * we switch on the opcode kind, rather than the exact opcode. */ opc = i.opcode; switch (opc.kind) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -