Browse Source

adds CtBehavior#insertAfter(String,boolean,boolean) for Issue #275

tags/rel_3_26_0_ga
chibash 4 years ago
parent
commit
9108650902

+ 1
- 1
Readme.html View File



<p>-version 3.26 <p>-version 3.26
<ul> <ul>
<li>GitHub Issue #270 (PR #272), Issue #265 (PR #267), Issue #271 and #222.
<li>GitHub Issue #270 (PR #272), #265 (PR #267), #271, #222, and #275.
</ul> </ul>


<p>-version 3.25 on April 16, 2019 <p>-version 3.25 on April 16, 2019

+ 2
- 2
build.xml View File

destdir="${build.classes.dir}" destdir="${build.classes.dir}"
debug="on" debug="on"
deprecation="on" deprecation="on"
source="1.7"
target="1.7"
source="1.8"
target="1.8"
optimize="off" optimize="off"
includeantruntime="true" includeantruntime="true"
includes="**"> includes="**">

BIN
javassist.jar View File


+ 2
- 2
pom.xml View File

<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version> <version>3.2</version>
<configuration> <configuration>
<source>1.7</source>
<target>1.7</target>
<source>1.8</source>
<target>1.8</target>
<testSource>11</testSource> <testSource>11</testSource>
<testTarget>11</testTarget> <testTarget>11</testTarget>
<testCompilerArgument>-parameters</testCompilerArgument> <testCompilerArgument>-parameters</testCompilerArgument>

+ 69
- 13
src/main/javassist/CtBehavior.java View File



/** /**
* Inserts bytecode at the end of the body. * Inserts bytecode at the end of the body.
* The bytecode is inserted just before every return insturction.
* The bytecode is inserted just before every return instruction.
* It is not executed when an exception is thrown. * It is not executed when an exception is thrown.
* *
* @param src the source code representing the inserted bytecode. * @param src the source code representing the inserted bytecode.
public void insertAfter(String src) public void insertAfter(String src)
throws CannotCompileException throws CannotCompileException
{ {
insertAfter(src, false);
insertAfter(src, false, false);
} }


/** /**
* Inserts bytecode at the end of the body. * Inserts bytecode at the end of the body.
* The bytecode is inserted just before every return insturction.
* The bytecode is inserted just before every return instruction.
* *
* @param src the source code representing the inserted bytecode. * @param src the source code representing the inserted bytecode.
* It must be a single statement or block. * It must be a single statement or block.
*/ */
public void insertAfter(String src, boolean asFinally) public void insertAfter(String src, boolean asFinally)
throws CannotCompileException throws CannotCompileException
{
insertAfter(src, asFinally, false);
}

