diff options
author | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2003-05-14 16:20:13 +0000 |
---|---|---|
committer | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2003-05-14 16:20:13 +0000 |
commit | dea5156362fd172b97c0adb001402fdd6107f2a7 (patch) | |
tree | 8e39e1189d558e30d462864183bae71f06606237 /src | |
parent | 1f290d54001e508c65d6b1270c508b92d7af618c (diff) | |
download | javassist-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.java | 14 | ||||
-rw-r--r-- | src/main/javassist/CtClassType.java | 53 | ||||
-rw-r--r-- | src/main/javassist/CtConstructor.java | 4 | ||||
-rw-r--r-- | src/main/javassist/compiler/CodeGen.java | 36 | ||||
-rw-r--r-- | src/main/javassist/compiler/MemberCodeGen.java | 17 | ||||
-rw-r--r-- | src/main/javassist/expr/Expr.java | 4 |
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; |