📄 codegen.java
字号:
// CodeGen.java - Build class data structures on the fly for// various dynamic loading systems.package toba.runtime;import toba.classfile.*;import java.io.*;public abstract class CodeGen { // The code generator used by the system to generate classes. static CodeGen generator; /** Verify all JIT requirements, like where things are in runtime * data structures. * Toba hash code: __RTwoi */ public static native void verifyRequirements (); // For now, we support only one code generator at a time, which is // normally initialized by the static initializer for the class which // extends CodeGen in an implementation; say the InterpCodeGen or // JITCodeGen. public static void setGenerator (CodeGen ng) { generator = ng; return; } public static CodeGen getGenerator () { return generator; } // Generate code for Method m in Class c // This should call m.setMethodCode on an instance of MethodCode // or a subtype of it, generate the code, and return the MethodCode // object. protected abstract MethodCode generateCode(Class c, Method m); // Define a class from the given data Class defineClass(ClassLoader loader, byte data[], int offset, int length) { DataInputStream instream = new DataInputStream( new ByteArrayInputStream(data, offset, length)); return defineClass(loader, instream); } Class defineClass(ClassLoader loader, DataInputStream instream) throws NoClassDefFoundError { ClassData cdata; Class cl, superclass; try { // Convert the stream into a ClassData obj cdata = ClassData.forStream (loader, instream); // Load the appropriate superclasses Supers.load (cdata, loader); } catch (ClassFormatError e) { throw new NoClassDefFoundError(e.getMessage()); } catch (ClassNotFoundException e) { throw new NoClassDefFoundError(e.getMessage()); } catch (java.io.IOException e) { throw new ClassFormatError(e.getMessage()); } /* We only build native classes if we didn't get this ClassData from * an existing native class. */ if (ClassData.CDSRC_tobaclass != cdata.cdsrc) { cl = buildNativeClass(cdata, loader); /* Install a pointer to the loaded class into ClassData */ cdata.javaClass = cl; } else { cl = cdata.javaClass; if (null == cl) { throw new InternalError ("CDSRC_tobaclass didn't assign javaClass"); } } return cl; } /* Resolve class references and generate the methods for this class */ void resolveClass(Class c, ClassLoader loader) { // synchronize on c to prevent multiple resolution of the class//System.out.println ("CodeGen.resolveClass " + c); synchronized(c) { int flags = ClassRT.getFlags(c); ClassData cdata = ClassRT.getClassData(c); Class sc = c.getSuperclass(); // Resolve our superclass if necessary if (sc != null) { ClassData sccdata = ClassRT.getClassData(sc); if (sccdata.state != ClassData.RES_CONSTANTS) { resolveClass(sc, sc.getClassLoader ()); } } Resolve.resolveClass(cdata, loader); // Set list of referenced classes if (ClassData.CDSRC_tobaclass != cdata.cdsrc) { /* This is a build-native-class thing; don't do for * tobaclass-sourced data */ ClassRT.setReferencedClasses(c, referencedClasses(c, loader)); } } } // Size and alignment information that is machine dependent static native int typeSpace(char c); static native int typeAlignment(char c); static native int baseSize(); static native int baseAlignment(); /** Native route to store a one-byte value into a given C address. * @param addr where value should go * @param v value to store * Toba hash code: _lb_hu2R9 */ static public native void pokeByte (long addr, byte v); /** Native route to store a two-byte value into a given C address. * @param addr where value should go * @param v value to store * Toba hash code: _ls_cLN3R */ static public native void pokeShort (long addr, short v); /** Native route to store a four-byte value into a given C address. * @param addr where value should go * @param v value to store * Toba hash code: _li_ZDc1h */ static public native void pokeInt (long addr, int v); /** Native route to store an eight-byte value into a given C address. * @param addr where value should go * @param v value to store * Toba hash code: _ll_FO5Cd */ static public native void pokeLong (long addr, long v); /** Native routine to convert an object reference value into a long address * @param or object reference to store * @returns address of a block that holds the object reference value * Toba hash code: _O_HIiqz */ static public native long getNativeObjectAddr (Object or); /** Return the address of some native symbol, such as a hashed native * method name; presumably we can find this through dlopen or some * other registry. * Toba hash code: _S_rTxsP */ static public native long getNativeSymbolAddress (String cname); // Construct a list of the classes referenced by this class private long[] referencedClasses(Class c, ClassLoader loader) { int nrefs = 0; ClassData cdata = ClassRT.getClassData(c); /* Count the number of references to other classes that are * made by this class */ for (int i = 0; i < cdata.constants.length; i++) { Constant k = cdata.constants[i]; if (k != null && k.tag == Constant.CLASS) { ClassRef r = (ClassRef)k.value; String s = Names.baseclass(r.name); // s == null if k is an array of primitives if (s != null) { nrefs++; } } } long[] refs = new long[nrefs]; // Fill out the array of all referenced classes. int index = 0; for (int i = 0; i < cdata.constants.length; i++) { Constant k = cdata.constants[i]; if (k != null && k.tag == Constant.CLASS) { ClassRef r = (ClassRef)k.value; String s = Names.baseclass(r.name); Class refClass; if (s != null) { /* OK, what we want to add is the base class of this * class. I.e., strip away all the array stuff. * Toba does this at runtime; we can't just use * Class.forName(s) because that results in an infinite * loop. Note: the getFoo stuff in ClassRT.c is _not_ * protected against attempting to lookup a class that * doesn't have a C structure yet, so this may dump * core if somehow we got an array class without a * corresponding base class. */ refClass = r.getRefClass (loader); while (0 != (ClassRT.IS_ARRAY & ClassRT.getFlags (refClass))) { refClass = ClassRT.getElementClass (refClass); } refs[index++] = ClassRT.getNativeClass(refClass); } } } return refs; } // Construct a list of all of the superclasses of this class, // given its first superclass private long[] superclasses(Class c, Class superclass) { int nsupers = 1; /* We count ourselves in this */ Class sc = superclass; while (sc != null) { nsupers++; sc = sc.getSuperclass(); } long[] supers = new long[nsupers]; int index = 0; supers[index++] = ClassRT.getNativeClass(c); sc = superclass; while (sc != null) { supers[index++] = ClassRT.getNativeClass(sc); sc = sc.getSuperclass(); } return supers; } // Construct a list of the interfaces used by this class private long[] interfaces(Class c) throws NoClassDefFoundError { int ninters = 0; Class sc = c; // Count the number of interfaces while (sc != null) { ninters += ClassRT.getClassData(sc).interfaces.length; sc = sc.getSuperclass(); } long[] inters = new long[ninters]; int index = 0; sc = c; while (sc != null) { ClassData sccdata = ClassRT.getClassData(sc); ClassLoader loader = sc.getClassLoader (); for (int i = 0; i < sccdata.interfaces.length; i++) { Class intf; ClassRef r = sccdata.interfaces[i]; Resolve.resolveClassRef(r, loader); intf = r.getRefClass(loader); inters[index++] = ClassRT.getNativeClass(intf); } sc = sc.getSuperclass(); } return inters; } /* Compute the byte offsets of each field in the vars field * and return them as an array of offsets. */ private int[] instanceOffsets(Class c) { Class sc; ClassData cdata = ClassRT.getClassData(c); ClassData sccdata; Field[] vars = cdata.ivtable; Field[] scvars = null; int[] offsets = new int[vars.length]; int curroffset = baseSize(); int index = 0; sc = c.getSuperclass(); if (sc != null) { sccdata = ClassRT.getClassData(sc); if (sccdata.ivtable.length > 0) { scvars = sccdata.ivtable; for (int i = 0; i < scvars.length; i++) { offsets[i] = ClassRT.getInstanceVarOffset(sc, scvars[i].tableslot); } index = scvars.length; curroffset = offsets[index - 1] + typeSpace(scvars[index - 1].signature.charAt(0)); } } for (int i = index; i < vars.length; i++) { int fieldsize = typeSpace(vars[i].signature.charAt(0)); /* Extend the current offset to the right alignment * for the current field */ int alignment = typeAlignment(vars[i].signature.charAt(0)); int curralign = 8 - (curroffset % 8); curroffset += (curralign % fieldsize); offsets[i] = curroffset; /* And then set aside space for the variable */ curroffset += fieldsize; } return offsets; } /* Pass in the instance info, and compute the instance size */ private int instanceSize(Field[] vars, int[] offsets) { int size; if (vars.length == 0) return baseSize(); size = offsets[offsets.length - 1] + typeSpace(vars[vars.length - 1].signature.charAt(0)); /* Pad the size out to the alignment of the largest element * in the instance */ int largestalign = baseAlignment(); for (int i = 0; i < vars.length; i++) { int a = typeAlignment(vars[i].signature.charAt(0)); if (a > largestalign)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -