aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2003-05-14 16:20:13 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2003-05-14 16:20:13 +0000
commitdea5156362fd172b97c0adb001402fdd6107f2a7 (patch)
tree8e39e1189d558e30d462864183bae71f06606237 /src
parent1f290d54001e508c65d6b1270c508b92d7af618c (diff)
downloadjavassist-dea5156362fd172b97c0adb001402fdd6107f2a7.tar.gz
javassist-dea5156362fd172b97c0adb001402fdd6107f2a7.zip
fixed several compiler bugs and updated the tutorial.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@14 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src')
-rw-r--r--src/main/javassist/CtClass.java14
-rw-r--r--src/main/javassist/CtClassType.java53
-rw-r--r--src/main/javassist/CtConstructor.java4
-rw-r--r--src/main/javassist/compiler/CodeGen.java36
-rw-r--r--src/main/javassist/compiler/MemberCodeGen.java17
-rw-r--r--src/main/javassist/expr/Expr.java4
6 files changed, 101 insertions, 27 deletions
diff --git a/src/main/javassist/CtClass.java b/src/main/javassist/CtClass.java
index 04576b49..497b6c8f 100644
--- a/src/main/javassist/CtClass.java
+++ b/src/main/javassist/CtClass.java
@@ -512,6 +512,7 @@ public abstract class CtClass {
* This method returns <code>null</code> if
* no class initializer is not declared.
*
+ * @see #makeClassInitializer()
* @see javassist.CtConstructor
*/
public CtConstructor getClassInitializer() {
@@ -585,6 +586,19 @@ public abstract class CtClass {
}
/**
+ * Makes a class initializer (static constructor).
+ * If the class already includes a class initializer,
+ * this method returns it.
+ *
+ * @see #getClassInitializer()
+ */
+ public CtConstructor makeClassInitializer()
+ throws CannotCompileException
+ {
+ throw new CannotCompileException("not a class");
+ }
+
+ /**
* Adds a constructor.
*/
public void addConstructor(CtConstructor c)
diff --git a/src/main/javassist/CtClassType.java b/src/main/javassist/CtClassType.java
index 9e6f90d3..73a873e9 100644
--- a/src/main/javassist/CtClassType.java
+++ b/src/main/javassist/CtClassType.java
@@ -449,15 +449,9 @@ class CtClassType extends CtClass {
public CtConstructor getClassInitializer() {
if (classInitializerCache == null) {
- List list = getClassFile2().getMethods();
- int n = list.size();
- for (int i = 0; i < n; ++i) {
- MethodInfo minfo = (MethodInfo)list.get(i);
- if (minfo.isStaticInitializer()) {
- classInitializerCache = new CtConstructor(minfo, this);
- break;
- }
- }
+ MethodInfo minfo = getClassFile2().getStaticInitializer();
+ if (minfo != null)
+ classInitializerCache = new CtConstructor(minfo, this);
}
return classInitializerCache;
@@ -635,6 +629,26 @@ class CtClassType extends CtClass {
}
}
+ public CtConstructor makeClassInitializer()
+ throws CannotCompileException
+ {
+ CtConstructor clinit = getClassInitializer();
+ if (clinit != null)
+ return clinit;
+
+ checkModify();
+ ClassFile cf = getClassFile2();
+ Bytecode code = new Bytecode(cf.getConstPool(), 0, 0);
+ try {
+ modifyClassConstructor(cf, b, 0, 0);
+ }
+ catch (CompileError e) {
+ throw new CannotCompileException(e);
+ }
+
+ return getClassInitializer();
+ }
+
public void addConstructor(CtConstructor c)
throws CannotCompileException
{
@@ -728,11 +742,11 @@ class CtClassType extends CtClass {
Bytecode code = new Bytecode(cf.getConstPool(), 0, 0);
Javac jv = new Javac(code, this);
int stacksize = 0;
- boolean none = true;
+ boolean doInit = false;
for (FieldInitLink fi = fieldInitializers; fi != null; fi = fi.next) {
CtField f = fi.field;
if (Modifier.isStatic(f.getModifiers())) {
- none = false;
+ doInit = true;
int s = fi.init.compileIfStatic(f.getType(), f.getName(),
code, jv);
if (stacksize < s)
@@ -740,15 +754,20 @@ class CtClassType extends CtClass {
}
}
- if (none)
- return; // no initializer for static fileds.
+ if (doInit) // need an initializer for static fileds.
+ modifyClassConstructor(cf, code, stacksize, 0);
+ }
+ private void modifyClassConstructor(ClassFile cf, Bytecode code,
+ int stacksize, int localsize)
+ throws CannotCompileException
+ {
MethodInfo m = cf.getStaticInitializer();
if (m == null) {
code.add(Bytecode.RETURN);
code.setMaxStack(stacksize);
- m = new MethodInfo(cf.getConstPool(),
- "<clinit>", "()V");
+ code.setMaxLocals(localsize);
+ m = new MethodInfo(cf.getConstPool(), "<clinit>", "()V");
m.setAccessFlags(AccessFlag.STATIC);
m.setCodeAttribute(code.toCodeAttribute());
cf.addMethod(m);
@@ -765,6 +784,10 @@ class CtClassType extends CtClass {
int maxstack = codeAttr.getMaxStack();
if (maxstack < stacksize)
codeAttr.setMaxStack(stacksize);
+
+ int maxlocals = codeAttr.getMaxLocals();
+ if (maxlocals < localsize)
+ codeAttr.setMaxLocals(localsize);
}
catch (BadBytecode e) {
throw new CannotCompileException(e);
diff --git a/src/main/javassist/CtConstructor.java b/src/main/javassist/CtConstructor.java
index f83bcd20..e44e6db0 100644
--- a/src/main/javassist/CtConstructor.java
+++ b/src/main/javassist/CtConstructor.java
@@ -390,12 +390,16 @@ public final class CtConstructor extends CtBehavior {
/**
* Inserts bytecode just after another constructor in the super class
* or this class is called.
+ * It does not work if this object represents a class initializer.
*
* @param src the source code representing the inserted bytecode.
* It must be a single statement or block.
*/
public void insertBeforeBody(String src) throws CannotCompileException {
declaringClass.checkModify();
+ if (isClassInitializer())
+ throw new CannotCompileException("class initializer");
+
CodeAttribute ca = methodInfo.getCodeAttribute();
CodeIterator iterator = ca.iterator();
Bytecode b = new Bytecode(methodInfo.getConstPool(),
diff --git a/src/main/javassist/compiler/CodeGen.java b/src/main/javassist/compiler/CodeGen.java
index 754b5a48..60170dbb 100644
--- a/src/main/javassist/compiler/CodeGen.java
+++ b/src/main/javassist/compiler/CodeGen.java
@@ -35,6 +35,11 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
private int tempVar;
/**
+ * true if the last visited node is a return statement.
+ */
+ protected boolean hasReturned;
+
+ /**
* Must be true if compilation is for a static method.
*/
public boolean inStaticMethod;
@@ -51,6 +56,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
public CodeGen(Bytecode b) {
bytecode = b;
tempVar = -1;
+ hasReturned = false;
inStaticMethod = false;
breakList = null;
continueList = null;
@@ -229,11 +235,11 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
if (isCons && needsSuperCall(s))
insertDefaultSuperCall();
+ hasReturned = false;
s.accept(this);
- if (isVoid
- && (bytecode.read(bytecode.currentPc() - 1) & 0xff)
- != Opcode.RETURN) {
+ if (isVoid && !hasReturned) {
bytecode.addOpcode(Opcode.RETURN);
+ hasReturned = true;
}
}
@@ -302,9 +308,12 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
atThrowStmnt(st);
else if (op == TRY)
atTryStmnt(st);
- else // LABEL, SWITCH label stament might be null?.
+ else {
+ // LABEL, SWITCH label stament might be null?.
+ hasReturned = false;
throw new CompileError(
"sorry, not supported statement: TokenId " + op);
+ }
}
private void atIfStmnt(Stmnt st) throws CompileError {
@@ -316,10 +325,14 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
int pc2 = 0;
bytecode.addIndex(0); // correct later
+ hasReturned = false;
if (thenp != null)
thenp.accept(this);
- if (elsep != null) {
+ boolean thenHasReturned = hasReturned;
+ hasReturned = false;
+
+ if (elsep != null && !thenHasReturned) {
bytecode.addOpcode(Opcode.GOTO);
pc2 = bytecode.currentPc();
bytecode.addIndex(0);
@@ -329,7 +342,10 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
if (elsep != null) {
elsep.accept(this);
- bytecode.write16bit(pc2, bytecode.currentPc() - pc2 + 1);
+ if (!thenHasReturned)
+ bytecode.write16bit(pc2, bytecode.currentPc() - pc2 + 1);
+
+ hasReturned = thenHasReturned && hasReturned;
}
}
@@ -364,6 +380,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
patchGoto(continueList, pc3);
continueList = prevContList;
breakList = prevBreakList;
+ hasReturned = false;
}
private void patchGoto(ArrayList list, int targetPc) {
@@ -416,6 +433,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
patchGoto(continueList, pc3);
continueList = prevContList;
breakList = prevBreakList;
+ hasReturned = false;
}
private void atBreakStmnt(Stmnt st, boolean notCont)
@@ -462,6 +480,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
}
bytecode.addOpcode(op);
+ hasReturned = true;
}
private void atThrowStmnt(Stmnt st) throws CompileError {
@@ -471,9 +490,12 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
throw new CompileError("bad throw statement");
bytecode.addOpcode(ATHROW);
+ hasReturned = true;
}
- protected abstract void atTryStmnt(Stmnt st) throws CompileError;
+ protected void atTryStmnt(Stmnt st) throws CompileError {
+ hasReturned = false;
+ }
private static boolean isPlusPlusExpr(ASTree expr) {
if (expr instanceof Expr) {
diff --git a/src/main/javassist/compiler/MemberCodeGen.java b/src/main/javassist/compiler/MemberCodeGen.java
index 437f1f80..97a12341 100644
--- a/src/main/javassist/compiler/MemberCodeGen.java
+++ b/src/main/javassist/compiler/MemberCodeGen.java
@@ -107,6 +107,7 @@ public class MemberCodeGen extends CodeGen {
"sorry, finally has not been supported yet");
bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);
+ hasReturned = false;
}
public void atNewExpr(NewExpr expr) throws CompileError {
@@ -228,13 +229,20 @@ public class MemberCodeGen extends CodeGen {
if (method instanceof Member) {
mname = ((Member)method).get();
targetClass = thisClass;
- bytecode.addAload(0); // this
+ if (inStaticMethod)
+ isStatic = true; // should be static
+ else
+ bytecode.addAload(0); // this
}
else if (method instanceof Keyword) { // constructor
isSpecial = true;
mname = MethodInfo.nameInit; // <init>
targetClass = thisClass;
- bytecode.addAload(0); // this
+ if (inStaticMethod)
+ throw new CompileError("a constructor cannot be static");
+ else
+ bytecode.addAload(0); // this
+
if (((Keyword)method).get() == SUPER)
targetClass = getSuperclass(targetClass);
}
@@ -358,7 +366,10 @@ public class MemberCodeGen extends CodeGen {
else if (declClass.isInterface())
bytecode.addInvokeinterface(declClass, mname, desc, count);
else
- bytecode.addInvokevirtual(declClass, mname, desc);
+ if (isStatic)
+ throw new CompileError(mname + " is not static");
+ else
+ bytecode.addInvokevirtual(declClass, mname, desc);
setReturnType(desc, isStatic, popTarget);
}
diff --git a/src/main/javassist/expr/Expr.java b/src/main/javassist/expr/Expr.java
index d34180d5..b02d40e9 100644
--- a/src/main/javassist/expr/Expr.java
+++ b/src/main/javassist/expr/Expr.java
@@ -22,9 +22,9 @@ import java.util.LinkedList;
import java.util.Iterator;
/**
- * Caller-side expression.
+ * Expression.
*/
-abstract class Expr implements Opcode {
+public abstract class Expr implements Opcode {
int currentPos;
CodeIterator iterator;
CtClass thisClass;