/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.vm.classmgr; import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.HashSet; import org.vmmagic.pragma.UninterruptiblePragma; /** * Abstract class for VmType classes that represent classes. * * @author Ewout Prangsma (epr@users.sourceforge.net) */ public abstract class VmClassType<T> extends VmType<T> { /** * The Virtual method table of this class. * It contains: VmClass, Method 0, Method 1... */ private Object[] tib; /** * The number of instances of this class */ private int instanceCount; /** * The interface method tables (each imt is an entry within this array) */ //private Object[] imtList; private VmInstanceMethod[] syntheticAbstractMethods; /** * @param name * @param superClassName * @param loader * @param accessFlags */ public VmClassType( String name, String superClassName, VmClassLoader loader, int accessFlags, ProtectionDomain protectionDomain) { super(name, superClassName, loader, accessFlags, protectionDomain); } /** * @param name * @param superClass * @param loader * @param typeSize */ public VmClassType( String name, VmNormalClass<? super T> superClass, VmClassLoader loader, int typeSize, ProtectionDomain protectionDomain) { super(name, superClass, loader, typeSize, protectionDomain); } /** * Returns the instanceCount. * * @return int */ public int getInstanceCount() { return instanceCount; } public final void incInstanceCount() throws UninterruptiblePragma { instanceCount++; } /** * Find a method from a given interface method reference. * @param methodRef */ /*public final VmMethod getIMethod(VmConstIMethodRef methodRef) { final VmType intf = methodRef.getConstClass().getResolvedVmClass(); final Object[] imtList = this.imtList; final int imtListSize = imtList.length; for (int i = 0; i < imtListSize; i++) { final Object[] imt = (Object[])imtList[i]; if (imt[0] == intf) { return (VmMethod)imt[methodRef.getImtOffset()]; } } // Not found return null; }*/ /** * Gets the type information block * * @return VmSystemObject[] */ public final Object[] getTIB() { return tib; } /** * Prepare the virtual method table * * @param allInterfaces * @return The tib */ protected Object[] prepareTIB(HashSet<VmInterfaceClass<?>> allInterfaces) { final VmNormalClass superClass = getSuperClass(); final TIBBuilder vmt; final int tc_mtable_length = getNoDeclaredMethods(); if (superClass != null) { // Initialize from vmt = new TIBBuilder(this, superClass.getTIB(), tc_mtable_length); } else { vmt = new TIBBuilder(this, tc_mtable_length); } // Loop through the method table of this class // searching for virtual methods which are not in the method table // of the super class. for (int i = 0; i < tc_mtable_length; i++) { final VmMethod mts = getDeclaredMethod(i); if (!(mts.isStatic() || mts.isSpecial())) { final VmInstanceMethod method = (VmInstanceMethod) mts; final String name = mts.getName(); final String signature = mts.getSignature(); final int index = vmt.indexOf(name, signature); if (index >= 0) { // The method existed in the super class, overwrite it if (vmt.overrides(index, method)) { vmt.set(index, method); } else { vmt.add(method); } } else { // The method does not exist yet. vmt.add(method); } } } // Loop through all the implemented interfaces of this class, // searching for methods that don't have an implementation (and a // place in the VMT) yet. // This is only needed for abstract methods, since non-abstract // methods must have implemented all methods already. ArrayList<VmInstanceMethod> syntheticAbstractMethods = null; if (isAbstract()) { for (VmInterfaceClass<?> icls : allInterfaces) { final int cnt = icls.getNoDeclaredMethods(); for (int j = 0; j < cnt; j++) { final VmMethod mts = icls.getDeclaredMethod(j); if (!mts.isStatic()) { final VmInstanceMethod method = (VmInstanceMethod) mts; final String name = method.getName(); final String signature = method.getSignature(); final int index = vmt.indexOf(name, signature); if (index >= 0) { // The method already exist in the VMT // do nothing } else { // The method does not exist yet. // Create a clone to include in our vmt. // We must clone here, because the VMT offset // is set. Without a clone, the VMT offset of // an interface method could be overwritten // in several abstract classes. final VmInstanceMethod clone = new VmInstanceMethod(method); vmt.add(clone); if (syntheticAbstractMethods == null) { syntheticAbstractMethods = new ArrayList<VmInstanceMethod>(); } syntheticAbstractMethods.add(clone); } } } } } if (syntheticAbstractMethods != null) { this.syntheticAbstractMethods = new VmInstanceMethod[syntheticAbstractMethods.size()]; syntheticAbstractMethods.toArray(this.syntheticAbstractMethods); } // Use the new VMT this.tib = vmt.toArray(); return tib; } /** * Prepare the interface method tables * * @param allInterfaces * @return The builder */ protected IMTBuilder prepareIMT(HashSet<VmInterfaceClass<?>> allInterfaces) { final IMTBuilder imtBuilder = new IMTBuilder(); for (VmType<?> intf : allInterfaces) { final int max = intf.getNoDeclaredMethods(); // Add all method of the current interface for (int m = 0; m < max; m++) { final VmMethod intfMethod = intf.getDeclaredMethod(m); if (!intfMethod.isStatic()) { final VmMethod clsMethod = getMethod(intfMethod.getName(), intfMethod.getSignature()); if (clsMethod instanceof VmInstanceMethod) { imtBuilder.add((VmInstanceMethod) clsMethod); } else { throw new ClassFormatError( "Interface method " + intfMethod.getName() + " in class " + getName() + " is static"); } } } } return imtBuilder; } /** * Search for an synthetic abstract class, that is not in this class, * but is a method of one of the implemented interfaces. * Synthetic abstract methods are added when the VMT is created. * * @param name * @param signature * @param hashCode * @return The method */ protected VmMethod getSyntheticAbstractMethod(String name, String signature, int hashCode) { if (syntheticAbstractMethods != null) { final int len = syntheticAbstractMethods.length; for (int i = 0; i < len; i++) { final VmMethod mts = syntheticAbstractMethods[i]; int mtsHashCode = mts.getMemberHashCode(); if (mtsHashCode == hashCode) { if (mts.nameEquals(name) && mts.signatureEquals(signature)) { return mts; } } } } // Not found return null; } /** * Verify this object before it is written into the bootimage * by the bootimage builder. * * @see org.jnode.vm.objects.VmSystemObject#verifyBeforeEmit() */ public void verifyBeforeEmit() { if (tib == null) { throw new RuntimeException("TIB == null in " + getName()); } super.verifyBeforeEmit(); } }