/* * $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; /** * Class used to construct interface method tables. * * @author epr */ public final class IMTBuilder { private final Object[] imt; private final boolean[] imtCollisions; // private final int length; /** * Number of elements in the IMT that have a collision */ private int collectionCount; /** * Initialize a new instance */ public IMTBuilder() { final int length = ObjectLayout.IMT_LENGTH; this.imt = new Object[length]; this.imtCollisions = new boolean[length]; } /** * Add the given method to this IMT. * * @param method */ public void add(VmInstanceMethod method) { final int length = getLength(); final int selector = method.getSelector(); final int index = selector % length; if (!contains(selector, index)) { if (imt[index] == null) { imt[index] = method; } else { // We have a collision if (imtCollisions[index]) { // We must extend the collision list that is already there final Object[] oldCollisionList = (Object[]) imt[index]; final int oldLength = oldCollisionList.length; final Object[] newCollisionList = new Object[oldLength + 1]; System.arraycopy(oldCollisionList, 0, newCollisionList, 0, oldLength); newCollisionList[oldLength] = method; imt[index] = newCollisionList; } else { // We must create a new collision list final Object[] collisionList = new Object[2]; collisionList[0] = imt[index]; collisionList[1] = method; imt[index] = collisionList; imtCollisions[index] = true; collectionCount++; } } } } /** * Does this IMT contain a method with the given selector? * * @param selector * @param index * @return boolean */ private boolean contains(int selector, int index) { if (imt[index] == null) { return false; } else { // We have a collision if (imtCollisions[index]) { // We must extend the collision list that is already there final Object[] collisionList = (Object[]) imt[index]; final int length = collisionList.length; for (int i = 0; i < length; i++) { final VmInstanceMethod method = (VmInstanceMethod) collisionList[i]; if (selector == method.getSelector()) { return true; } } return false; } else { final VmInstanceMethod method = (VmInstanceMethod) imt[index]; return (selector == method.getSelector()); } } } /** * Gets the number of elements in the IMT that have a collision. * * @return int */ public int getCollectionCount() { return collectionCount; } /** * Gets the IMT itself. * * @return The imt */ public Object[] getImt() { return imt; } /** * Gets an array describing which IMT indexes have a collision * * @return boolean[] */ public boolean[] getImtCollisions() { return imtCollisions; } /** * Gets the length (in elements) of the IMT. * * @return int */ public final int getLength() { return imt.length; } }