aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2007-06-02 14:12:36 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2007-06-02 14:12:36 +0000
commitb8445cabacd7ab2a9c04bc5936583060f35ef505 (patch)
tree0d3ed708d5c2ef0b2849e45b44d1ec3e250062a5 /src/main/javassist
parent8242ef42ef19f1f6a3f15e9b230f0317067f3863 (diff)
downloadjavassist-b8445cabacd7ab2a9c04bc5936583060f35ef505.tar.gz
javassist-b8445cabacd7ab2a9c04bc5936583060f35ef505.zip
fixed bugs related to stack map tables.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@378 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main/javassist')
-rw-r--r--src/main/javassist/CtBehavior.java46
-rw-r--r--src/main/javassist/CtClassType.java8
-rw-r--r--src/main/javassist/CtConstructor.java18
-rw-r--r--src/main/javassist/CtMethod.java1
-rw-r--r--src/main/javassist/CtNewConstructor.java5
-rw-r--r--src/main/javassist/CtNewWrappedMethod.java4
-rw-r--r--src/main/javassist/bytecode/ClassFile.java56
-rw-r--r--src/main/javassist/bytecode/MethodInfo.java36
-rw-r--r--src/main/javassist/compiler/CodeGen.java27
-rw-r--r--src/main/javassist/compiler/Javac.java16
-rw-r--r--src/main/javassist/compiler/MemberCodeGen.java54
-rw-r--r--src/main/javassist/expr/ExprEditor.java11
12 files changed, 240 insertions, 42 deletions
diff --git a/src/main/javassist/CtBehavior.java b/src/main/javassist/CtBehavior.java
index 249c0eae..f5e27ff4 100644
--- a/src/main/javassist/CtBehavior.java
+++ b/src/main/javassist/CtBehavior.java
@@ -62,6 +62,7 @@ public abstract class CtBehavior extends CtMember {
map.put(srcSuperName, destSuperName);
}
+ // a stack map table is copied from srcInfo.
methodInfo = new MethodInfo(cp, srcInfo.getName(), srcInfo, map);
if (isCons && patch)
methodInfo.setSuperclass(destSuperName);
@@ -349,9 +350,10 @@ public abstract class CtBehavior extends CtMember {
String delegateObj, String delegateMethod)
throws CannotCompileException
{
- declaringClass.checkModify();
+ CtClass cc = declaringClass;
+ cc.checkModify();
try {
- Javac jv = new Javac(declaringClass);
+ Javac jv = new Javac(cc);
if (delegateMethod != null)
jv.recordProceed(delegateObj, delegateMethod);
@@ -359,9 +361,12 @@ public abstract class CtBehavior extends CtMember {
methodInfo.setCodeAttribute(b.toCodeAttribute());
methodInfo.setAccessFlags(methodInfo.getAccessFlags()
& ~AccessFlag.ABSTRACT);
+ methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
}
catch (CompileError e) {
throw new CannotCompileException(e);
+ } catch (BadBytecode e) {
+ throw new CannotCompileException(e);
}
}
@@ -380,6 +385,7 @@ public abstract class CtBehavior extends CtMember {
ConstPool cp = destInfo.getConstPool();
CodeAttribute ca = (CodeAttribute)cattr.copy(cp, map);
destInfo.setCodeAttribute(ca);
+ // a stack map table is copied to destInfo.
}
}
catch (CodeAttribute.RuntimeCopyException e) {
@@ -466,7 +472,7 @@ public abstract class CtBehavior extends CtMember {
CtField field = new CtField(type, fname, cc);
field.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
cc.addField(field, CtField.Initializer.byNew(type));
- insertBefore(fname + ".enter();");
+ insertBefore(fname + ".enter();", false);
String src = fname + ".exit();";
insertAfter(src, true);
}
@@ -561,13 +567,20 @@ public abstract class CtBehavior extends CtMember {
* @see CtConstructor#insertBeforeBody(String)
*/
public void insertBefore(String src) throws CannotCompileException {
- declaringClass.checkModify();
+ insertBefore(src, true);
+ }
+
+ private void insertBefore(String src, boolean rebuild)
+ throws CannotCompileException
+ {
+ CtClass cc = declaringClass;
+ cc.checkModify();
CodeAttribute ca = methodInfo.getCodeAttribute();
if (ca == null)
throw new CannotCompileException("no method body");
CodeIterator iterator = ca.iterator();
- Javac jv = new Javac(declaringClass);
+ Javac jv = new Javac(cc);
try {
int nvars = jv.recordParams(getParameterTypes(),
Modifier.isStatic(getModifiers()));
@@ -586,6 +599,8 @@ public abstract class CtBehavior extends CtMember {
int pos = iterator.insertEx(b.get());
iterator.insert(b.getExceptionTable(), pos);
+ if (rebuild)
+ methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
}
catch (NotFoundException e) {
throw new CannotCompileException(e);
@@ -627,7 +642,8 @@ public abstract class CtBehavior extends CtMember {
public void insertAfter(String src, boolean asFinally)
throws CannotCompileException
{
- declaringClass.checkModify();
+ CtClass cc = declaringClass;
+ cc.checkModify();
ConstPool pool = methodInfo.getConstPool();
CodeAttribute ca = methodInfo.getCodeAttribute();
if (ca == null)
@@ -637,7 +653,7 @@ public abstract class CtBehavior extends CtMember {
int retAddr = ca.getMaxLocals();
Bytecode b = new Bytecode(pool, 0, retAddr + 1);
b.setStackDepth(ca.getMaxStack() + 1);
- Javac jv = new Javac(b, declaringClass);
+ Javac jv = new Javac(b, cc);
try {
int nvars = jv.recordParams(getParameterTypes(),
Modifier.isStatic(getModifiers()));
@@ -677,6 +693,8 @@ public abstract class CtBehavior extends CtMember {
subr = iterator.getCodeLength() - gapLen;
}
}
+
+ methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
}
catch (NotFoundException e) {
throw new CannotCompileException(e);
@@ -855,13 +873,14 @@ public abstract class CtBehavior extends CtMember {
String exceptionName)
throws CannotCompileException
{
- declaringClass.checkModify();
+ CtClass cc = declaringClass;
+ cc.checkModify();
ConstPool cp = methodInfo.getConstPool();
CodeAttribute ca = methodInfo.getCodeAttribute();
CodeIterator iterator = ca.iterator();
Bytecode b = new Bytecode(cp, ca.getMaxStack(), ca.getMaxLocals());
b.setStackDepth(1);
- Javac jv = new Javac(b, declaringClass);
+ Javac jv = new Javac(b, cc);
try {
jv.recordParams(getParameterTypes(),
Modifier.isStatic(getModifiers()));
@@ -883,12 +902,15 @@ public abstract class CtBehavior extends CtMember {
ca.getExceptionTable().add(getStartPosOfBody(ca), len, len,
cp.addClassInfo(exceptionType));
iterator.append(b.getExceptionTable(), pos);
+ methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
}
catch (NotFoundException e) {
throw new CannotCompileException(e);
}
catch (CompileError e) {
throw new CannotCompileException(e);
+ } catch (BadBytecode e) {
+ throw new CannotCompileException(e);
}
}
@@ -961,9 +983,10 @@ public abstract class CtBehavior extends CtMember {
if (!modify)
return lineNum;
- declaringClass.checkModify();
+ CtClass cc = declaringClass;
+ cc.checkModify();
CodeIterator iterator = ca.iterator();
- Javac jv = new Javac(declaringClass);
+ Javac jv = new Javac(cc);
try {
jv.recordLocalVariables(ca, index);
jv.recordParams(getParameterTypes(),
@@ -983,6 +1006,7 @@ public abstract class CtBehavior extends CtMember {
iterator.insert(index, b.get());
iterator.insert(b.getExceptionTable(), index);
+ methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
return lineNum;
}
catch (NotFoundException e) {
diff --git a/src/main/javassist/CtClassType.java b/src/main/javassist/CtClassType.java
index d9146d0a..ce20578f 100644
--- a/src/main/javassist/CtClassType.java
+++ b/src/main/javassist/CtClassType.java
@@ -1350,6 +1350,13 @@ class CtClassType extends CtClass {
throw new CannotCompileException(e);
}
}
+
+ try {
+ m.rebuildStackMapIf6(classPool, cf);
+ }
+ catch (BadBytecode e) {
+ throw new CannotCompileException(e);
+ }
}
private void modifyConstructors(ClassFile cf)
@@ -1375,6 +1382,7 @@ class CtClassType extends CtClass {
classPool);
int stacksize = makeFieldInitializer(init, params);
insertAuxInitializer(codeAttr, init, stacksize);
+ minfo.rebuildStackMapIf6(classPool, cf);
}
catch (BadBytecode e) {
throw new CannotCompileException(e);
diff --git a/src/main/javassist/CtConstructor.java b/src/main/javassist/CtConstructor.java
index a2868fc7..4a14bc60 100644
--- a/src/main/javassist/CtConstructor.java
+++ b/src/main/javassist/CtConstructor.java
@@ -44,7 +44,7 @@ public final class CtConstructor extends CtBehavior {
* must be added to a class with <code>CtClass.addConstructor()</code>.
*
* <p>The created constructor does not include a constructor body,
- * must be specified with <code>setBody()</code>.
+ * which must be specified with <code>setBody()</code>.
*
* @param declaring the class to which the created method is added.
* @param parameters a list of the parameter types
@@ -244,7 +244,8 @@ public final class CtConstructor extends CtBehavior {
* It must be a single statement or block.
*/
public void insertBeforeBody(String src) throws CannotCompileException {
- declaringClass.checkModify();
+ CtClass cc = declaringClass;
+ cc.checkModify();
if (isClassInitializer())
throw new CannotCompileException("class initializer");
@@ -253,7 +254,7 @@ public final class CtConstructor extends CtBehavior {
Bytecode b = new Bytecode(methodInfo.getConstPool(),
ca.getMaxStack(), ca.getMaxLocals());
b.setStackDepth(ca.getMaxStack());
- Javac jv = new Javac(b, declaringClass);
+ Javac jv = new Javac(b, cc);
try {
jv.recordParams(getParameterTypes(), false);
jv.compileStmnt(src);
@@ -262,6 +263,7 @@ public final class CtConstructor extends CtBehavior {
iterator.skipConstructor();
int pos = iterator.insertEx(b.get());
iterator.insert(b.getExceptionTable(), pos);
+ methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
}
catch (NotFoundException e) {
throw new CannotCompileException(e);
@@ -346,8 +348,16 @@ public final class CtConstructor extends CtBehavior {
if (isConstructor()) {
MethodInfo minfo = method.getMethodInfo2();
CodeAttribute ca = minfo.getCodeAttribute();
- if (ca != null)
+ if (ca != null) {
removeConsCall(ca);
+ try {
+ methodInfo.rebuildStackMapIf6(declaring.getClassPool(),
+ declaring.getClassFile2());
+ }
+ catch (BadBytecode e) {
+ throw new CannotCompileException(e);
+ }
+ }
}
method.setName(name);
diff --git a/src/main/javassist/CtMethod.java b/src/main/javassist/CtMethod.java
index a2286645..a6015dba 100644
--- a/src/main/javassist/CtMethod.java
+++ b/src/main/javassist/CtMethod.java
@@ -262,6 +262,7 @@ public final class CtMethod extends CtBehavior {
methodInfo.setCodeAttribute(cattr);
methodInfo.setAccessFlags(methodInfo.getAccessFlags()
& ~AccessFlag.ABSTRACT);
+ // rebuilding a stack map table is not needed.
}
// inner classes
diff --git a/src/main/javassist/CtNewConstructor.java b/src/main/javassist/CtNewConstructor.java
index ac3d12b2..2ac2f7ca 100644
--- a/src/main/javassist/CtNewConstructor.java
+++ b/src/main/javassist/CtNewConstructor.java
@@ -67,8 +67,10 @@ public class CtNewConstructor {
Javac compiler = new Javac(declaring);
try {
CtMember obj = compiler.compile(src);
- if (obj instanceof CtConstructor)
+ if (obj instanceof CtConstructor) {
+ // a stack map table has been already created.
return (CtConstructor)obj;
+ }
}
catch (CompileError e) {
throw new CannotCompileException(e);
@@ -145,6 +147,7 @@ public class CtNewConstructor {
code.add(Bytecode.RETURN);
+ // no need to construct a stack map table.
cons.getMethodInfo2().setCodeAttribute(code.toCodeAttribute());
return cons;
}
diff --git a/src/main/javassist/CtNewWrappedMethod.java b/src/main/javassist/CtNewWrappedMethod.java
index 88e680eb..5e48749d 100644
--- a/src/main/javassist/CtNewWrappedMethod.java
+++ b/src/main/javassist/CtNewWrappedMethod.java
@@ -63,6 +63,9 @@ class CtNewWrappedMethod {
return code;
}
+ /* The generated method body does not need a stack map table
+ * because it does not contain a branch instruction.
+ */
protected static int makeBody0(CtClass clazz, ClassFile classfile,
CtMethod wrappedBody,
boolean isStatic, CtClass[] parameters,
@@ -146,6 +149,7 @@ class CtNewWrappedMethod {
map);
int acc = body.getAccessFlags();
body.setAccessFlags(AccessFlag.setPrivate(acc));
+ // a stack map is copied. rebuilding it is not needed.
classfile.addMethod(body);
bodies.put(src, bodyname);
}
diff --git a/src/main/javassist/bytecode/ClassFile.java b/src/main/javassist/bytecode/ClassFile.java
index 3d743d7b..73cdc6ec 100644
--- a/src/main/javassist/bytecode/ClassFile.java
+++ b/src/main/javassist/bytecode/ClassFile.java
@@ -46,10 +46,28 @@ public final class ClassFile {
String cachedSuperclass;
/**
+ * The major version number of class files
+ * for JDK 1.3.
+ */
+ public static final int JAVA_3 = 47;
+
+ /**
+ * The major version number of class files
+ * for JDK 1.5.
+ */
+ public static final int JAVA_5 = 49;
+
+ /**
+ * The major version number of class files
+ * for JDK 1.6.
+ */
+ public static final int JAVA_6 = 50;
+
+ /**
* The major version number of class files created
* from scratch. The value is 47 (JDK 1.3).
*/
- public static final int MAJOR_VERSION = 47;
+ public static final int MAJOR_VERSION = JAVA_3;
/**
* Constructs a class file from a byte stream.
@@ -540,6 +558,8 @@ public final class ClassFile {
/**
* Appends a method to the class.
+ * If there is a bridge method with the same name and signature,
+ * then the bridge method is removed before a new method is added.
*
* @throws DuplicateMemberException when the method is already included.
*/
@@ -558,20 +578,38 @@ public final class ClassFile {
String name = newMinfo.getName();
String descriptor = newMinfo.getDescriptor();
ListIterator it = methods.listIterator(0);
- while (it.hasNext()) {
- MethodInfo minfo = (MethodInfo)it.next();
- if (minfo.getName().equals(name)
- && notBridgeMethod(minfo) && notBridgeMethod(newMinfo)
- && Descriptor.eqParamTypes(minfo.getDescriptor(),
- descriptor))
+ while (it.hasNext())
+ if (isDuplicated(newMinfo, name, descriptor, (MethodInfo)it.next(), it))
throw new DuplicateMemberException("duplicate method: " + name
- + " in " + this.getName());
+ + " in " + this.getName());
+ }
+
+ private static boolean isDuplicated(MethodInfo newMethod, String newName,
+ String newDesc, MethodInfo minfo,
+ ListIterator it)
+ {
+ if (!minfo.getName().equals(newName))
+ return false;
+
+ String desc = minfo.getDescriptor();
+ if (!Descriptor.eqParamTypes(desc, newDesc))
+ return false;
+
+ if (desc.equals(newDesc)) {
+ if (notBridgeMethod(minfo))
+ return true;
+ else {
+ it.remove();
+ return false;
+ }
}
+ else
+ return notBridgeMethod(minfo) && notBridgeMethod(newMethod);
}
/* For a bridge method, see Sec. 15.12.4.5 of JLS 3rd Ed.
*/
- private boolean notBridgeMethod(MethodInfo minfo) {
+ private static boolean notBridgeMethod(MethodInfo minfo) {
return (minfo.getAccessFlags() & AccessFlag.BRIDGE) == 0;
}
diff --git a/src/main/javassist/bytecode/MethodInfo.java b/src/main/javassist/bytecode/MethodInfo.java
index 8d0cce10..6e945570 100644
--- a/src/main/javassist/bytecode/MethodInfo.java
+++ b/src/main/javassist/bytecode/MethodInfo.java
@@ -21,6 +21,8 @@ import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import javassist.ClassPool;
+import javassist.bytecode.stackmap.MapMaker;
/**
* <code>method_info</code> structure.
@@ -371,6 +373,40 @@ public final class MethodInfo {
}
/**
+ * Rebuilds a stack map table if the class file is for Java 6
+ * or later. Java 5 or older Java VMs do not recognize a stack
+ * map table.
+ *
+ * @param pool used for making type hierarchy.
+ * @param cf rebuild if this class file is for Java 6 or later.
+ * @see #rebuildStackMap(ClassPool)
+ * @since 3.6
+ */
+ public void rebuildStackMapIf6(ClassPool pool, ClassFile cf)
+ throws BadBytecode
+ {
+ if (cf.getMajorVersion() >= ClassFile.JAVA_6)
+ rebuildStackMap(pool);
+ }
+
+ /**
+ * Rebuilds a stack map table. If no stack map table is included,
+ * a new one is created. If this <code>MethodInfo</code> does not
+ * include a code attribute, nothing happens.
+ *
+ * @param pool used for making type hierarchy.
+ * @see StackMapTable
+ * @since 3.6
+ */
+ public void rebuildStackMap(ClassPool pool) throws BadBytecode {
+ CodeAttribute ca = getCodeAttribute();
+ if (ca != null) {
+ StackMapTable smt = MapMaker.make(pool, this);
+ ca.setAttribute(smt);
+ }
+ }
+
+ /**
* Returns the line number of the source line corresponding to the specified
* bytecode contained in this method.
*
diff --git a/src/main/javassist/compiler/CodeGen.java b/src/main/javassist/compiler/CodeGen.java
index dfcddc4e..0712d906 100644
--- a/src/main/javassist/compiler/CodeGen.java
+++ b/src/main/javassist/compiler/CodeGen.java
@@ -53,7 +53,13 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
*/
protected static abstract class ReturnHook {
ReturnHook next;
- protected abstract void doit(Bytecode b, int opcode);
+
+ /**
+ * Returns true if the generated code ends with return,
+ * throw, or goto.
+ */
+ protected abstract boolean doit(Bytecode b, int opcode);
+
protected ReturnHook(CodeGen gen) {
next = gen.returnHooks;
gen.returnHooks = this;
@@ -607,7 +613,10 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
}
for (ReturnHook har = returnHooks; har != null; har = har.next)
- har.doit(bytecode, op);
+ if (har.doit(bytecode, op)) {
+ hasReturned = true;
+ return;
+ }
bytecode.addOpcode(op);
hasReturned = true;
@@ -645,9 +654,10 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
bc.addOpcode(MONITORENTER);
ReturnHook rh = new ReturnHook(this) {
- protected void doit(Bytecode b, int opcode) {
+ protected boolean doit(Bytecode b, int opcode) {
b.addAload(var);
b.addOpcode(MONITOREXIT);
+ return false;
}
};
@@ -665,10 +675,13 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
bc.addIndex(0);
}
- int pc4 = bc.currentPc();
- rh.doit(bc, 0); // the 2nd arg is ignored.
- bc.addOpcode(ATHROW);
- bc.addExceptionHandler(pc, pc2, pc4, 0);
+ if (pc < pc2) { // if the body is not empty
+ int pc4 = bc.currentPc();
+ rh.doit(bc, 0); // the 2nd arg is ignored.
+ bc.addOpcode(ATHROW);
+ bc.addExceptionHandler(pc, pc2, pc4, 0);
+ }
+
if (!hasReturned)
bc.write16bit(pc3, bc.currentPc() - pc3 + 1);
diff --git a/src/main/javassist/compiler/Javac.java b/src/main/javassist/compiler/Javac.java
index d32fddcf..b3d275b3 100644
--- a/src/main/javassist/compiler/Javac.java
+++ b/src/main/javassist/compiler/Javac.java
@@ -27,6 +27,7 @@ import javassist.Modifier;
import javassist.bytecode.Bytecode;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
+import javassist.bytecode.BadBytecode;
import javassist.bytecode.Opcode;
import javassist.NotFoundException;
@@ -89,8 +90,17 @@ public class Javac {
try {
if (mem instanceof FieldDecl)
return compileField((FieldDecl)mem);
- else
- return compileMethod(p, (MethodDecl)mem);
+ else {
+ CtBehavior cb = compileMethod(p, (MethodDecl)mem);
+ CtClass decl = cb.getDeclaringClass();
+ cb.getMethodInfo2()
+ .rebuildStackMapIf6(decl.getClassPool(),
+ decl.getClassFile2());
+ return cb;
+ }
+ }
+ catch (BadBytecode bb) {
+ throw new CompileError(bb.getMessage());
}
catch (CannotCompileException e) {
throw new CompileError(e.getMessage());
@@ -128,7 +138,7 @@ public class Javac {
return f;
}
- private CtMember compileMethod(Parser p, MethodDecl md)
+ private CtBehavior compileMethod(Parser p, MethodDecl md)
throws CompileError
{
int mod = MemberResolver.getModifiers(md.getModifiers());
diff --git a/src/main/javassist/compiler/MemberCodeGen.java b/src/main/javassist/compiler/MemberCodeGen.java
index 3d7ed373..71849957 100644
--- a/src/main/javassist/compiler/MemberCodeGen.java
+++ b/src/main/javassist/compiler/MemberCodeGen.java
@@ -24,8 +24,6 @@ import java.util.ArrayList;
/* Code generator methods depending on javassist.* classes.
*/
public class MemberCodeGen extends CodeGen {
- public static final int JAVA5_VER = 49;
-
protected MemberResolver resolver;
protected CtClass thisClass;
protected MethodInfo thisMethod;
@@ -106,11 +104,11 @@ public class MemberCodeGen extends CodeGen {
private void jsrJmp(Bytecode b) {
b.addOpcode(Opcode.GOTO);
- jsrList.add(new Integer(b.currentPc()));
+ jsrList.add(new int[] {b.currentPc(), var});
b.addIndex(0);
}
- protected void doit(Bytecode b, int opcode) {
+ protected boolean doit(Bytecode b, int opcode) {
switch (opcode) {
case Opcode.RETURN :
jsrJmp(b);
@@ -143,6 +141,47 @@ public class MemberCodeGen extends CodeGen {
default :
throw new RuntimeException("fatal");
}
+
+ return false;
+ }
+ }
+
+ static class JsrHook2 extends ReturnHook {
+ int var;
+ int target;
+
+ JsrHook2(CodeGen gen, int[] retTarget) {
+ super(gen);
+ target = retTarget[0];
+ var = retTarget[1];
+ }
+
+ protected boolean doit(Bytecode b, int opcode) {
+ switch (opcode) {
+ case Opcode.RETURN :
+ break;
+ case ARETURN :
+ b.addAstore(var);
+ break;
+ case IRETURN :
+ b.addIstore(var);
+ break;
+ case LRETURN :
+ b.addLstore(var);
+ break;
+ case DRETURN :
+ b.addDstore(var);
+ break;
+ case FRETURN :
+ b.addFstore(var);
+ break;
+ default :
+ throw new RuntimeException("fatal");
+ }
+
+ b.addOpcode(Opcode.GOTO);
+ b.addIndex(target - b.currentPc() + 3);
+ return true;
}
}
@@ -236,9 +275,12 @@ public class MemberCodeGen extends CodeGen {
Bytecode bc = bytecode;
int n = returnList.size();
for (int i = 0; i < n; ++i) {
- int pc = ((Integer)returnList.get(i)).intValue();
+ final int[] ret = (int[])returnList.get(i);
+ int pc = ret[0];
bc.write16bit(pc, bc.currentPc() - pc + 1);
+ ReturnHook hook = new JsrHook2(this, ret);
finallyBlock.accept(this);
+ hook.remove(this);
if (!hasReturned) {
bc.addOpcode(Opcode.GOTO);
bc.addIndex(pc + 3 - bc.currentPc());
@@ -923,7 +965,7 @@ public class MemberCodeGen extends CodeGen {
}
protected void atClassObject2(String cname) throws CompileError {
- if (getMajorVersion() < JAVA5_VER)
+ if (getMajorVersion() < ClassFile.JAVA_5)
super.atClassObject2(cname);
else
bytecode.addLdc(bytecode.getConstPool().addClassInfo(cname));
diff --git a/src/main/javassist/expr/ExprEditor.java b/src/main/javassist/expr/ExprEditor.java
index 9bba13b7..db9cb437 100644
--- a/src/main/javassist/expr/ExprEditor.java
+++ b/src/main/javassist/expr/ExprEditor.java
@@ -101,12 +101,21 @@ public class ExprEditor {
}
}
- // codeAttr might be modified by other partys
+ // codeAttr might be modified by other partiess
// so I check the current value of max-locals.
if (codeAttr.getMaxLocals() < context.maxLocals)
codeAttr.setMaxLocals(context.maxLocals);
codeAttr.setMaxStack(codeAttr.getMaxStack() + context.maxStack);
+ try {
+ if (edited)
+ minfo.rebuildStackMapIf6(clazz.getClassPool(),
+ clazz.getClassFile2());
+ }
+ catch (BadBytecode b) {
+ throw new CannotCompileException(b.getMessage(), b);
+ }
+
return edited;
}