/*
This file is part of JOP, the Java Optimized Processor
see <http://www.jopdesign.com/>
Copyright (C) 2004,2005, Flavius Gruian
Copyright (C) 2005-2008, Martin Schoeberl (martin@jopdesign.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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 for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jopdesign.build;
import org.apache.bcel.classfile.CodeException;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.Type;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.List;
/**
* @author Flavius, Martin
* @deprecated code needs to be moved to other class, data should be attached to methodinfo using CustomKeys
*/
public class JopMethodInfo extends OldMethodInfo implements Serializable {
private static final long serialVersionUID = 1L;
static List clinitList;
int codeAddress;
// struct address is ONLY useful for <clinit> methods
// and the boot/main methods!
// Now it's necessary for debugging too.
int structAddress;
CodeException[] exctab;
int mstack, margs, mreallocals;
int len, exclen;
int vtindex;
/**
* Constructor is only used by the ClassInfo visitor
*
* @param jc
* @param mid
*/
protected JopMethodInfo(OldClassInfo jc, String mid) {
super(jc, mid);
codeAddress = 0;
structAddress = 0;
}
/**
* Return the correct type of cli
*/
public JopClassInfo getCli() {
return (JopClassInfo) super.getCli();
}
/**
* Extract linking information for this method
* @param addr the bytecode start address
*/
public void setInfo(int addr) {
codeAddress = addr;
Method m = getMethod();
margs = 0;
Type at[] = m.getArgumentTypes();
for (int i = 0; i < at.length; ++i) {
margs += at[i].getSize();
}
// FIXME! invokespecial adds an extra objref!!! inits, private, and
// superclass calls
// for now only handle inits
if (!m.isStatic()) {
margs++;
}
if (m.isAbstract()) {
mstack = mreallocals = len = exclen = 0;
exctab = null;
} else {
mstack = m.getCode().getMaxStack();
// the 'real' locals - means without arguments
mreallocals = m.getCode().getMaxLocals() - margs;
// System.err.println(" ++++++++++++ "+methodId+" --> mlocals
// ="+mlocals+" margs ="+margs);
len = (m.getCode().getCode().length + 3) / 4;
exctab = m.getCode().getExceptionTable();
exclen = exctab != null ? exctab.length : 0;
// TODO: couldn't len=JOP...MAX_SIZE/4 be ok?
if (len >= JOPizer.METHOD_MAX_SIZE / 4 || mreallocals > 31
|| margs > 31) {
// we interprete clinit on JOP - no size restriction
if (!m.getName().equals("<clinit>")) {
System.err.println("len(max:"
+ (JOPizer.METHOD_MAX_SIZE / 4) + ")=" + len
+ "mreallocals(max:31)=" + mreallocals
+ " margs(max:31)=" + margs);
System.err.println("wrong size: "
+ getCli().clazz.getClassName() + "." + methodId);
throw new Error();
}
}
// System.out.println((mstack+m.getCode().getMaxLocals())+" "+
// m.getName()+" maxStack="+mstack+"
// locals="+m.getCode().getMaxLocals());
}
}
public int getLength() {
return getMethod().isAbstract() ? 0 : len + 1 + 2 * exclen;
}
public void dumpMethodStruct(PrintWriter out, int addr) {
if (methodId.equals(OldAppInfo.clinitSig)
&& len >= JOPizer.METHOD_MAX_SIZE / 4) {
out.println("\t// no size for <clinit> - we interpret it and allow larger methods!");
}
// java_lang_String
// 0x01 TODO access
// 2 TODO ? stack
// code start:1736
// code length:4
// cp:3647
// locals: 1 args size: 1
String abstr = "";
if (getMethod().isAbstract()) {
abstr = "abstract ";
}
out.println("\t//\t" + addr + ": " + abstr
+ getCli().clazz.getClassName() + "." + methodId);
out.println("\t\t//\tcode start: " + codeAddress);
out.println("\t\t//\tcode length: " + len);
out.println("\t\t//\tcp: " + getCli().cpoolAddress);
out.println("\t\t//\tlocals: " + (mreallocals + margs) + " args size: "
+ margs);
int word1 = codeAddress << 10 | len;
// no length on large <clinit> methods
// get interpreted at start - see Startup.clazzinit()
if (methodId.equals(OldAppInfo.clinitSig)
&& len >= JOPizer.METHOD_MAX_SIZE / 4) {
word1 = codeAddress << 10;
}
int word2 = getCli().cpoolAddress << 10 | mreallocals << 5 | margs;
if (getMethod().isAbstract()) {
word1 = word2 = 0;
}
out.println("\t\t" + word1 + ",");
out.println("\t\t" + word2 + ",");
}
public void dumpByteCode(PrintWriter out, PrintWriter outLinkInfo) {
// link info: dump bytecode address
outLinkInfo.println("bytecode "+getFQMethodName()+" "+codeAddress);
out.println("//\t" + codeAddress + ": " + methodId);
if (getCode() == null) {
out.println("//\tabstract");
return;
}
byte bc[] = getCode().getCode();
String post = "// ";
int i, word, j;
for (j = 0, i = 3, word = 0; j < bc.length; j++) {
word = word << 8 | (bc[j] & 0xFF);
post += (bc[j] & 0xFF) + " ";
if (i == 0) {
out.println("\t" + word + ",\t" + post);
post = "// ";
i = 3;
word = 0;
} else
i--;
}
if (i != 3) {
word = word << (i + 1) * 8;
out.println("\t" + word + ",\t" + post);
}
word = getMethod().isSynchronized() ? 1 : 0;
word |= getMethod().isStatic() ? 2 : 0;
word <<= 16;
word |= exclen & 0xFFFF;
out.println("\t" + word
+ ",\t//\tstatic?, sync?, exception table length");
for (i = 0; i < exclen; i++) {
Integer idx = new Integer(exctab[i].getCatchType());
int pos = getCli().cpoolUsed.indexOf(idx) + 1;
word = exctab[i].getStartPC();
post = "// start: " + exctab[i].getStartPC();
word = word << 16 | exctab[i].getEndPC();
post += "\tend: " + exctab[i].getEndPC();
out.println("\t" + word + ",\t" + post);
word = exctab[i].getHandlerPC();
post = "// target: " + exctab[i].getHandlerPC();
word = word << 16 | pos;
post += "\ttype: " + pos;
out.println("\t" + word + ",\t" + post);
}
}
public int getCodeAddress() {
return codeAddress;
}
public int getStructAddress() {
return structAddress;
}
}