/**
* Inserts bytecode at the end of the body.
* The bytecode is inserted just before every return instruction.
*
* @param src the source code representing the inserted bytecode.
* It must be a single statement or block.
* @param asFinally true if the inserted bytecode is executed
* not only when the control normally returns
* but also when an exception is thrown.
* If this parameter is true, the inserted code cannot
* access local variables.
* @param redundant if true, redundant bytecode will be generated.
* the redundancy is necessary when some compilers (Kotlin?)
* generate the original bytecode.
* The other <code>insertAfter</code> methods calls this method
* with <code>false</code> for this parameter.
* @since 3.26
*/
public void insertAfter(String src, boolean asFinally, boolean redundant)
throws CannotCompileException
{ {
CtClass cc = declaringClass; CtClass cc = declaringClass;
cc.checkModify(); cc.checkModify();
if (c == Opcode.ARETURN || c == Opcode.IRETURN if (c == Opcode.ARETURN || c == Opcode.IRETURN
|| c == Opcode.FRETURN || c == Opcode.LRETURN || c == Opcode.FRETURN || c == Opcode.LRETURN
|| c == Opcode.DRETURN || c == Opcode.RETURN) { || c == Opcode.DRETURN || c == Opcode.RETURN) {
if (noReturn) {
// finally clause for normal termination
adviceLen = insertAfterAdvice(b, jv, src, pool, rtype, varNo);
handlerPos = iterator.append(b.get());
iterator.append(b.getExceptionTable(), handlerPos);
if (redundant) {
iterator.setMark2(handlerPos);
Bytecode bcode;
Javac jvc;
int retVarNo;
if (noReturn) {
noReturn = false;
bcode = b;
jvc = jv;
retVarNo = varNo;
}
else {
bcode = new Bytecode(pool, 0, retAddr + 1);
bcode.setStackDepth(ca.getMaxStack() + 1);
jvc = new Javac(bcode, cc);
int nvars2 = jvc.recordParams(getParameterTypes(),
Modifier.isStatic(getModifiers()));
jvc.recordParamNames(ca, nvars2);
retVarNo = jvc.recordReturnType(rtype, true);
jvc.recordLocalVariables(ca, 0);
}

int adviceLen2 = insertAfterAdvice(bcode, jvc, src, pool, rtype, retVarNo);
int offset = iterator.append(bcode.get());
iterator.append(bcode.getExceptionTable(), offset);
int advicePos2 = iterator.getCodeLength() - adviceLen2;
insertGoto(iterator, advicePos2, pos);
handlerPos = iterator.getMark2();
}
else {
if (noReturn) {
// finally clause for normal termination
adviceLen = insertAfterAdvice(b, jv, src, pool, rtype, varNo);
handlerPos = iterator.append(b.get());
iterator.append(b.getExceptionTable(), handlerPos);
advicePos = iterator.getCodeLength() - adviceLen;
handlerLen = advicePos - handlerPos;
noReturn = false;
}

insertGoto(iterator, advicePos, pos);
advicePos = iterator.getCodeLength() - adviceLen; advicePos = iterator.getCodeLength() - adviceLen;
handlerLen = advicePos - handlerPos;
noReturn = false;
handlerPos = advicePos - handlerLen;
} }
insertGoto(iterator, advicePos, pos);
advicePos = iterator.getCodeLength() - adviceLen;
handlerPos = advicePos - handlerLen;
} }
} }



+ 38
- 6
src/main/javassist/bytecode/CodeIterator.java View File

protected byte[] bytecode; protected byte[] bytecode;
protected int endPos; protected int endPos;
protected int currentPos; protected int currentPos;
protected int mark;
protected int mark, mark2;


protected CodeIterator(CodeAttribute ca) { protected CodeIterator(CodeAttribute ca) {
codeAttr = ca; codeAttr = ca;
* Moves to the first instruction. * Moves to the first instruction.
*/ */
public void begin() { public void begin() {
currentPos = mark = 0;
currentPos = mark = mark2 = 0;
endPos = getCodeLength(); endPos = getCodeLength();
} }


mark = index; mark = index;
} }


/**
* Sets a mark to the bytecode at the given index.
* The mark can be used to track the position of that bytecode
* when code blocks are inserted.
* If a code block is inclusively inserted at the position of the
* bytecode, the mark is set to the inserted code block.
*
* @see #getMark2()
* @since 3.26
*/
public void setMark2(int index) {
mark2 = index;
}

/** /**
* Gets the index of the position of the mark set by * Gets the index of the position of the mark set by
* <code>setMark</code>. * <code>setMark</code>.
*/ */
public int getMark() { return mark; } public int getMark() { return mark; }


/**
* Gets the index of the position of the mark set by
* <code>setMark2</code>.
*
* @return the index of the position.
* @see #setMark2(int)
* @since 3.26
*/
public int getMark2() { return mark2; }

/** /**
* Returns a Code attribute read with this iterator. * Returns a Code attribute read with this iterator.
*/ */


if (mark > pos || (mark == pos && exclusive)) if (mark > pos || (mark == pos && exclusive))
mark += length2; mark += length2;

if (mark2 > pos || (mark2 == pos && exclusive))
mark2 += length2;
} }


codeAttr.setCode(c); codeAttr.setCode(c);


