use of org.jikesrvm.objectmodel.ITable in project JikesRVM by JikesRVM.
the class InterfaceInvocation method installITable.
private static void installITable(RVMClass C, RVMClass I) {
TIB tib = C.getTypeInformationBlock();
ITableArray iTables = tib.getITableArray();
if (iTables == null) {
iTables = MemoryManager.newITableArray(2);
tib.setITableArray(iTables);
} else {
for (int i = 0; i < iTables.length(); i++) {
if (iTables.get(i).isFor(I)) {
// some other thread just built the iTable
return;
}
}
ITableArray tmp = MemoryManager.newITableArray(iTables.length() + 1);
for (int i = 0; i < iTables.length(); i++) {
tmp.set(i, iTables.get(i));
}
iTables = tmp;
tib.setITableArray(iTables);
}
if (VM.VerifyAssertions)
VM._assert(iTables.get(iTables.length() - 1) == null);
ITable iTable = buildITable(C, I);
iTables.set(iTables.length() - 1, iTable);
// iTables[0] is a move to front cache; fill it here so we can
// assume it always contains some iTable.
iTables.set(0, iTable);
}
use of org.jikesrvm.objectmodel.ITable in project JikesRVM by JikesRVM.
the class InterfaceInvocation method updateTIBEntry.
/**
* If there is an an IMT or ITable entry that contains
* compiled code for the argument method, then update it to
* contain the current compiled code for the method.
*
* @param klass the RVMClass who's IMT/ITable is being reset
* @param m the method that needs to be updated.
*/
public static void updateTIBEntry(RVMClass klass, RVMMethod m) {
TIB tib = klass.getTypeInformationBlock();
if (VM.BuildForIMTInterfaceInvocation) {
RVMMethod[] map = klass.noIMTConflictMap;
if (map != null) {
for (int i = 0; i < IMT_METHOD_SLOTS; i++) {
if (map[i] == m) {
IMT imt = tib.getImt();
imt.set(i, m.getCurrentEntryCodeArray());
// all done -- a method is in at most 1 IMT slot
return;
}
}
}
} else if (VM.BuildForITableInterfaceInvocation) {
if (tib.getITableArray() != null) {
ITableArray iTables = tib.getITableArray();
Atom name = m.getName();
Atom desc = m.getDescriptor();
for (int i = 0; i < iTables.length(); i++) {
ITable iTable = iTables.get(i);
if (iTable != null) {
RVMClass I = iTable.getInterfaceClass();
RVMMethod[] interfaceMethods = I.getDeclaredMethods();
for (RVMMethod im : interfaceMethods) {
if (im.getName() == name && im.getDescriptor() == desc) {
iTable.set(getITableIndex(I, name, desc), m.getCurrentEntryCodeArray());
}
}
}
}
}
}
}
use of org.jikesrvm.objectmodel.ITable in project JikesRVM by JikesRVM.
the class InterfaceInvocation method buildITable.
private static ITable buildITable(RVMClass C, RVMClass I) {
RVMMethod[] interfaceMethods = I.getDeclaredMethods();
TIB tib = C.getTypeInformationBlock();
ITable iTable = MemoryManager.newITable(interfaceMethods.length + 1);
iTable.set(0, I);
for (RVMMethod im : interfaceMethods) {
if (im.isClassInitializer())
continue;
if (VM.VerifyAssertions)
VM._assert(im.isPublic() && im.isAbstract());
RVMMethod vm = C.findVirtualMethod(im.getName(), im.getDescriptor());
// Since the methods in question take no arguments, we can get away with this.
if (vm == null || vm.isAbstract()) {
vm = Entrypoints.raiseAbstractMethodError;
} else if (!vm.isPublic()) {
vm = Entrypoints.raiseIllegalAccessError;
}
if (vm.isStatic()) {
vm.compile();
iTable.set(getITableIndex(I, im.getName(), im.getDescriptor()), vm.getCurrentEntryCodeArray());
} else {
iTable.set(getITableIndex(I, im.getName(), im.getDescriptor()), tib.getVirtualMethod(vm.getOffset()));
}
}
return iTable;
}
use of org.jikesrvm.objectmodel.ITable in project JikesRVM by JikesRVM.
the class InterfaceInvocation method findITable.
/**
* Return a reference to the itable for a given class, interface pair
* We might not have created the iTable yet, in which case we will do that and then return it.
*
* @param tib the TIB for the class
* @param id interface id of the interface sought (NOT dictionary id!!)
* @return iTable for desired interface
*/
@Entrypoint
public static ITable findITable(TIB tib, int id) throws IncompatibleClassChangeError {
ITableArray iTables = tib.getITableArray();
// Search for the right ITable
RVMType I = RVMClass.getInterface(id);
if (iTables != null) {
// check the cache at slot 0
ITable iTable = iTables.get(0);
if (iTable.isFor(I)) {
// cache hit :)
return iTable;
}
// Have to search the 'real' entries for the iTable
for (int i = 1; i < iTables.length(); i++) {
iTable = iTables.get(i);
if (iTable.isFor(I)) {
// found it; update cache
iTables.set(0, iTable);
return iTable;
}
}
}
// Didn't find the itable, so we don't yet know if
// the class implements the interface. :(((
// Therefore, we need to establish that and then
// look for the iTable again.
RVMClass C = (RVMClass) tib.getType();
if (!RuntimeEntrypoints.isAssignableWith(I, C))
throw new IncompatibleClassChangeError();
synchronized (C) {
installITable(C, (RVMClass) I);
}
ITable iTable = findITable(tib, id);
if (VM.VerifyAssertions)
VM._assert(iTable != null);
return iTable;
}
use of org.jikesrvm.objectmodel.ITable in project JikesRVM by JikesRVM.
the class InterfaceInvocation method invokeInterface.
/*
* PART I: runtime routines to implement the invokeinterface bytecode.
* these routines are called from the generated code
* as part of the interface invocation sequence.
*/
/**
* Resolve an interface method call.
* This routine is never called by the IMT-based dispatching code.
* It is only called for directly indexed ITables when the table
* index was unknown at compile time (i.e. the target Interface was not loaded).
*
* @param target object to which interface method is to be applied
* @param mid id of the MemberReference for the target interface method.
* @return machine code corresponding to desired interface method
*/
@Entrypoint
public static CodeArray invokeInterface(Object target, int mid) throws IncompatibleClassChangeError {
MethodReference mref = MemberReference.getMemberRef(mid).asMethodReference();
RVMMethod sought = mref.resolveInterfaceMethod();
RVMClass I = sought.getDeclaringClass();
RVMClass C = Magic.getObjectType(target).asClass();
if (VM.BuildForITableInterfaceInvocation) {
TIB tib = C.getTypeInformationBlock();
ITable iTable = findITable(tib, I.getInterfaceId());
return iTable.getCode(getITableIndex(I, mref.getName(), mref.getDescriptor()));
} else {
if (!RuntimeEntrypoints.isAssignableWith(I, C))
throw new IncompatibleClassChangeError();
RVMMethod found = C.findVirtualMethod(sought.getName(), sought.getDescriptor());
if (found == null)
throw new IncompatibleClassChangeError();
return found.getCurrentEntryCodeArray();
}
}
Aggregations