Browse Source

fixed JASSIST-160 by rewriting the whole javassist.bytecode.stackmap package.

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

+ 1
- 1
Readme.html View File

@@ -284,7 +284,7 @@ see javassist.Dump.
<p>-version 3.17
<ul>
<li>OSGi bundle info is now included in the jar file.
<li>JIRA JASSIST-163, 166, 168, 170, 171 have been fixed.
<li>JIRA JASSIST-160, 163, 166, 168, 170, 171 have been fixed.
</ul>

<p>-version 3.16.1 on March 6, 2012

+ 18
- 1
src/main/javassist/bytecode/stackmap/Tracer.java View File

@@ -801,13 +801,30 @@ public abstract class Tracer implements TypeTag {
checkParamTypes(desc, 1);
if (notStatic) {
String className = cpool.getMethodrefClassName(i);
stackTypes[--stackTop].setType(className, classPool);
TypeData target = stackTypes[--stackTop];
if (target instanceof TypeData.UninitTypeVar && target.isUninit())
constructorCalled((TypeData.UninitTypeVar)target);

target.setType(className, classPool);
}

pushMemberType(desc);
return 3;
}

/* This is a constructor call on an uninitialized object.
* Sets flags of other references to that object.
*/
private void constructorCalled(TypeData.UninitTypeVar target) {
int offset = target.offset();
target.constructorCalled(offset);
for (int i = 0; i < stackTop; i++)
stackTypes[i].constructorCalled(offset);

for (int i = 0; i < localsTypes.length; i++)
localsTypes[i].constructorCalled(offset);
}

private int doInvokeIntfMethod(int pos, byte[] code) throws BadBytecode {
int i = ByteArray.readU16bit(code, pos + 1);
String desc = cpool.getInterfaceMethodrefType(i);

+ 54
- 3
src/main/javassist/bytecode/stackmap/TypeData.java View File

@@ -92,6 +92,9 @@ public abstract class TypeData {
*/
protected TypeVar toTypeVar() { return null; }

// see UninitTypeVar and UninitData
public void constructorCalled(int offset) {}

/**
* Primitive types.
*/
@@ -147,7 +150,8 @@ public abstract class TypeData {
public boolean eq(TypeData d) { return getName().equals(d.getName()); }
}

// a type variable representing a class type.
/* a type variable representing a class type or a basic type.
*/
public static class TypeVar extends AbsTypeVar {
protected ArrayList lowers; // lower bounds of this type. ArrayList<TypeData>
protected ArrayList usedBy; // reverse relations of lowers
@@ -615,6 +619,42 @@ public abstract class TypeData {
}
}

public static class UninitTypeVar extends AbsTypeVar {
protected TypeData type; // UninitData or TOP

public UninitTypeVar(UninitData t) { type = t; }
public int getTypeTag() { return type.getTypeTag(); }
public int getTypeData(ConstPool cp) { return type.getTypeData(cp); }
public BasicType isBasicType() { return type.isBasicType(); }
public boolean is2WordType() { return type.is2WordType(); }
public boolean isUninit() { return type.isUninit(); }
public boolean eq(TypeData d) { return type.eq(d); }
public String getName() { return type.getName(); }

protected TypeVar toTypeVar() { return null; }
public TypeData join() { return type.join(); }

public void setType(String s, ClassPool cp) throws BadBytecode {
type.setType(s, cp);
}

public void merge(TypeData t) {
if (!t.eq(type))
type = TypeTag.TOP;
}

public void constructorCalled(int offset) {
type.constructorCalled(offset);
}

public int offset() {
if (type instanceof UninitData)
return ((UninitData)type).offset;
else // if type == TypeTag.TOP
throw new RuntimeException("not available");
}
}

/**
* Type data for OBJECT.
*/
@@ -675,6 +715,8 @@ public abstract class TypeData {
this.initialized = false;
}

public UninitData copy() { return new UninitData(offset, getName()); }

public int getTypeTag() {
return StackMapTable.UNINIT;
}
@@ -684,8 +726,10 @@ public abstract class TypeData {
}

public TypeData join() {
TypeData td = initialized ? new ClassName(getName()) : this;
return new TypeVar(td);
if (initialized)
return new TypeVar(new ClassName(getName()));
else
return new UninitTypeVar(copy());
}

public boolean isUninit() { return true; }
@@ -705,6 +749,11 @@ public abstract class TypeData {
}

public String toString() { return "uninit:" + getName() + "@" + offset; }

public void constructorCalled(int offset) {
if (offset == this.offset)
initialized = true;
}
}

public static class UninitThis extends UninitData {
@@ -712,6 +761,8 @@ public abstract class TypeData {
super(-1, className);
}

public UninitData copy() { return new UninitThis(getName()); }

public int getTypeTag() {
return StackMapTable.THIS;
}

+ 45
- 0
src/test/javassist/bytecode/StackMapTest.java View File

@@ -294,6 +294,51 @@ public class StackMapTest extends TestCase {
}
}

public void testRebuildConstructor() throws Exception {
CtClass cc = loader.get("javassist.bytecode.StackMapTest$T5");
rebuildStackMaps2(cc);
cc.writeFile();
Object t1 = make(cc.getName());
assertEquals(122, invoke(t1, "test"));
}

public static class T5 {
int count;
public T5() { count = 0; }
public T5(int k) {
if (k > 0) count = 10;
else count = 100;
count++;
}
public T5(double d) {
this(d > 0.0 ? 1 : -1);
if (d > 1.0) count += 10;
else count += 100;
count++;
}
public int test() {
return new T5(3).count + new T5(1.0).count;
}
}

public void testRebuildConstructor2() throws Exception {
CtClass cc = loader.get("javassist.bytecode.StackMapTest$T6");
rebuildStackMaps2(cc);
cc.writeFile();
Object t1 = make(cc.getName());
assertEquals(101, invoke(t1, "test2"));
}

public static class T6 {
public int test2() {
T5 t0 = new T5();
T5 t = new T5(t0.count > 0 ? (new T5(t0.count > 0 ? 1 : -1).count) : -1);
if (t0.count > 0)
t.count += 1000;
return t.count;
}
}

public void tstCtClassType() throws Exception {
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("javassist.CtClassType");

Loading…
Cancel
Save