aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2005-12-29 16:20:02 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2005-12-29 16:20:02 +0000
commit07eda55dcc1b4e4e9f9d54beb5722709bd92e4f5 (patch)
tree874e801504912bd9dcdabb093b5bc90f00c1ddca /src/main
parentc9ab3dda7e40a5fa6fa83757a347d9256d2b77d9 (diff)
downloadjavassist-07eda55dcc1b4e4e9f9d54beb5722709bd92e4f5.tar.gz
javassist-07eda55dcc1b4e4e9f9d54beb5722709bd92e4f5.zip
implemented recursive replace() for ExprEditor.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@227 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main')
-rw-r--r--src/main/javassist/bytecode/CodeIterator.java12
-rw-r--r--src/main/javassist/expr/Expr.java56
-rw-r--r--src/main/javassist/expr/ExprEditor.java228
3 files changed, 196 insertions, 100 deletions
diff --git a/src/main/javassist/bytecode/CodeIterator.java b/src/main/javassist/bytecode/CodeIterator.java
index ab9ce7d9..eb10c871 100644
--- a/src/main/javassist/bytecode/CodeIterator.java
+++ b/src/main/javassist/bytecode/CodeIterator.java
@@ -154,6 +154,18 @@ public class CodeIterator implements Opcode {
}
/**
+ * Obtains the value that the next call
+ * to <code>next()</code> will return.
+ *
+ * <p>This method is side-effects free.
+ * Successive calls to <code>lookAhead()</code> return the
+ * same value until <code>next()</code> is called.
+ */
+ public int lookAhead() {
+ return currentPos;
+ }
+
+ /**
* Moves to the instruction for
* either <code>super()</code> or <code>this()</code>.
*
diff --git a/src/main/javassist/expr/Expr.java b/src/main/javassist/expr/Expr.java
index 7760aa6b..d0a42b74 100644
--- a/src/main/javassist/expr/Expr.java
+++ b/src/main/javassist/expr/Expr.java
@@ -43,15 +43,10 @@ import java.util.LinkedList;
*/
public abstract class Expr implements Opcode {
int currentPos;
-
CodeIterator iterator;
-
CtClass thisClass;
-
MethodInfo thisMethod;
-
boolean edited;
-
int maxLocals, maxStack;
static final String javaLangObject = "java.lang.Object";
@@ -252,6 +247,32 @@ public abstract class Expr implements Opcode {
}
}
+ /**
+ * Replaces this expression with the bytecode derived from
+ * the given source text.
+ *
+ * @param statement a Java statement.
+ */
+ public abstract void replace(String statement) throws CannotCompileException;
+
+ /**
+ * Replaces this expression with the bytecode derived from
+ * the given source text and <code>ExprEditor</code>.
+ *
+ * @param statement a Java statement.
+ * @param recursive if not null, the substituted bytecode
+ * is recursively processed by the given
+ * <code>ExprEditor</code>.
+ * @since 3.1
+ */
+ public void replace(String statement, ExprEditor recursive)
+ throws CannotCompileException
+ {
+ replace(statement);
+ if (recursive != null)
+ runEditor(recursive, iterator);
+ }
+
protected void replace0(int pos, Bytecode bytecode, int size)
throws BadBytecode {
byte[] code = bytecode.get();
@@ -268,4 +289,29 @@ public abstract class Expr implements Opcode {
maxLocals = bytecode.getMaxLocals();
maxStack = bytecode.getMaxStack();
}
+
+ protected void runEditor(ExprEditor ed, CodeIterator oldIterator)
+ throws CannotCompileException
+ {
+ CodeAttribute codeAttr = oldIterator.get();
+ int orgLocals = codeAttr.getMaxLocals();
+ int orgStack = codeAttr.getMaxStack();
+ int newLocals = locals();
+ codeAttr.setMaxStack(stack());
+ codeAttr.setMaxLocals(newLocals);
+ ExprEditor.LoopContext context
+ = new ExprEditor.LoopContext(newLocals);
+ CodeIterator iterator = codeAttr.iterator();
+ iterator.move(currentPos);
+ int size = iterator.getCodeLength();
+ int endPos = oldIterator.lookAhead();
+ if (ed.doit(thisClass, thisMethod, context, iterator, endPos))
+ edited = true;
+
+ oldIterator.move(endPos + iterator.getCodeLength() - size);
+ codeAttr.setMaxLocals(orgLocals);
+ codeAttr.setMaxStack(orgStack);
+ maxLocals = context.maxLocals;
+ maxStack += context.maxStack;
+ }
}
diff --git a/src/main/javassist/expr/ExprEditor.java b/src/main/javassist/expr/ExprEditor.java
index 475ab692..c18e426b 100644
--- a/src/main/javassist/expr/ExprEditor.java
+++ b/src/main/javassist/expr/ExprEditor.java
@@ -72,18 +72,6 @@ public class ExprEditor {
*/
public ExprEditor() {}
- static class NewOp {
- NewOp next;
- int pos;
- String type;
-
- NewOp(NewOp n, int p, String t) {
- next = n;
- pos = p;
- type = t;
- }
- }
-
/**
* Undocumented method. Do not use; internal-use only.
*/
@@ -96,85 +84,11 @@ public class ExprEditor {
CodeIterator iterator = codeAttr.iterator();
boolean edited = false;
- int maxLocals = codeAttr.getMaxLocals();
- int maxStack = 0;
-
- NewOp newList = null;
- ConstPool cp = minfo.getConstPool();
+ LoopContext context = new LoopContext(codeAttr.getMaxLocals());
while (iterator.hasNext())
- try {
- Expr expr = null;
- int pos = iterator.next();
- int c = iterator.byteAt(pos);
-
- if (c < Opcode.GETSTATIC) // c < 178
- /* skip */;
- else if (c < Opcode.NEWARRAY) { // c < 188
- if (c == Opcode.INVOKESTATIC
- || c == Opcode.INVOKEINTERFACE
- || c == Opcode.INVOKEVIRTUAL) {
- expr = new MethodCall(pos, iterator, clazz, minfo);
- edit((MethodCall)expr);
- }
- else if (c == Opcode.GETFIELD || c == Opcode.GETSTATIC
- || c == Opcode.PUTFIELD
- || c == Opcode.PUTSTATIC) {
- expr = new FieldAccess(pos, iterator, clazz, minfo, c);
- edit((FieldAccess)expr);
- }
- else if (c == Opcode.NEW) {
- int index = iterator.u16bitAt(pos + 1);
- newList = new NewOp(newList, pos,
- cp.getClassInfo(index));
- }
- else if (c == Opcode.INVOKESPECIAL) {
- if (newList != null && cp.isConstructor(newList.type,
- iterator.u16bitAt(pos + 1)) > 0) {
- expr = new NewExpr(pos, iterator, clazz, minfo,
- newList.type, newList.pos);
- edit((NewExpr)expr);
- newList = newList.next;
- }
- else {
- MethodCall mcall = new MethodCall(pos, iterator, clazz, minfo);
- if (mcall.getMethodName().equals(MethodInfo.nameInit)) {
- ConstructorCall ccall = new ConstructorCall(pos, iterator, clazz, minfo);
- expr = ccall;
- edit(ccall);
- }
- else {
- expr = mcall;
- edit(mcall);
- }
- }
- }
- }
- else { // c >= 188
- if (c == Opcode.NEWARRAY || c == Opcode.ANEWARRAY
- || c == Opcode.MULTIANEWARRAY) {
- expr = new NewArray(pos, iterator, clazz, minfo, c);
- edit((NewArray)expr);
- }
- else if (c == Opcode.INSTANCEOF) {
- expr = new Instanceof(pos, iterator, clazz, minfo);
- edit((Instanceof)expr);
- }
- else if (c == Opcode.CHECKCAST) {
- expr = new Cast(pos, iterator, clazz, minfo);
- edit((Cast)expr);
- }
- }
-
- if (expr != null && expr.edited()) {
- edited = true;
- maxLocals = max(maxLocals, expr.locals());
- maxStack = max(maxStack, expr.stack());
- }
- }
- catch (BadBytecode e) {
- throw new CannotCompileException(e);
- }
+ if (loopBody(iterator, clazz, minfo, context))
+ edited = true;
ExceptionTable et = codeAttr.getExceptionTable();
int n = et.size();
@@ -183,18 +97,142 @@ public class ExprEditor {
edit(h);
if (h.edited()) {
edited = true;
- maxLocals = max(maxLocals, h.locals());
- maxStack = max(maxStack, h.stack());
+ context.updateMax(h.locals(), h.stack());
}
}
- codeAttr.setMaxLocals(maxLocals);
- codeAttr.setMaxStack(codeAttr.getMaxStack() + maxStack);
+ codeAttr.setMaxLocals(context.maxLocals);
+ codeAttr.setMaxStack(codeAttr.getMaxStack() + context.maxStack);
+ return edited;
+ }
+
+ /**
+ * Visits each bytecode in the given range.
+ */
+ boolean doit(CtClass clazz, MethodInfo minfo, LoopContext context,
+ CodeIterator iterator, int endPos)
+ throws CannotCompileException
+ {
+ boolean edited = false;
+
+ while (iterator.hasNext() && iterator.lookAhead() < endPos)
+ if (loopBody(iterator, clazz, minfo, context))
+ edited = true;
+
return edited;
}
- private int max(int i, int j) {
- return i > j ? i : j;
+ final static class NewOp {
+ NewOp next;
+ int pos;
+ String type;
+
+ NewOp(NewOp n, int p, String t) {
+ next = n;
+ pos = p;
+ type = t;
+ }
+ }
+
+ final static class LoopContext {
+ NewOp newList;
+ int maxLocals;
+ int maxStack;
+
+ LoopContext(int locals) {
+ maxLocals = locals;
+ maxStack = 0;
+ newList = null;
+ }
+
+ void updateMax(int locals, int stack) {
+ if (maxLocals < locals)
+ maxLocals = locals;
+
+ if (maxStack < stack)
+ maxStack = stack;
+ }
+ }
+
+ final boolean loopBody(CodeIterator iterator, CtClass clazz,
+ MethodInfo minfo, LoopContext context)
+ throws CannotCompileException
+ {
+ try {
+ Expr expr = null;
+ int pos = iterator.next();
+ int c = iterator.byteAt(pos);
+
+ if (c < Opcode.GETSTATIC) // c < 178
+ /* skip */;
+ else if (c < Opcode.NEWARRAY) { // c < 188
+ if (c == Opcode.INVOKESTATIC
+ || c == Opcode.INVOKEINTERFACE
+ || c == Opcode.INVOKEVIRTUAL) {
+ expr = new MethodCall(pos, iterator, clazz, minfo);
+ edit((MethodCall)expr);
+ }
+ else if (c == Opcode.GETFIELD || c == Opcode.GETSTATIC
+ || c == Opcode.PUTFIELD
+ || c == Opcode.PUTSTATIC) {
+ expr = new FieldAccess(pos, iterator, clazz, minfo, c);
+ edit((FieldAccess)expr);
+ }
+ else if (c == Opcode.NEW) {
+ int index = iterator.u16bitAt(pos + 1);
+ context.newList = new NewOp(context.newList, pos,
+ minfo.getConstPool().getClassInfo(index));
+ }
+ else if (c == Opcode.INVOKESPECIAL) {
+ NewOp newList = context.newList;
+ if (newList != null
+ && minfo.getConstPool().isConstructor(newList.type,
+ iterator.u16bitAt(pos + 1)) > 0) {
+ expr = new NewExpr(pos, iterator, clazz, minfo,
+ newList.type, newList.pos);
+ edit((NewExpr)expr);
+ context.newList = newList.next;
+ }
+ else {
+ MethodCall mcall = new MethodCall(pos, iterator, clazz, minfo);
+ if (mcall.getMethodName().equals(MethodInfo.nameInit)) {
+ ConstructorCall ccall = new ConstructorCall(pos, iterator, clazz, minfo);
+ expr = ccall;
+ edit(ccall);
+ }
+ else {
+ expr = mcall;
+ edit(mcall);
+ }
+ }
+ }
+ }
+ else { // c >= 188
+ if (c == Opcode.NEWARRAY || c == Opcode.ANEWARRAY
+ || c == Opcode.MULTIANEWARRAY) {
+ expr = new NewArray(pos, iterator, clazz, minfo, c);
+ edit((NewArray)expr);
+ }
+ else if (c == Opcode.INSTANCEOF) {
+ expr = new Instanceof(pos, iterator, clazz, minfo);
+ edit((Instanceof)expr);
+ }
+ else if (c == Opcode.CHECKCAST) {
+ expr = new Cast(pos, iterator, clazz, minfo);
+ edit((Cast)expr);
+ }
+ }
+
+ if (expr != null && expr.edited()) {
+ context.updateMax(expr.locals(), expr.stack());
+ return true;
+ }
+ else
+ return false;
+ }
+ catch (BadBytecode e) {
+ throw new CannotCompileException(e);
+ }
}
/**