/* * @(#)CVMClass.java 1.34 06/10/22 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */ package vm; /* * CVM-specific internal representation of * a class. Target-machine independent. * There is a references from each instance of components.ClassInfo to * one of these, and a reference back as well. * Derived from the JDK-specific ClassClass * * !!See also CVMVM for VM-specific info not associated directly with a class. */ import components.*; import util.*; import consts.Const; import consts.CVMConst; import java.util.Enumeration; import java.util.Vector; import java.util.Hashtable; import java.util.StringTokenizer; public class CVMClass extends ClassClass implements Const, CVMConst, CVMTypeCode { public CVMMethodInfo methods[]; private String myNativeName; protected int typeCode = 0; private int classId = CVM_T_ERROR; public int nStaticWords; public int nStaticRef; public FieldInfo statics[]; // // Most methods are compressible, which makes their enclosing class // compressible // private boolean isCompressible = true; public CVMClass( ClassInfo c ){ classInfo = c; c.vmClass = this; if ( c.methods != null ){ // per-method, CVM-specific info. methods = new CVMMethodInfo[ c.methods.length ]; for( int i = 0; i < methods.length; i++ ){ components.MethodInfo m = c.methods[i]; methods[i] = new CVMMethodInfo( m ); if (!hasStaticInitializer && m.isStaticMember() && m.name.string.equals(/*NOI18N*/"<clinit>")) { hasStaticInitializer = true; } } } } public void setCompressible(boolean isCompressible) { this.isCompressible = isCompressible; } public boolean isCompressible() { return this.isCompressible; } public String getNativeName(){ if ( myNativeName == null ){ if (classInfo instanceof ArrayClassInfo) { ArrayClassInfo aci = (ArrayClassInfo)classInfo; if (aci.depth == 1) { /* * There are some special arrays of well-known basic * types here. */ if (aci.baseType != Const.T_CLASS) { myNativeName = "manufacturedArrayOf"+ aci.getNativeName(); } else if (aci.baseClass.find().superClassInfo == null) { myNativeName = "manufacturedArrayOfObject"; } else { myNativeName = "manufacturedArrayClass"+ aci.arrayClassNumber; } } else { myNativeName = "manufacturedArrayClass"+ aci.arrayClassNumber; } } else { myNativeName = classInfo.getGenericNativeName(); } } return myNativeName; } public int CVMflags(){ int flagval = 0; int acc = classInfo.access; if ((acc & ACC_PUBLIC) != 0) flagval |= CVM_CLASS_ACC_PUBLIC; if ((acc & ACC_FINAL) != 0) flagval |= CVM_CLASS_ACC_FINAL; if ((acc & ACC_SUPER) != 0) flagval |= CVM_CLASS_ACC_SUPER; if ((acc & ACC_INTERFACE) != 0) flagval |= CVM_CLASS_ACC_INTERFACE; if ((acc & ACC_ABSTRACT) != 0) flagval |= CVM_CLASS_ACC_ABSTRACT; if (isPrimitiveClass()) { flagval |= CVM_CLASS_ACC_PRIMITIVE; } if (classInfo.hasNonTrivialFinalizer) { flagval |= CVM_CLASS_ACC_FINALIZABLE; } if (classInfo.isReference()) { flagval |= CVM_CLASS_ACC_REFERENCE; } return flagval; } public int typecode(){ return typeCode; } // Accessor methods for the classId field: public int getClassId() { return classId; } protected void setClassId(int id) { classId = id; } public void orderStatics(){ // count statics. // arranged them ref-first // do not assign offsets. FieldInfo f[] = classInfo.fields; nStaticWords = 0; if ( (f == null) || (f.length == 0 ) ) return; // nothing to do. int nFields = f.length; int nStatic = 0; int nRef = 0; for ( int i = 0; i < nFields; i++ ){ FieldInfo fld = f[i]; if ( fld.isStaticMember() ){ nStatic += 1; char toptype = fld.type.string.charAt(0); if ( (toptype == 'L') || (toptype=='[')) nRef += 1; } } int refOff = 0; int scalarOff = nRef; int totalStaticWords = nRef; statics = new FieldInfo[ nStatic ]; for ( int i = 0; i < nFields; i++ ){ FieldInfo fld = f[i]; if ( fld.isStaticMember() ){ char toptype = fld.type.string.charAt(0); if ( (toptype == 'L') || (toptype=='[')){ statics[refOff] = fld; refOff += 1; } else { statics[scalarOff] = fld; scalarOff += 1; totalStaticWords += fld.nSlots; } } } nStaticWords = totalStaticWords; nStaticRef = nRef; } /* Inline all the methods in this code object */ public void getInlining() { for( int i = 0; i < methods.length; i++ ){ methods[i].getInlining(); } } public boolean adjustSymbolicConstants(UnresolvedReferenceList missingReferences){ ConstantPool cp = classInfo.getConstantPool(); if (!isPartiallyResolved(cp)) { return true; } makeResolvable(cp, missingReferences, classInfo.className); impureConstants = true; return false; } public static void makeResolvable( ConstantPool cp, UnresolvedReferenceList missingReferences, String source) { // // This is easy. // There is no change to the structure of the constant pool. // Mark the pool as impure and emit a bunch of warning // messages. We don't need to add utf8's to the pool! // ConstantObject consts[] = cp.getConstants(); int nconst = cp.getLength(); for( int i = 1; i < nconst; i += consts[i].nSlots ){ ConstantObject o; String className; o = consts[i]; if ( o.isResolved() ){ continue; } switch( o.tag ){ case Const.CONSTANT_CLASS: ClassConstant co = (ClassConstant)o; className = co.name.string; missingReferences.add(o, source); continue; case Const.CONSTANT_FIELD: case Const.CONSTANT_METHOD: case Const.CONSTANT_INTERFACEMETHOD: FMIrefConstant fo = (FMIrefConstant)o; if ( fo.clas.isResolved() ){ // This is a missing member of a resolved class. // Print this out // To print all the references to a totally missing // Add it to the list. missingReferences.add(o, source); } /* else ... * we will also stumble across the unresolved ClassConstant * object and will add it to the list in the above case. */ /* * If this memberRef constant is in the shared pool, * the the constants it references had better be as well. * If it is not, then they had better not be either. */ if (fo.shared){ ClassConstant cc = fo.clas; NameAndTypeConstant sig = fo.sig; if (cc.shared){ // This is not likely at all. if (cc.containingPool != fo.containingPool){ throw new ValidationException( "MemberRef and Class in different pools "+ fo); } } else { // oops. Need to make sure I can reference a shared // class constant. cc = (ClassConstant)fo.containingPool.lookup(cc); if (cc == null){ throw new ValidationException( "Shared MemberRef referenced Class not in shared pool "+fo); } fo.clas = cc; } if (sig.shared){ // This is not likely at all. if (sig.containingPool != fo.containingPool){ throw new ValidationException( "MemberRef and NameAndType in different pools "+ fo); } } else { // oops. Need to make sure I can reference a shared // NameAndType constant. sig = (NameAndTypeConstant)fo.containingPool.lookup(sig); if (sig == null){ throw new ValidationException( "Shared MemberRef referenced NameAndType not in shared pool "+fo); } fo.sig = sig; } }else if (fo.clas.shared || fo.sig.shared){ throw new ValidationException( "Shared clas/sig referenced from unshared memberRef "+ fo); } continue; } } } /* * Moved globals to CVMROMGlobals. * This requires that we can identify classes that contain writeable * methods. * The code to decide about writeability is copied from * CVMWriter.writeMethods(). */ public boolean hasWritableMethods() { for (int i = 0; i < methods.length; i++) { if (methods[i].codeHasJsr()) return true; } return false; } }