some (very) basic support for pointer / reference types
This commit is contained in:
parent
800203a71f
commit
bab4777e4c
|
@ -35,6 +35,7 @@ import com.ibm.wala.ssa.SSANewInstruction;
|
|||
import com.ibm.wala.ssa.SSAReturnInstruction;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import static com.ibm.wala.types.TypeName.*;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
@ -227,8 +228,17 @@ public abstract class AbstractReflectionInterpreter implements SSAContextInterpr
|
|||
|
||||
if (t.isArrayType()) {
|
||||
// for now, just allocate an array of size 1 in each dimension.
|
||||
int dim = t.getDimensionality();
|
||||
int[] extents = new int[dim];
|
||||
int dims = 0;
|
||||
int dim = t.getDerivedMask();
|
||||
if ((dim&ElementMask) == PrimitiveMask) {
|
||||
dim >>= 2;
|
||||
}
|
||||
while ((dim&ElementMask) == ArrayMask) {
|
||||
dims++;
|
||||
dim >>=2;
|
||||
}
|
||||
|
||||
int[] extents = new int[dims];
|
||||
Arrays.fill(extents, 1);
|
||||
SSANewInstruction a = insts.NewInstruction(alloc, ref, extents);
|
||||
addInstruction(t, a, true);
|
||||
|
|
|
@ -18,6 +18,7 @@ import java.util.Set;
|
|||
|
||||
import com.ibm.wala.cfg.ControlFlowGraph;
|
||||
import com.ibm.wala.cfg.InducedCFG;
|
||||
import com.ibm.wala.classLoader.ArrayClass;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.CodeScanner;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
|
@ -155,7 +156,7 @@ public class CloneInterpreter implements SSAContextInterpreter {
|
|||
if (klass.isArrayClass()) {
|
||||
int length = nextLocal++;
|
||||
statements.add(insts.ArrayLengthInstruction(length, 1));
|
||||
int[] sizes = new int[klass.getReference().getDimensionality()];
|
||||
int[] sizes = new int[((ArrayClass)klass).getDimensionality()];
|
||||
Arrays.fill(sizes, length);
|
||||
N = insts.NewInstruction(retValue, ref, sizes);
|
||||
} else {
|
||||
|
|
|
@ -25,6 +25,7 @@ import com.ibm.wala.analysis.typeInference.SetType;
|
|||
import com.ibm.wala.analysis.typeInference.TypeAbstraction;
|
||||
import com.ibm.wala.cfg.ControlFlowGraph;
|
||||
import com.ibm.wala.cfg.InducedCFG;
|
||||
import com.ibm.wala.classLoader.ArrayClass;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.CodeScanner;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
|
@ -528,7 +529,7 @@ class FactoryBypassInterpreter extends AbstractReflectionInterpreter {
|
|||
NewSiteReference ref = NewSiteReference.make(getNewSiteForType(T), T);
|
||||
SSANewInstruction a = null;
|
||||
if (T.isArrayType()) {
|
||||
int[] sizes = new int[T.getDimensionality()];
|
||||
int[] sizes = new int[((ArrayClass)klass).getDimensionality()];
|
||||
initValueNumberForConstantOne();
|
||||
Arrays.fill(sizes, valueNumberForConstantOne);
|
||||
a = insts.NewInstruction(i, ref, sizes);
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.ibm.wala.ipa.cha.IClassHierarchy;
|
|||
import com.ibm.wala.shrikeBT.Constants;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import static com.ibm.wala.types.TypeName.*;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
@ -234,7 +235,17 @@ public class ArrayClass implements IClass, Constants {
|
|||
}
|
||||
|
||||
public int getDimensionality() {
|
||||
return getReference().getDimensionality();
|
||||
int mask = getReference().getDerivedMask();
|
||||
if ((mask&PrimitiveMask) == PrimitiveMask) {
|
||||
mask >>= 2;
|
||||
}
|
||||
int dims = 0;
|
||||
while ((mask&ArrayMask) == ArrayMask) {
|
||||
mask >>= 2;
|
||||
dims++;
|
||||
}
|
||||
assert dims>0;
|
||||
return dims;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.util.Iterator;
|
|||
import java.util.Map;
|
||||
|
||||
import com.ibm.wala.cfg.InducedCFG;
|
||||
import com.ibm.wala.classLoader.ArrayClass;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
|
@ -174,7 +175,7 @@ public abstract class AbstractRootMethod extends SyntheticMethod {
|
|||
int instance = nextLocal++;
|
||||
NewSiteReference ref = NewSiteReference.make(statements.size(), T);
|
||||
assert T.isArrayType();
|
||||
assert T.getDimensionality() == 1;
|
||||
assert ((ArrayClass)cha.lookupClass(T)).getDimensionality() == 1;
|
||||
int[] sizes = new int[1];
|
||||
Arrays.fill(sizes, getValueNumberForIntConstant(length));
|
||||
SSANewInstruction result = insts.NewInstruction(instance, ref, sizes);
|
||||
|
@ -206,7 +207,7 @@ public abstract class AbstractRootMethod extends SyntheticMethod {
|
|||
if (T.isReferenceType()) {
|
||||
NewSiteReference ref = NewSiteReference.make(statements.size(), T);
|
||||
if (T.isArrayType()) {
|
||||
int[] sizes = new int[T.getDimensionality()];
|
||||
int[] sizes = new int[((ArrayClass)cha.lookupClass(T)).getDimensionality()];
|
||||
Arrays.fill(sizes, getValueNumberForIntConstant(1));
|
||||
result = insts.NewInstruction(instance, ref, sizes);
|
||||
} else {
|
||||
|
@ -229,7 +230,7 @@ public abstract class AbstractRootMethod extends SyntheticMethod {
|
|||
int alloc = nextLocal++;
|
||||
SSANewInstruction ni = null;
|
||||
if (e.isArrayType()) {
|
||||
int[] sizes = new int[T.getDimensionality()];
|
||||
int[] sizes = new int[((ArrayClass)cha.lookupClass(T)).getDimensionality()];
|
||||
Arrays.fill(sizes, getValueNumberForIntConstant(1));
|
||||
ni = insts.NewInstruction(alloc, n, sizes);
|
||||
} else {
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.util.Iterator;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.classLoader.ArrayClass;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IField;
|
||||
import com.ibm.wala.dataflow.graph.BitVectorSolver;
|
||||
|
@ -259,7 +260,7 @@ public class ModRef {
|
|||
@Override
|
||||
public void visitNew(SSANewInstruction instruction) {
|
||||
if (instruction.getConcreteType().isArrayType()) {
|
||||
int dim = instruction.getConcreteType().getDimensionality();
|
||||
int dim = ((ArrayClass)n.getClassHierarchy().lookupClass(instruction.getConcreteType())).getDimensionality();
|
||||
if (dim > 1) {
|
||||
// we need to handle the top-level allocation, just like the 1D case
|
||||
InstanceKey ik = h.getInstanceKeyForAllocation(n, instruction.getNewSite());
|
||||
|
|
|
@ -45,6 +45,7 @@ import com.ibm.wala.types.Descriptor;
|
|||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import static com.ibm.wala.types.TypeName.*;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
|
@ -515,7 +516,11 @@ public class XMLMethodSummaryReader implements BytecodeConstants {
|
|||
Assertions.productionAssertion(size != null);
|
||||
Integer sNumber = symbolTable.get(size);
|
||||
Assertions.productionAssertion(sNumber != null);
|
||||
Assertions.productionAssertion(type.getDimensionality() == 1);
|
||||
Assertions.productionAssertion(
|
||||
// array of objects
|
||||
type.getDerivedMask()==ArrayMask ||
|
||||
// array of primitives
|
||||
type.getDerivedMask()==((ArrayMask<<2)|PrimitiveMask));
|
||||
a = insts.NewInstruction(defNum, ref, new int[] { sNumber.intValue() });
|
||||
} else {
|
||||
a = insts.NewInstruction(defNum, ref);
|
||||
|
|
|
@ -27,6 +27,14 @@ import com.ibm.wala.util.strings.StringStuff;
|
|||
*/
|
||||
public final class TypeName implements Serializable {
|
||||
|
||||
public static final byte ArrayMask = 0x01;
|
||||
public static final byte PointerMask = 0x02;
|
||||
public static final byte ReferenceMask = 0x03;
|
||||
public static final byte PrimitiveMask = 0x04;
|
||||
|
||||
public static final byte ElementMask = 0x07;
|
||||
public static final byte ElementBits = 3;
|
||||
|
||||
/* Serial version */
|
||||
private static final long serialVersionUID = -3256390509887654326L;
|
||||
|
||||
|
@ -54,12 +62,17 @@ public final class TypeName implements Serializable {
|
|||
Atom className = Atom.findOrCreate(StringStuff.parseForClass(name, start, length));
|
||||
ImmutableByteArray p = StringStuff.parseForPackage(name, start, length);
|
||||
Atom packageName = (p == null) ? null : Atom.findOrCreate(p);
|
||||
short dim = StringStuff.parseForArrayDimensionality(name, start, length);
|
||||
int dim = StringStuff.parseForArrayDimensionality(name, start, length);
|
||||
boolean innermostPrimitive = StringStuff.classIsPrimitive(name, start, length);
|
||||
if (innermostPrimitive && (dim == 0)) {
|
||||
dim = -1;
|
||||
if (innermostPrimitive) {
|
||||
if (dim == 0) {
|
||||
dim = -1;
|
||||
} else {
|
||||
dim <<= ElementBits;
|
||||
dim |= PrimitiveMask;
|
||||
}
|
||||
}
|
||||
TypeNameKey t = new TypeNameKey(packageName, className, dim, innermostPrimitive);
|
||||
TypeNameKey t = new TypeNameKey(packageName, className, dim);
|
||||
return findOrCreate(t);
|
||||
}
|
||||
|
||||
|
@ -82,12 +95,12 @@ public final class TypeName implements Serializable {
|
|||
if (className == null) {
|
||||
throw new IllegalArgumentException("null className");
|
||||
}
|
||||
TypeNameKey T = new TypeNameKey(packageName, className, (short) 0, false);
|
||||
TypeNameKey T = new TypeNameKey(packageName, className, 0);
|
||||
return findOrCreate(T);
|
||||
}
|
||||
|
||||
private static TypeName findOrCreate(Atom packageName, Atom className, short dim, boolean innermostPrimitive) {
|
||||
TypeNameKey T = new TypeNameKey(packageName, className, dim, innermostPrimitive);
|
||||
public static TypeName findOrCreate(Atom packageName, Atom className, int dim) {
|
||||
TypeNameKey T = new TypeNameKey(packageName, className, dim);
|
||||
return findOrCreate(T);
|
||||
}
|
||||
|
||||
|
@ -141,29 +154,52 @@ public final class TypeName implements Serializable {
|
|||
* @return the name of the array element type for an array
|
||||
*/
|
||||
public TypeName parseForArrayElementName() {
|
||||
short newDim = (short) (key.dim - 1);
|
||||
if (newDim == 0 && key.innermostPrimitive) {
|
||||
newDim = -1;
|
||||
int newDim;
|
||||
if ((key.dim&ElementMask) == PrimitiveMask) {
|
||||
int tmpDim = key.dim>>(2*ElementBits);
|
||||
if (tmpDim == 0) {
|
||||
newDim = -1;
|
||||
} else {
|
||||
newDim = (tmpDim<<ElementBits) | PrimitiveMask;
|
||||
}
|
||||
} else {
|
||||
newDim = key.dim>>ElementBits;
|
||||
}
|
||||
return findOrCreate(key.packageName, key.className, newDim, key.innermostPrimitive);
|
||||
|
||||
return findOrCreate(key.packageName, key.className, newDim);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a type name that represents an array of this element type
|
||||
*/
|
||||
public TypeName getArrayTypeForElementType() {
|
||||
short newDim = (short) (key.dim + 1);
|
||||
if (newDim == 0) {
|
||||
newDim = 1;
|
||||
private TypeName getDerivedTypeForElementType(byte mask) {
|
||||
int newDim;
|
||||
if (key.dim == -1) {
|
||||
newDim = mask<<ElementBits | PrimitiveMask;
|
||||
} else if ((key.dim & ElementMask) == PrimitiveMask) {
|
||||
newDim = (((key.dim & ~ElementMask) | mask)<<ElementBits) | PrimitiveMask;
|
||||
} else {
|
||||
newDim = key.dim<<ElementBits | mask;
|
||||
}
|
||||
return findOrCreate(key.packageName, key.className, newDim, key.innermostPrimitive);
|
||||
|
||||
return findOrCreate(key.packageName, key.className, newDim);
|
||||
}
|
||||
|
||||
public TypeName getArrayTypeForElementType() {
|
||||
return getDerivedTypeForElementType(ArrayMask);
|
||||
}
|
||||
public TypeName getPointerTypeForElementType() {
|
||||
return getDerivedTypeForElementType(PointerMask);
|
||||
}
|
||||
public TypeName getReferenceTypeForElementType() {
|
||||
return getDerivedTypeForElementType(ReferenceMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dimensionality of the type. By convention, class types have dimensionality 0, primitves -1, and arrays the number
|
||||
* @return the dimensionality of the type. By convention, class types have dimensionality 0, primitives -1, and arrays the number
|
||||
* of [ in their descriptor.
|
||||
*/
|
||||
public final int getDimensionality() {
|
||||
public final int getDerivedMask() {
|
||||
return key.dim;
|
||||
}
|
||||
|
||||
|
@ -192,8 +228,8 @@ public final class TypeName implements Serializable {
|
|||
* Return the innermost element type reference for an array
|
||||
*/
|
||||
public final TypeName getInnermostElementType() {
|
||||
short newDim = key.innermostPrimitive ? (short) -1 : 0;
|
||||
return findOrCreate(key.packageName, key.className, newDim, key.innermostPrimitive);
|
||||
short newDim = ((key.dim&ElementMask) == PrimitiveMask) ? (short) -1 : 0;
|
||||
return findOrCreate(key.packageName, key.className, newDim);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -211,31 +247,26 @@ public final class TypeName implements Serializable {
|
|||
private final Atom className;
|
||||
|
||||
/**
|
||||
* Dimensionality: -1 => primitive 0 => class >0 => array
|
||||
* Dimensionality: -1 => primitive
|
||||
* 0 => class
|
||||
* >0 => mask of levels of array, reference, pointer
|
||||
*/
|
||||
private final short dim;
|
||||
|
||||
/**
|
||||
* Is the innermost element type a primitive? TODO: encode in dim?
|
||||
*/
|
||||
private final boolean innermostPrimitive;
|
||||
private final int dim;
|
||||
|
||||
/**
|
||||
* This should be the only constructor
|
||||
*/
|
||||
private TypeNameKey(Atom packageName, Atom className, short dim, boolean innermostPrimitive) {
|
||||
private TypeNameKey(Atom packageName, Atom className, int dim) {
|
||||
this.packageName = packageName;
|
||||
this.className = className;
|
||||
this.dim = dim;
|
||||
this.innermostPrimitive = innermostPrimitive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof TypeNameKey) {
|
||||
TypeNameKey other = (TypeNameKey) obj;
|
||||
return className == other.className && packageName == other.packageName && dim == other.dim
|
||||
&& innermostPrimitive == other.innermostPrimitive;
|
||||
return className == other.className && packageName == other.packageName && dim == other.dim;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -246,7 +277,7 @@ public final class TypeName implements Serializable {
|
|||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = className.hashCode() * 5009 + dim * 5011 + (innermostPrimitive ? 5021 : 5023);
|
||||
int result = className.hashCode() * 5009 + dim * 5011;
|
||||
if (packageName != null) {
|
||||
result += packageName.hashCode();
|
||||
}
|
||||
|
@ -256,14 +287,7 @@ public final class TypeName implements Serializable {
|
|||
@Override
|
||||
public String toString() {
|
||||
StringBuffer result = new StringBuffer();
|
||||
for (short i = 0; i < dim; i++) {
|
||||
result.append("[");
|
||||
}
|
||||
if (!innermostPrimitive) {
|
||||
result.append("L");
|
||||
} else if (packageName != null && innermostPrimitive) {
|
||||
result.append("P");
|
||||
}
|
||||
toStringPrefix(result);
|
||||
|
||||
if (packageName != null) {
|
||||
result.append(packageName.toString());
|
||||
|
@ -274,17 +298,34 @@ public final class TypeName implements Serializable {
|
|||
return result.toString();
|
||||
}
|
||||
|
||||
private void toStringPrefix(StringBuffer result) {
|
||||
boolean isPrimitive = (dim==-1) || (dim&ElementMask)==PrimitiveMask;
|
||||
if (dim != -1) {
|
||||
for (int d = (dim&ElementMask) == PrimitiveMask? dim>>ElementBits: dim; d != 0; d>>=ElementBits) {
|
||||
switch (d&ElementMask) {
|
||||
case ArrayMask:
|
||||
result.append("[");
|
||||
break;
|
||||
case PointerMask:
|
||||
result.append("*");
|
||||
break;
|
||||
case ReferenceMask:
|
||||
result.append("&");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isPrimitive) {
|
||||
result.append("L");
|
||||
} else if (packageName != null && isPrimitive) {
|
||||
result.append("P");
|
||||
}
|
||||
}
|
||||
|
||||
public String toUnicodeString() {
|
||||
try {
|
||||
StringBuffer result = new StringBuffer();
|
||||
for (short i = 0; i < dim; i++) {
|
||||
result.append("[");
|
||||
}
|
||||
if (!innermostPrimitive) {
|
||||
result.append("L");
|
||||
} else if (packageName != null && innermostPrimitive) {
|
||||
result.append("P");
|
||||
}
|
||||
toStringPrefix(result);
|
||||
|
||||
if (packageName != null) {
|
||||
result.append(packageName.toUnicodeString());
|
||||
|
|
|
@ -318,6 +318,10 @@ public final class TypeReference implements Serializable {
|
|||
|
||||
public final static byte ArrayTypeCode = '[';
|
||||
|
||||
public final static byte PointerTypeCode = '*';
|
||||
|
||||
public final static byte ReferenceTypeCode = '&';
|
||||
|
||||
// TODO! the following two are unsound hacks; kill them.
|
||||
final static TypeName NullName = TypeName.string2TypeName("null");
|
||||
|
||||
|
@ -412,6 +416,30 @@ public final class TypeReference implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
public static TypeReference findOrCreateReferenceTo(TypeReference t) {
|
||||
if (t == null) {
|
||||
throw new IllegalArgumentException("t is null");
|
||||
}
|
||||
TypeName name = t.getName();
|
||||
if (t.isPrimitiveType()) {
|
||||
return findOrCreate(ClassLoaderReference.Primordial, name.getReferenceTypeForElementType());
|
||||
} else {
|
||||
return findOrCreate(t.getClassLoader(), name.getReferenceTypeForElementType());
|
||||
}
|
||||
}
|
||||
|
||||
public static TypeReference findOrCreatePointerTo(TypeReference t) {
|
||||
if (t == null) {
|
||||
throw new IllegalArgumentException("t is null");
|
||||
}
|
||||
TypeName name = t.getName();
|
||||
if (t.isPrimitiveType()) {
|
||||
return findOrCreate(ClassLoaderReference.Primordial, name.getPointerTypeForElementType());
|
||||
} else {
|
||||
return findOrCreate(t.getClassLoader(), name.getPointerTypeForElementType());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NB: All type names should use '/' and not '.' as a separator. eg. Ljava/lang/Class
|
||||
*
|
||||
|
@ -456,8 +484,8 @@ public final class TypeReference implements Serializable {
|
|||
* Return the dimensionality of the type. By convention, class types have dimensionality 0, primitives -1, and arrays
|
||||
* the number of [ in their descriptor.
|
||||
*/
|
||||
public final int getDimensionality() {
|
||||
return name.getDimensionality();
|
||||
public final int getDerivedMask() {
|
||||
return name.getDerivedMask();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
*******************************************************************************/
|
||||
package com.ibm.wala.util.strings;
|
||||
|
||||
import static com.ibm.wala.types.TypeName.*;
|
||||
import static com.ibm.wala.types.TypeReference.ArrayTypeCode;
|
||||
import static com.ibm.wala.types.TypeReference.PointerTypeCode;
|
||||
import static com.ibm.wala.types.TypeReference.ReferenceTypeCode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
@ -263,28 +268,19 @@ public class StringStuff {
|
|||
|
||||
continue;
|
||||
}
|
||||
case TypeReference.ArrayTypeCode: {
|
||||
case TypeReference.ArrayTypeCode:
|
||||
case TypeReference.PointerTypeCode:
|
||||
case TypeReference.ReferenceTypeCode: {
|
||||
int off = i - 1;
|
||||
while (b.get(i) == TypeReference.ArrayTypeCode) {
|
||||
++i;
|
||||
while (StringStuff.isTypeCodeChar(b, i)) {
|
||||
++i;
|
||||
}
|
||||
TypeName T = null;
|
||||
byte c = b.get(i++);
|
||||
if (c == TypeReference.ClassTypeCode) {
|
||||
if (c == TypeReference.ClassTypeCode || c == TypeReference.OtherPrimitiveTypeCode) {
|
||||
while (b.get(i++) != ';')
|
||||
;
|
||||
T = TypeName.findOrCreate(b, off, i - off - 1);
|
||||
} else if (c == TypeReference.OtherPrimitiveTypeCode) {
|
||||
int typeOff = i;
|
||||
|
||||
while (b.get(i++) != ';')
|
||||
;
|
||||
|
||||
T = l.lookupPrimitiveType(new String(b.substring(typeOff, i - typeOff - 1)));
|
||||
while (--typeOff > off) {
|
||||
T = T.getArrayTypeForElementType();
|
||||
}
|
||||
|
||||
} else {
|
||||
T = TypeName.findOrCreate(b, off, i - off);
|
||||
}
|
||||
|
@ -309,6 +305,12 @@ public class StringStuff {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean isTypeCodeChar(ImmutableByteArray name, int i) {
|
||||
return name.b[i] == TypeReference.ArrayTypeCode ||
|
||||
name.b[i] == TypeReference.PointerTypeCode ||
|
||||
name.b[i] == TypeReference.ReferenceTypeCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given that name[start:start+length] is a Type name in JVM format, parse it for the package
|
||||
*
|
||||
|
@ -329,7 +331,10 @@ public class StringStuff {
|
|||
if (lastSlash == -1) {
|
||||
return null;
|
||||
}
|
||||
short dim = parseForArrayDimensionality(name, start, length);
|
||||
short dim = 0;
|
||||
while (isTypeCodeChar(name, start+dim)) {
|
||||
dim++;
|
||||
}
|
||||
return new ImmutableByteArray(name.b, start + 1 + dim, lastSlash - start - 1 - dim);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
throw new IllegalArgumentException("invalid name " + name + " start: " + start + " length: " + length);
|
||||
|
@ -366,7 +371,7 @@ public class StringStuff {
|
|||
}
|
||||
try {
|
||||
if (parseForPackage(name, start, length) == null) {
|
||||
while (name.b[start] == '[') {
|
||||
while (isTypeCodeChar(name, start)) {
|
||||
start++;
|
||||
length--;
|
||||
}
|
||||
|
@ -410,22 +415,30 @@ public class StringStuff {
|
|||
* @return dimensionality - something like "1" or "2"
|
||||
* @throws IllegalArgumentException if b == null
|
||||
*/
|
||||
public static short parseForArrayDimensionality(ImmutableByteArray b, int start, int length) throws IllegalArgumentException,
|
||||
public static int parseForArrayDimensionality(ImmutableByteArray b, int start, int length) throws IllegalArgumentException,
|
||||
IllegalArgumentException {
|
||||
|
||||
if (b == null) {
|
||||
throw new IllegalArgumentException("b == null");
|
||||
}
|
||||
try {
|
||||
int code = 0;
|
||||
for (int i = start; i < start + length; ++i) {
|
||||
if (b.b[i] != '[') {
|
||||
return (short) (i - start);
|
||||
if (isTypeCodeChar(b, i)) {
|
||||
code <<= ElementBits;
|
||||
switch (b.b[i]) {
|
||||
case ArrayTypeCode: code |= ArrayMask; break;
|
||||
case PointerTypeCode: code |= PointerMask; break;
|
||||
case ReferenceTypeCode: code |= ReferenceMask; break;
|
||||
default:
|
||||
throw new IllegalArgumentException("ill-formed array descriptor " + b);
|
||||
}
|
||||
}
|
||||
}
|
||||
return code;
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
throw new IllegalArgumentException("ill-formed array descriptor " + b);
|
||||
}
|
||||
throw new IllegalArgumentException("ill-formed array descriptor " + b);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -443,7 +456,7 @@ public class StringStuff {
|
|||
try {
|
||||
int i = start;
|
||||
for (; i < start + length; ++i) {
|
||||
if (b.b[i] != '[') {
|
||||
if (! isTypeCodeChar(b, i)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -477,7 +490,7 @@ public class StringStuff {
|
|||
throw new IllegalArgumentException("name is null");
|
||||
}
|
||||
try {
|
||||
while (length > 0 && name.b[start] == '[') {
|
||||
while (length > 0 && isTypeCodeChar(name, start)) {
|
||||
start++;
|
||||
length--;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue