📄 sparcjitcodegen.java
字号:
} /** Assuming we just got back from a call to the given method, push * the return value onto the evaluation stack. * @param mr MethodRef of called method (FieldRef if interface method) */ private void EmitRetvalStore (FieldRef mr) { String s = mr.signature; switch (s.charAt (s.indexOf (')') + 1)) { case Field.FT_byte: case Field.FT_char: case Field.FT_int: case Field.FT_object: case Field.FT_short: case Field.FT_boolean: case Field.FT_array: code.pushES ("%o0"); break; case Field.FT_float: code.FpushES ("%f0"); break; case Field.FT_long: code.LpushES ("%o0"); break; case Field.FT_double: code.DpushES ("%f0"); break; case Field.FT_void: break; } return; } /** Load the pointer to the C class for type into register * @param i instruction inducing the load * @param cr ClassRef to type we're looking for; not necessarily resolved * @param getArray If nonzero, want the array-of-type instead of base type * @param reg Register pointer should go into */ private void loadClassPointer (Instr i, // Instruction inducing load ClassRef cr, // Reference to class int getArray, // Get array, or base type? String reg) // Name of target register { int cp; // Integer representation of pointer int arank; /* We have here the name of a primitive or reference type. * We need to get the pointer to the struct class that defines * it. */ arank = 0; while (Field.FT_array == cr.name.charAt(arank)) { arank++; } cp = 0; switch (cr.name.charAt (arank)) { case Field.FT_byte: cp = (int) getNPprimclass (Opcode.T_BYTE, getArray); break; case Field.FT_char: cp = (int) getNPprimclass (Opcode.T_CHAR, getArray); break; case Field.FT_double: cp = (int) getNPprimclass (Opcode.T_DOUBLE, getArray); break; case Field.FT_float: cp = (int) getNPprimclass (Opcode.T_FLOAT, getArray); break; case Field.FT_int: cp = (int) getNPprimclass (Opcode.T_INT, getArray); break; case Field.FT_long: cp = (int) getNPprimclass (Opcode.T_LONG, getArray); break; case Field.FT_short: cp = (int) getNPprimclass (Opcode.T_SHORT, getArray); break; case Field.FT_boolean: cp = (int) getNPprimclass (Opcode.T_BOOLEAN, getArray); break; default: /* Something not a primitive class. We should just be able * to load the native class. We'd better not want an * array version of it, though. */ if (0 != getArray) { throw new InternalError ("Don't support loadClassPointer of array non-primitives"); } code.reserveCode (CodeBlock.brLOADNatCl, i, reg, cr); cp = 0; break; } /* If haven't already gotten the class address into reg, * put it there */ if (0 != cp) { code.SETHI (cp, reg); code.SetLo (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 * @param tychar Encoded type of object at address */ private void pushFromMemory (String areg, char tychar) { /* 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.LDUB (areg, 0, "%o7"); break; case Field.FT_byte: code.LDSB (areg, 0, "%o7"); break; case Field.FT_char: code.LDUH (areg, 0, "%o7"); break; case Field.FT_short: code.LDSH (areg, 0, "%o7"); break; case Field.FT_float: case Field.FT_int: case Field.FT_object: code.LD (areg, 0, "%o7"); break; case Field.FT_double: case Field.FT_long: code.LD (areg, 0, "%o7"); // high word code.pushES ("%o7"); code.LD (areg, 4, "%o7"); // low word break; } code.pushES ("%o7"); return; } /** Take a value of a particular type off the stack and store it into * memory. * @param areg Register containing memory address of value * @param tychar Encoded type of object to be stored at address */ private void popIntoMemory (String areg, char tychar) { /* 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 ("%o7"); 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.STB ("%o7", areg, 0); break; case Field.FT_char: case Field.FT_short: code.STH ("%o7", areg, 0); break; case Field.FT_float: case Field.FT_int: case Field.FT_object: code.ST ("%o7", areg, 0); break; case Field.FT_double: case Field.FT_long: code.ST ("%o7", areg, 4); // low word code.popES ("%o7"); code.ST ("%o7", areg, 0); // high word break; } return; } private void EmitCkInstance (Instr i, ClassRef cr) { /* 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 (1, "%o0"); return; } /* Get a pointer to the C class of the object into %o1. */ code.LD ("%o0", 0, "%o1"); if (Field.FT_array != cr.name.charAt(0)) { /* Non array objects: if going to an interface, %o1 must implement * it; if going to a class, %o1 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, "%o2", cr); code.LD ("%o2", getFieldOffset (OID_class_flags), "%o7"); code.ANDcc ("%o7", ClassRT.IS_INTERFACE, "%o7"); int bo_isiface = code.nextByteOffs (); code.BNE (0); code.NOP (); // fill delay slot /* Is not an interface: we're OK iff o2 is a super class of o1. */ code.LD ("%o1", getFieldOffset (OID_class_nsupers), "%o3"); code.LD ("%o2", getFieldOffset (OID_class_nsupers), "%o4"); code.SUBcc ("%o3", "%o4", "%o3"); int bo_fail1 = code.nextByteOffs (); code.BL (0); code.NOP (); // fill delay slot /* OK, o1->nsupers >= o2->nsupers. See if the superclass up * that high is right. * o1->supers[o1->nsupers-o2->nsupers] == o2 */ code.LD ("%o1", getFieldOffset (OID_class_supers), "%o4"); code.SLL ("%o3", 2, "%o3"); // mul by 4 to handle pointer elements code.LD ("%o4", "%o3", "%o3"); code.CMP ("%o3", "%o2"); /* If not equal, jump to the failure point */ int bo_fail2 = code.nextByteOffs (); code.BNE (0); code.NOP (); // fill delay slot /* Are equal: cast is OK. */ code.MOV (1, "%o0"); int bo_exit1 = code.nextByteOffs (); code.BA (0); code.NOP (); // fill delay slot /* OK, here on out it's an interface. Just call instanceof. */ code.PatchDisp22 (bo_isiface, (code.nextByteOffs() - bo_isiface) >>> 2); /* We already have %o0 as the object ref, %o2 as the target * class pointer. Rearrange to meet the parameter requirements * of instanceof(Object,Class,ArrayDim). */ code.MOV ("%o2", "%o1"); code.MOV ("%g0", "%o2"); code.reserveCode (CodeBlock.brACALL, i, "noreg", getFuncAddr (FID_instanceof)); code.NOP (); // fill delay slot int bo_exit2 = code.nextByteOffs (); code.BA (0); code.NOP (); // fill delay slot /* Fail: backpatch all fails, and clear the return value */ code.PatchDisp22 (bo_fail1, (code.nextByteOffs() - bo_fail1) >>> 2); code.PatchDisp22 (bo_fail2, (code.nextByteOffs() - bo_fail2) >>> 2); code.MOV ("%g0", "%o0"); /* Exit: backpatch all exits */ code.PatchDisp22 (bo_exit1, (code.nextByteOffs() - bo_exit1) >>> 2); code.PatchDisp22 (bo_exit2, (code.nextByteOffs() - bo_exit2) >>> 2); 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, "%o2"); /* Presume this will work, to simplify control flow */ code.MOV (1, "%o0"); /* See if classes match */ code.CMP ("%o1", "%o2"); int bo_exit = code.nextByteOffs (); code.BE (0); code.NOP (); /* Nope, set to fail. */ code.MOV ("%g0", "%o0"); /* Here's where we go out. */ code.PatchDisp22 (bo_exit, (code.nextByteOffs() - bo_exit) >>> 2); } /* 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 %o0. Put class pointer into * %o2, presuming this loadClassPointer function will go down to * the base object. Put array rank into %o2. Call instanceof. */ loadClassPointer (i, cr, 0, "%o1"); code.MOV (n, "%o2"); code.reserveCode (CodeBlock.brACALL, i, "noreg", getFuncAddr (FID_instanceof)); code.NOP (); // fill delay slot } /** 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -