Browse Source

CtBehavior#insertAt() and support methods have been implemented.


git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@63 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
tags/rel_3_17_1_ga
chiba 20 years ago
parent
commit
33894b1cae

+ 1
- 0
Readme.html View File

@@ -259,6 +259,7 @@ see javassist.Dump.
<li>javassist.bytecode.DeprecatedAttribute has been added.
<li>javassist.bytecode.LocalVariableAttribute has been added.
<li>CtClass.getURL() and javassist.ClassPath.find() has been added.
<li>CtBehavior.insertAt() has been added.
</ul>

<p>- version 2.6 in August, 2003.

+ 78
- 0
src/main/javassist/CtBehavior.java View File

@@ -672,4 +672,82 @@ public abstract class CtBehavior extends CtMember {
throw new CannotCompileException(e);
}
}

/**
* Inserts bytecode at the specified line in the body. It is equivalent
* to insertAt(lineNum, true, src).
*
* @param lineNum the line number.
* @param src the source code representing the inserted bytecode.
* It must be a single statement or block.
*/
public int insertAt(int lineNum, String src)
throws CannotCompileException
{
return insertAt(lineNum, true, src);
}

/**
* Inserts bytecode at the specified line in the body.
*
* @param lineNum the line number.
* @param modify if false, this method does not insert the bytecode.
* It instead only returns the line number at which
* the bytecode would be inserted.
* @param src the source code representing the inserted bytecode.
* It must be a single statement or block.
* If modify is false, the value of src can be null.
*/
public int insertAt(int lineNum, boolean modify, String src)
throws CannotCompileException
{
CodeAttribute ca = methodInfo.getCodeAttribute();
if (ca == null)
throw new CannotCompileException("no method body");

LineNumberAttribute ainfo
= (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
if (ainfo == null)
throw new CannotCompileException("no line number info");

LineNumberAttribute.Pc pc = ainfo.toNearPc(lineNum);
lineNum = pc.line;
int index = pc.index;
if (!modify)
return lineNum;

declaringClass.checkModify();
CodeIterator iterator = ca.iterator();
Javac jv = new Javac(declaringClass);
try {
jv.recordParams(getParameterTypes(),
Modifier.isStatic(getModifiers()));
jv.compileStmnt(src);
Bytecode b = jv.getBytecode();
int stack = b.getMaxStack();
int locals = b.getMaxLocals();

/* We assume that there is no values in the operand stack
* at the position where the bytecode is inserted.
*/
if (stack > ca.getMaxStack())
ca.setMaxStack(stack);

if (locals > ca.getMaxLocals())
ca.setMaxLocals(locals);

iterator.insert(index, b.get());
iterator.insert(b.getExceptionTable(), index);
return lineNum;
}
catch (NotFoundException e) {
throw new CannotCompileException(e);
}
catch (CompileError e) {
throw new CannotCompileException(e);
}
catch (BadBytecode e) {
throw new CannotCompileException(e);
}
}
}

+ 4
- 3
src/main/javassist/bytecode/CodeAttribute.java View File

@@ -295,7 +295,7 @@ public class CodeAttribute extends AttributeInfo implements Opcode {

LdcEntry ldc = copyCode(this.info, 0, len, this.getConstPool(),
newCode, destCp, classnames);
return LdcEntry.doit(newCode, ldc, etable);
return LdcEntry.doit(newCode, ldc, etable, this);
}

