/*
* $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 org.jnode.util.NumberUtils;
import org.jnode.vm.VmAddress;
import org.jnode.annotation.KernelSpace;
import org.jnode.annotation.MagicPermission;
import org.jnode.annotation.Uninterruptible;
import org.jnode.vm.compiler.NativeCodeCompiler;
import org.vmmagic.unboxed.Address;
/**
* @author epr
*/
@MagicPermission
public final class VmCompiledCode extends AbstractCode {
/**
* Address of native code of this method
*/
private final VmAddress nativeCode;
/**
* Size in bytes of native code
*/
private int nativeCodeSize1;
/**
* Address of the default exception handler (only for compiled methods)
*/
private final VmAddress defaultExceptionHandler;
/**
* Compiled code of this method
*/
private final Object compiledCode1;
/**
* Exception handler table
*/
private final VmCompiledExceptionHandler[] eTable;
/**
* Mapping between PC's and addresses
*/
private final VmAddressMap addressTable;
/**
* The compiler used to generate this code
*/
private final NativeCodeCompiler compiler;
/**
* Next in linked list
*/
private VmCompiledCode next;
/**
* Unique id of this compiled code
*/
private final int id;
/**
* The method this code is generated for
*/
private final VmMethod method;
/**
* Create a new instance
*
* @param bytecode
* @param nativeCode
* @param compiledCode
* @param size
* @param eTable
* @param defaultExceptionHandler
* @param addressTable
*/
VmCompiledCode(int id, VmMethod method, NativeCodeCompiler compiler, VmByteCode bytecode,
VmAddress nativeCode, Object compiledCode, int size,
VmCompiledExceptionHandler[] eTable,
VmAddress defaultExceptionHandler, VmAddressMap addressTable) {
this.id = id;
this.method = method;
this.compiler = compiler;
this.nativeCode = nativeCode;
this.compiledCode1 = compiledCode;
this.eTable = eTable;
this.nativeCodeSize1 = size;
this.defaultExceptionHandler = defaultExceptionHandler;
this.addressTable = addressTable;
if (bytecode != null) {
bytecode.lock();
}
if (addressTable != null) {
addressTable.lock();
/*
* if (bytecode != null) { if
* (bytecode.getMethod().getDeclaringClass().getName().equals(
* "org.jnode.vm.TryCatchNPETest")) {
* addressTable.writeTo(System.out); } }
*/
}
}
/**
* Returns the defaultExceptionHandler.
*
* @return Object
*/
public VmAddress getDefaultExceptionHandler() {
return defaultExceptionHandler;
}
/**
* Gets the length of the native code in bytes.
*
* @return the length
*/
public int getSize() {
return nativeCodeSize1;
}
/**
* Get the number of exception handlers
*
* @return the number of exception handlers
*/
public int getNoExceptionHandlers() {
return (eTable == null) ? 0 : eTable.length;
}
/**
* Get the handler PC of the exception handler at a given index
*
* @param index
* @return The handler
*/
public VmCompiledExceptionHandler getExceptionHandler(int index) {
if (eTable != null) {
return eTable[index];
} else {
throw new IndexOutOfBoundsException("eTable is null; index "
+ index);
}
}
/**
* Gets address map index for the given instruction pointer.
*
* @param instrPtr
* @return The index, or -1 is not found.
*/
public final int getAddressMapIndex(Address instrPtr) {
final Address codeAddr = Address.fromAddress(nativeCode);
final int offset = instrPtr.toWord().sub(codeAddr.toWord()).toInt();
return addressTable.getIndexForOffset(offset);
}
/**
* Gets the address of the start of the native code.
*
* @return The address
*/
final VmAddress getNativeCode() {
return nativeCode;
}
final Object getCompiledCode() {
return compiledCode1;
}
/**
* Does this method contain the given address?
*
* @param codePtr
* @return boolean
*/
public boolean contains(Address codePtr) {
final Address start = Address.fromAddress(nativeCode);
final Address end = start.add(nativeCodeSize1);
return codePtr.GE(start) && codePtr.LT(end);
}
public String toString() {
if (compiledCode1 instanceof byte[]) {
return NumberUtils.hex((byte[]) compiledCode1);
} else {
return super.toString();
}
}
/**
* Gets the compiler that generated this code.
*
* @return Returns the compiler.
*/
public final NativeCodeCompiler getCompiler() {
return this.compiler;
}
/**
* @return Returns the next.
*/
final VmCompiledCode getNext() {
return this.next;
}
/**
* @param next The next to set.
*/
final void setNext(VmCompiledCode next) {
if (this.next != null) {
throw new SecurityException("Cannot set next twice");
}
this.next = next;
}
/**
* Do a lookup of the compiled code that has the given magic value.
*
* @param magic
* @return The compiled code found in the list, or null if not found.
*/
final VmCompiledCode lookup(int magic) {
VmCompiledCode c = this;
while (c != null) {
if (c.compiler.getMagic() == magic) {
return c;
}
c = c.next;
}
return null;
}
/**
* @return Returns the id.
*/
public final int getId() {
return id;
}
/**
* @return Returns the method.
*/
@KernelSpace
@Uninterruptible
public final VmMethod getMethod() {
return method;
}
/**
* @return Returns the addressTable.
* Can be null.
*/
public final VmAddressMap getAddressMap() {
return addressTable;
}
}