📄 codegen.java
字号:
largestalign = a; } size += ((8 - (size % 8)) % largestalign); return size; } private int classVariableSpace(Field[] cvars) { int currspace = 0; for (int i = 0; i < cvars.length; i++) { int fieldsize = typeSpace(cvars[i].signature.charAt(0)); /* Extend the current offset to the right alignment * for the current field */ int alignment = typeAlignment(cvars[i].signature.charAt(0)); int curralign = 8 - (currspace % 8); currspace += (curralign % fieldsize); /* And then set aside space for the variable */ currspace += fieldsize; } return currspace; } private int classVariableAlignment(Field[] cvars) { int maxalignment = 0; for (int i = 0; i < cvars.length; i++) { int alignment = typeAlignment(cvars[i].signature.charAt(0)); if (alignment > maxalignment) maxalignment = alignment; } return maxalignment; } /* Compute the offset of each class variable in the class * variable structure. The native code turns this into actual * addresses. */ private int[] classVariableOffsets(Field[] cvars) { int curroffset = 0; int[] cvoffsets = new int[cvars.length]; for (int i = 0; i < cvars.length; i++) { int fieldsize = typeSpace(cvars[i].signature.charAt(0)); /* Extend the current offset to the right alignment * for the current field */ int alignment = typeAlignment(cvars[i].signature.charAt(0)); int curralign = 8 - (curroffset % 8); curroffset += (curralign % fieldsize); cvoffsets[i] = curroffset; /* And then set aside space for the variable */ curroffset += fieldsize; } return cvoffsets; } // Method used to get the addresses of all methods in the class // Used to generate the method table for subclasses private long[] getInstanceMethodAddrs(Class c) { ClassData cdata = ClassRT.getClassData(c); long[] addr = new long[cdata.imtable.length]; for (int i = 0; i < cdata.imtable.length; i++) { addr[i] = ClassRT.getMethodAddr(c, cdata.imtable [i]); } return addr; } private long[] instanceMethodAddrs(Class c, Field[] meths, int mtlength) { long[] addrs = new long[mtlength]; Class sc = c.getSuperclass(); ClassData cdata = ClassRT.getClassData(c); /* Look up the addresses for methods that we inherit */ if (sc != null) { long[] superaddrs = getInstanceMethodAddrs(sc); System.arraycopy(superaddrs, 0, addrs, 0, superaddrs.length); } // Meths only contains entries for locally implemented methods, for (int i = 0; i < meths.length; i++) { Field f = meths[i]; /* Find the right classdata for this method */ if (0 == (f.access & (ClassData.ACC_ABSTRACT | ClassData.ACC_STATIC))) { MethodCode mc = generateCode(c, new Method(cdata, f)); addrs[f.tableslot] = mc.getEntryPoint (); if (0 == addrs [f.tableslot]) { throw new InternalError ("generateCode failed to return imeth address for " + mc.method); } } } return addrs; } private long[] staticMethodAddrs(Class c, Field[] meths) { // No inheritance of static methods, so easy. long[] addrs = new long[meths.length]; ClassData cdata = ClassRT.getClassData(c); for (int i = 0; i < meths.length; i++) { Field f = meths[i]; /* Find the right classdata for this method */ if (0 == (f.access & (ClassData.ACC_ABSTRACT))) { MethodCode mc = generateCode(c, new Method(cdata, meths[i])); addrs[i] = mc.getEntryPoint (); if (0 == addrs [i]) { throw new InternalError ("generateCode failed to return smeth address"); } } } return addrs; } private String[] internStrings(Class c) { ClassData cdata = ClassRT.getClassData(c); Constant[] cons = cdata.constants; int nstrings = 0; /* cons[0] is unused and null */ for (int i = 1; i < cons.length; i++) { Constant co = cons[i]; if ((co != null) && ((co.tag == Constant.UTF8) || (co.tag == Constant.UNICODE))) { nstrings++; } } // We set aside an extra entry, so that if the cdata.name // field has been mangled because of '/' to '.', we have space // for BOTH of those strings. String[] strpool = new String[nstrings + 1]; /* The strings were already interned as they were created. * We just put them in a list in the class to conform * to the format of the class data structure. */ strpool[0] = cdata.name; int index = 1; /* cons[0] is unused and null */ for (int i = 1; i < cons.length; i++) { Constant co = cons[i]; if ((co != null) && ((co.tag == Constant.UTF8) || (co.tag == Constant.UNICODE))) { String s = (String)co.value; } } return strpool; } /** Return an array of addresses of the struct mt_generic descriptions * of the methods listed. Do _NOT_ return the address of the methods; * that's not what the findinterface function is supposed to give back. * @param c Class in which to search for methods * @param hlist List of fields for which we want address * @returns long[] Array of addresses for fields. */ private long[] hashAddrs(Class c, Field[] hlist) { long[] addrs = new long[hlist.length]; for (int i = 0; i < hlist.length; i++) { Field f = hlist[i]; if (f != null) addrs[i] = ClassRT.getMethodTEnt(c, f); else addrs[i] = 0; } return addrs; } private void setSpecialMethods(Class c) throws NoSuchMethodError { /* We need to find the following methods - the class * initializer(the static method named "<clinit>()V"), the * no-arg class constructor (the instance method named * "<init>()V"), and the finalizer (the instance method named * "finalize()V") */ // Find the no-arg constructor - there has to be one, or or // we throw a NoSuchMethodError boolean cons_set = false, fin_set = false; ClassData cdata = ClassRT.getClassData(c); for (int i = 0; i < cdata.imtable.length; i++) { Field f = cdata.imtable[i]; if ((f.name.equals ("<init>")) && (f.signature.equals ("()V"))) { ClassRT.setConstructor(c, ClassRT.getMethodAddr(c, f)); cons_set = true; } else if ((f.name.equals ("finalize")) && (f.signature.equals ("()V"))) { ClassRT.setFinalizer(c, ClassRT.getMethodAddr(c, f)); fin_set = true; } } if (!cons_set) throw new NoSuchMethodError("No <init> method in class " + cdata.name); if (!fin_set) throw new NoSuchMethodError("No <finalize> method in class " + cdata.name); for (int i = 0; i < cdata.smtable.length; i++) { Field f = cdata.smtable[i]; if ((f.name.equals ("<clinit>")) && (f.signature.equals ("()V"))) { ClassRT.setClassInitializer(c, ClassRT.getMethodAddr(c, f)); } } } private synchronized Class buildNativeClass(ClassData cdata, ClassLoader loader) { int cvspace, cvalign; int[] cvoffsets; int instsize; int[] ivoffsets; ClassData superclass = cdata.superclass; Class nativesc; Class nativeClass; long[] methCode; if (null != cdata.javaClass) { /* We already have the native class for this cdata. However, * we may have created it in a nested call, e.g. through Supers.load, * in which case some of the data is incorrect. Update things * here, then return the existing class. */ IHash h = new IHash(cdata); ClassRT.setHashTable(cdata.javaClass, h.mask, h.hlist, hashAddrs(cdata.javaClass, h.hlist)); return cdata.javaClass; }//System.out.println ("CodeGen.buildNativeClass " + cdata.name); if (superclass != null) nativesc = superclass.javaClass; else nativesc = null; cvspace = classVariableSpace(cdata.cvtable); cvalign = classVariableAlignment(cdata.cvtable); nativeClass = ClassRT.allocateNativeClass(cdata, cdata.imtable.length, cvspace, cvalign); cdata.javaClass = nativeClass; ClassRT.setSuperclasses(nativeClass, superclasses(nativeClass, nativesc)); ClassRT.setClassLoader(nativeClass, loader); /* String Pools calculations */ ClassRT.setStringPool(nativeClass, internStrings(nativeClass)); /* Instance variable/size calculations */ ivoffsets = instanceOffsets(nativeClass); instsize = instanceSize(cdata.ivtable, ivoffsets); ClassRT.setInstanceVariables(nativeClass, cdata.ivtable, ivoffsets); ClassRT.setInstanceSize(nativeClass, instsize); /* Class variable calculations */ cvoffsets = classVariableOffsets(cdata.cvtable); ClassRT.setClassVariables(nativeClass, cdata.cvtable, cvoffsets, cvalign); for (int i = 0; i < cdata.cvtable.length; i++) { Field f = cdata.cvtable [i]; byte adata []; int cind; float fv; double dv; // See if the field has a constant value (initializer) adata = Attribute.find (f.attributes, "ConstantValue"); if (null == adata) { continue; } /* OK, it does. What's the value of the initializer? If the * exception is thrown below, we probably had an invalid class * file. */ cind = -1; try { cind = (new DataInputStream (new ByteArrayInputStream (adata))).readShort (); } catch (IOException e) { } if (0 > cind) { continue; } /* Set the field value. */ Constant ival = cdata.constants [cind]; long vaddr = ClassRT.getClassVarAddr (nativeClass, f.tableslot); switch (ival.tag) { case Constant.LONG: // Just assign value pokeLong (vaddr, ((Long)ival.value).longValue ()); break; case Constant.FLOAT: // fv = ((Float)ival.value).floatValue (); pokeInt (vaddr, Float.floatToIntBits (fv)); break; case Constant.DOUBLE: dv = ((Double)ival.value).doubleValue (); pokeLong (vaddr, Double.doubleToLongBits (dv)); break; case Constant.INTEGER: // Just the value pokeInt (vaddr, ((Integer)ival.value).intValue ()); break; case Constant.STRING: pokeInt (vaddr, (int) getNativeObjectAddr (ival.value)); break; default: throw new InternalError ("Invalid constant type for static final initializer"); } } // Interface calculations ClassRT.setInterfaces(nativeClass, interfaces(nativeClass), cdata.interfaces.length); // Method table calculations methCode = instanceMethodAddrs(nativeClass, cdata.methods, // Not mtable! cdata.imtable.length); ClassRT.setInstanceMethods(nativeClass, cdata.imtable, methCode); // Static method calculations methCode = staticMethodAddrs(nativeClass, cdata.smtable); ClassRT.setStaticMethods(nativeClass, cdata.smtable, methCode); // Set special methods like the no-arg constructor, // class initializer, and finalizer setSpecialMethods(nativeClass); // Create the interface hash table IHash h = new IHash(cdata); ClassRT.setHashTable(nativeClass, h.mask, h.hlist, hashAddrs(nativeClass, h.hlist)); /* All done *///System.out.println ("done CodeGen.buildNativeClass " + cdata.name); return nativeClass; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -