Browse Source

changed the implementation of try statements so that jsr/ret will not be used anymore.


git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@371 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
tags/rel_3_17_1_ga
chiba 17 years ago
parent
commit
c2d6bdf673

+ 7
- 1
src/main/javassist/bytecode/ClassFile.java View File

String[] cachedInterfaces; String[] cachedInterfaces;
String cachedSuperclass; String cachedSuperclass;


/**
* The major version number of class files created
* from scratch. The value is 45 (JDK 1.1).
*/
public static final int MAJOR_VERSION = 45;

/** /**
* Constructs a class file from a byte stream. * Constructs a class file from a byte stream.
*/ */
* a fully-qualified super class name * a fully-qualified super class name
*/ */
public ClassFile(boolean isInterface, String classname, String superclass) { public ClassFile(boolean isInterface, String classname, String superclass) {
major = 45;
major = MAJOR_VERSION;
minor = 3; // JDK 1.1 or later minor = 3; // JDK 1.1 or later
constPool = new ConstPool(classname); constPool = new ConstPool(classname);
thisClass = constPool.getThisClassInfo(); thisClass = constPool.getThisClassInfo();

+ 9
- 4
src/main/javassist/compiler/CodeGen.java View File

cname = MemberResolver.jvmToJavaName(cname); cname = MemberResolver.jvmToJavaName(cname);
} }


atClassObject2(cname);
exprType = CLASS;
arrayDim = 0;
className = "java/lang/Class";
}

/* MemberCodeGen overrides this method.
*/
protected void atClassObject2(String cname) throws CompileError {
int start = bytecode.currentPc(); int start = bytecode.currentPc();
bytecode.addLdc(cname); bytecode.addLdc(cname);
bytecode.addInvokestatic("java.lang.Class", "forName", bytecode.addInvokestatic("java.lang.Class", "forName",
+ "Ljava/lang/NoClassDefFoundError;"); + "Ljava/lang/NoClassDefFoundError;");
bytecode.addOpcode(ATHROW); bytecode.addOpcode(ATHROW);
bytecode.write16bit(pc, bytecode.currentPc() - pc + 1); bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);

exprType = CLASS;
arrayDim = 0;
className = "java/lang/Class";
} }


public void atArrayRead(ASTree array, ASTree index) public void atArrayRead(ASTree array, ASTree index)

+ 56
- 30
src/main/javassist/compiler/MemberCodeGen.java View File

/* Code generator methods depending on javassist.* classes. /* Code generator methods depending on javassist.* classes.
*/ */
public class MemberCodeGen extends CodeGen { public class MemberCodeGen extends CodeGen {
public static final int JAVA5_VER = 49;
public static final int JAVA6_VER = 50;

protected MemberResolver resolver; protected MemberResolver resolver;
protected CtClass thisClass; protected CtClass thisClass;
protected MethodInfo thisMethod; protected MethodInfo thisMethod;
protected int version; // the major version of a class file.


protected boolean resultStatic; protected boolean resultStatic;


resolver = new MemberResolver(cp); resolver = new MemberResolver(cp);
thisClass = cc; thisClass = cc;
thisMethod = null; thisMethod = null;
ClassFile cf = cc.getClassFile2();
if (cf == null)
version = 0;
else
version = cf.getMajorVersion();
} }


/** /**


static class JsrHook extends ReturnHook { static class JsrHook extends ReturnHook {
ArrayList jsrList; ArrayList jsrList;
CodeGen cgen;
int var; int var;


JsrHook(CodeGen gen) { JsrHook(CodeGen gen) {
super(gen); super(gen);
jsrList = new ArrayList(); jsrList = new ArrayList();
var = gen.getMaxLocals();
gen.incMaxLocals(1);
cgen = gen;
var = -1;
}

private int getVar(int size) {
if (var < 0) {
var = cgen.getMaxLocals();
cgen.incMaxLocals(size);
}

return var;
} }


private void jsrJmp(Bytecode b) { private void jsrJmp(Bytecode b) {
b.addOpcode(JSR);
b.addOpcode(Opcode.GOTO);
jsrList.add(new Integer(b.currentPc())); jsrList.add(new Integer(b.currentPc()));
b.addIndex(0); b.addIndex(0);
} }
jsrJmp(b); jsrJmp(b);
break; break;
case ARETURN : case ARETURN :
b.addAstore(var);
b.addAstore(getVar(1));
jsrJmp(b); jsrJmp(b);
b.addAload(var); b.addAload(var);
break; break;
case IRETURN : case IRETURN :
b.addIstore(var);
b.addIstore(getVar(1));
jsrJmp(b); jsrJmp(b);
b.addIload(var); b.addIload(var);
break; break;
case LRETURN : case LRETURN :
b.addLstore(var);
b.addLstore(getVar(2));
jsrJmp(b); jsrJmp(b);
b.addLload(var); b.addLload(var);
break; break;
case DRETURN : case DRETURN :
b.addDstore(var);
b.addDstore(getVar(2));
jsrJmp(b); jsrJmp(b);
b.addDload(var); b.addDload(var);
break; break;
case FRETURN : case FRETURN :
b.addFstore(var);
b.addFstore(getVar(1));
jsrJmp(b); jsrJmp(b);
b.addFload(var); b.addFload(var);
break; break;
} }
} }


int pcFinally = -1;
if (finallyBlock != null) { if (finallyBlock != null) {
jsrHook.remove(this); jsrHook.remove(this);
// catch (any) clause // catch (any) clause
bc.addExceptionHandler(start, pcAnyCatch, pcAnyCatch, 0); bc.addExceptionHandler(start, pcAnyCatch, pcAnyCatch, 0);
bc.growStack(1); bc.growStack(1);
bc.addAstore(var); bc.addAstore(var);
bc.addOpcode(JSR);
int pcJsrIndex = bc.currentPc();
bc.addIndex(0); // correct later
bc.addAload(var);
bc.addOpcode(ATHROW);

// finally clause
pcFinally = bc.currentPc();
bc.write16bit(pcJsrIndex, pcFinally - pcJsrIndex + 1);
int retAddr = getMaxLocals();
incMaxLocals(1);
bc.growStack(1); // return address
bc.addAstore(retAddr);
hasReturned = false; hasReturned = false;
finallyBlock.accept(this); finallyBlock.accept(this);
if (!hasReturned) { if (!hasReturned) {
bc.addOpcode(RET);
bc.add(retAddr);
bc.addAload(var);
bc.addOpcode(ATHROW);
} }

addFinally(jsrHook.jsrList, finallyBlock);
} }


int pcEnd = bc.currentPc(); int pcEnd = bc.currentPc();
patchGoto(gotoList, pcEnd); patchGoto(gotoList, pcEnd);
hasReturned = !tryNotReturn;
if (finallyBlock != null) { if (finallyBlock != null) {
patchGoto(jsrHook.jsrList, pcFinally);
if (tryNotReturn) {
bc.addOpcode(JSR);
bc.addIndex(pcFinally - pcEnd);
}
if (tryNotReturn)
finallyBlock.accept(this);
} }
}


hasReturned = !tryNotReturn;
/**
* Adds a finally clause for earch return statement.
*/
private void addFinally(ArrayList returnList, Stmnt finallyBlock)
throws CompileError
{
Bytecode bc = bytecode;
int n = returnList.size();
for (int i = 0; i < n; ++i) {
int pc = ((Integer)returnList.get(i)).intValue();
bc.write16bit(pc, bc.currentPc() - pc + 1);
finallyBlock.accept(this);
if (!hasReturned) {
bc.addOpcode(Opcode.GOTO);
bc.addIndex(pc + 3 - bc.currentPc());
}
}
} }


public void atNewExpr(NewExpr expr) throws CompileError { public void atNewExpr(NewExpr expr) throws CompileError {
return cp.addFieldrefInfo(ci, name, type); return cp.addFieldrefInfo(ci, name, type);
} }


protected void atClassObject2(String cname) throws CompileError {
super.atClassObject2(cname);
}

protected void atFieldPlusPlus(int token, boolean isPost, protected void atFieldPlusPlus(int token, boolean isPost,
ASTree oprand, Expr expr, boolean doDup) ASTree oprand, Expr expr, boolean doDup)
throws CompileError throws CompileError

+ 1
- 1
tutorial/tutorial.html View File

<br>3. <a href="#load">Class loader</a> <br>3. <a href="#load">Class loader</a>
<br>4. <a href="tutorial2.html#intro">Introspection and customization</a> <br>4. <a href="tutorial2.html#intro">Introspection and customization</a>
<br>5. <a href="tutorial3.html#intro">Bytecode level API</a> <br>5. <a href="tutorial3.html#intro">Bytecode level API</a>
<br>6. <a href="tutorial3.html#generics">Generics</a>
</ul> </ul>


<p><br> <p><br>

+ 65
- 0
tutorial/tutorial3.html View File



</ul> </ul>


<p><a href="#generics">6. Generics</a>


<p><br> <p><br>


of <code>javassist.bytecode.AnnotationsAttribute</code> class of <code>javassist.bytecode.AnnotationsAttribute</code> class
and the <code>javassist.bytecode.annotation</code> package. and the <code>javassist.bytecode.annotation</code> package.


<p>Javassist also let you access annotations by the higher-level
API.
If you want to access annotations through <code>CtClass</code>,
call <code>getAnnotations()</code> in <code>CtClass</code> or
<code>CtBehavior</code>.

<p><br>

<h2><a name="generics">6. Generics</a></h2>

<p>The lower-level API of Javassist fully supports generics
introduced by Java 5. On the other hand, the higher-level
API such as <code>CtClass</code> does not directly support
generics. However, this is not a serious problem for bytecode
transformation.

<p>The generics of Java is implemented by the erasure technique.
After compilation, all type parameters are dropped off. For
example, suppose that your source code declare a parameterized
type <code>Vector&lt;String&gt;</code>:

<ul><pre>
Vector&lt;String&gt; v = new Vector&lt;String&gt();
:
String s = v.get(0);
</pre></ul>

<p>The compiled bytecode is equivalent to the following code:

<ul><pre>
Vector v = new Vector();
:
String s = (String)v.get(0);
</pre></ul>

<p>So when you write a bytecode transformer, you can just drop
off all type parameters. For example, if you have a class:

<ul><pre>
public class Wrapper&lt;T&gt; {
T value;
public Wrapper(T t) { value = t; }
}
</pre></ul>

<p>and want to add an interface <code>Getter&lt;T&gt;</code> to the
class <code>Wrapper&lt;T&gt;</code>:

<ul><pre>
public interface Getter&lt;T&gt; {
T get();
}
</pre></ul>

<p>Then the interface you really have to add is <code>Getter</code>
(the type parameters <code>&lt;T&gt;<code> drops off)
and the method you also have to add to the <code>Wrapper</code>
class is this simple one:

<ul><pre>
public Object get() { return value; }
</pre></ul>

<p>Note that no type parameters are necessary.


<p><br> <p><br>



Loading…
Cancel
Save