private static LdcEntry copyCode(byte[] code, int beginPos, int endPos,
@@ -377,12 +377,13 @@ final class LdcEntry {
int where;
int index;

static byte[] doit(byte[] code, LdcEntry ldc, ExceptionTable etable)
static byte[] doit(byte[] code, LdcEntry ldc, ExceptionTable etable,
CodeAttribute ca)
throws BadBytecode
{
while (ldc != null) {
int where = ldc.where;
code = CodeIterator.insertGap(code, where, 1, false, etable);
code = CodeIterator.insertGap(code, where, 1, false, etable, ca);
code[where] = (byte)Opcode.LDC_W;
ByteArray.write16bit(ldc.index, code, where + 1);
ldc = ldc.next;

+ 16
- 5
src/main/javassist/bytecode/CodeIterator.java View File

@@ -450,7 +450,7 @@ public class CodeIterator implements Opcode {

int cur = currentPos;
byte[] c = insertGap(bytecode, pos, length, exclusive,
get().getExceptionTable());
get().getExceptionTable(), codeAttr);
int length2 = c.length - bytecode.length;
if (cur >= pos)
currentPos = cur + length2;
@@ -599,19 +599,19 @@ public class CodeIterator implements Opcode {
* a multiple of 4.
*/
static byte[] insertGap(byte[] code, int where, int gapLength,
boolean exclusive, ExceptionTable etable)
boolean exclusive, ExceptionTable etable, CodeAttribute ca)
throws BadBytecode
{
if (gapLength <= 0)
return code;

try {
return insertGap0(code, where, gapLength, exclusive, etable);
return insertGap0(code, where, gapLength, exclusive, etable, ca);
}
catch (AlignmentException e) {
try {
return insertGap0(code, where, (gapLength + 3) & ~3,
exclusive, etable);
exclusive, etable, ca);
}
catch (AlignmentException e2) {
throw new RuntimeException("fatal error?");
@@ -620,13 +620,24 @@ public class CodeIterator implements Opcode {
}

private static byte[] insertGap0(byte[] code, int where, int gapLength,
boolean exclusive, ExceptionTable etable)
boolean exclusive, ExceptionTable etable,
CodeAttribute ca)
throws BadBytecode, AlignmentException
{
int codeLength = code.length;
byte[] newcode = new byte[codeLength + gapLength];
insertGap2(code, where, gapLength, codeLength, newcode, exclusive);
etable.shiftPc(where, gapLength, exclusive);
LineNumberAttribute na
= (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
if (na != null)
na.shiftPc(where, gapLength, exclusive);

LocalVariableAttribute va = (LocalVariableAttribute)ca.getAttribute(
LocalVariableAttribute.tag);
if (va != null)
va.shiftPc(where, gapLength, exclusive);

return newcode;
}


+ 60
- 0
src/main/javassist/bytecode/LineNumberAttribute.java View File

@@ -102,6 +102,53 @@ public class LineNumberAttribute extends AttributeInfo {
return -1;
}

/**
* Used as a return type of <code>toNearPc()</code>.
*/
static public class Pc {
/**
* The index into the code array.
*/
public int index;
/**
* The line number.
*/
public int line;
}

/**
* Returns the index into the code array at which the code for
* the specified line (or the nearest line after the specified one)
* begins.
*
* @param line the line number.
* @return a pair of the index and the line number of the
* bytecode at that index.
*/
public Pc toNearPc(int line) {
int n = tableLength();
int nearPc = 0;
int distance = 0;
if (n > 0) {
distance = lineNumber(0) - line;
nearPc = startPc(0);
}

for (int i = 1; i < n; ++i) {
int d = lineNumber(i) - line;
if ((d < 0 && d > distance)
|| (d >= 0 && (d < distance || distance < 0))) {
distance = d;
nearPc = startPc(i);
}
}

Pc res = new Pc();
res.index = nearPc;
res.line = line + distance;
return res;
}

/**
* Makes a copy.
*
@@ -118,4 +165,17 @@ public class LineNumberAttribute extends AttributeInfo {
LineNumberAttribute attr = new LineNumberAttribute(newCp, dest);
return attr;
}

/**
* Adjusts start_pc if bytecode is inserted in a method body.
*/
void shiftPc(int where, int gapLength, boolean exclusive) {
int n = tableLength();
for (int i = 0; i < n; ++i) {
int pos = i * 4 + 2;
int pc = ByteArray.readU16bit(info, pos);
if (pc > where || (exclusive && pc == where))
ByteArray.write16bit(pc + gapLength, info, pos);
}
}
}

+ 16
- 0
src/main/javassist/bytecode/LocalVariableAttribute.java View File

@@ -68,6 +68,22 @@ public class LocalVariableAttribute extends AttributeInfo {
return ByteArray.readU16bit(info, i * 10 + 4);
}

/**
* Adjusts start_pc and length if bytecode is inserted in a method body.
*/
void shiftPc(int where, int gapLength, boolean exclusive) {
int n = tableLength();
for (int i = 0; i < n; ++i) {
int pos = i * 10 + 2;
int pc = ByteArray.readU16bit(info, pos);
int len = ByteArray.readU16bit(info, pos + 2);
if (pc > where || (exclusive && pc == where))
ByteArray.write16bit(pc + gapLength, info, pos);
else if (pc + len > where)
ByteArray.write16bit(len + gapLength, info, pos + 2);
}
}

/**
* Returns <code>local_variable_table[i].name_index</code>.
* This represents the name of the local variable.

Loading…
Cancel
Save