static class Pointers { static class Pointers {
int cursor; int cursor;
int mark0, mark;
int mark0, mark, mark2;
ExceptionTable etable; ExceptionTable etable;
LineNumberAttribute line; LineNumberAttribute line;
LocalVariableAttribute vars, types; LocalVariableAttribute vars, types;
StackMapTable stack; StackMapTable stack;
StackMap stack2; StackMap stack2;


Pointers(int cur, int m, int m0, ExceptionTable et, CodeAttribute ca) {
Pointers(int cur, int m, int m2, int m0, ExceptionTable et, CodeAttribute ca) {
cursor = cur; cursor = cur;
mark = m; mark = m;
mark2 = m2;
mark0 = m0; mark0 = m0;
etable = et; // non null etable = et; // non null
line = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag); line = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
if (where < mark || (where == mark && exclusive)) if (where < mark || (where == mark && exclusive))
mark += gapLength; mark += gapLength;


if (where < mark2 || (where == mark2 && exclusive))
mark2 += gapLength;

if (where < mark0 || (where == mark0 && exclusive)) if (where < mark0 || (where == mark0 && exclusive))
mark0 += gapLength; mark0 += gapLength;


CodeAttribute ca, CodeAttribute.LdcEntry ldcs) CodeAttribute ca, CodeAttribute.LdcEntry ldcs)
throws BadBytecode throws BadBytecode
{ {
Pointers pointers = new Pointers(0, 0, 0, etable, ca);
Pointers pointers = new Pointers(0, 0, 0, 0, etable, ca);
List<Branch> jumps = makeJumpList(code, code.length, pointers); List<Branch> jumps = makeJumpList(code, code.length, pointers);
while (ldcs != null) { while (ldcs != null) {
addLdcW(ldcs, jumps); addLdcW(ldcs, jumps);
if (gapLength <= 0) if (gapLength <= 0)
return code; return code;


Pointers pointers = new Pointers(currentPos, mark, where, etable, ca);
Pointers pointers = new Pointers(currentPos, mark, mark2, where, etable, ca);
List<Branch> jumps = makeJumpList(code, code.length, pointers); List<Branch> jumps = makeJumpList(code, code.length, pointers);
byte[] r = insertGap2w(code, where, gapLength, exclusive, jumps, pointers); byte[] r = insertGap2w(code, where, gapLength, exclusive, jumps, pointers);
currentPos = pointers.cursor; currentPos = pointers.cursor;
mark = pointers.mark; mark = pointers.mark;
mark2 = pointers.mark2;
int where2 = pointers.mark0; int where2 = pointers.mark0;
if (where2 == currentPos && !exclusive) if (where2 == currentPos && !exclusive)
currentPos += gapLength; currentPos += gapLength;

+ 12
- 0
src/test/javassist/JvstTest5.java View File

Object obj = make(cc.getName()); Object obj = make(cc.getName());
assertEquals(1, invoke(obj, "run")); assertEquals(1, invoke(obj, "run"));
} }

// Issue #275
public void testRedundantInsertAfter() throws Exception {
CtClass cc = sloader.get(test5.InsertAfter.class.getName());
CtMethod m = cc.getDeclaredMethod("foo");
m.insertAfter("{ $_ += 1; }", false, true);
CtMethod m2 = cc.getDeclaredMethod("bar");
m2.insertAfter("{ $_ += 1; }", true, true);
cc.writeFile();
Object obj = make(cc.getName());
assertEquals(1, invoke(obj, "run"));
}
} }

+ 35
- 0
src/test/test5/InsertAfter.java View File

package test5;

public class InsertAfter {
public int run() {
return foo(7) + bar(20);
}

public int foo(int k) {
if (k > 0)
if (k > 10)
return k + 1;
else
return k * 10;
else
return k * 100;
}

public int bar(int k) {
if (k > 0)
try {
if (k > 10)
return k + 1;
else
return k * 10;
}
catch (Exception e) {
if (k > 0)
return k * 1000;
else
throw e;
}
else
return k * 100;
}
}

Loading…
Cancel
Save