Commit eb631dda authored by ebruneton's avatar ebruneton
Browse files

improved Javadoc, changed order of parameters in Attribute.read

parent 990aff2e
Manifest-Version: 1.0
Implementation-Title: "ASM Attribute classes"
Implementation-Version: "1.4.1"
Implementation-Vendor: "France Telecom R&D"
<project name="asm" default="dist">
<target name="dist">
<jar jarfile="${out.dist.lib}/asm-attrs.jar"
basedir="${out.build}"
manifest="${archive}/asm-attrs.mf">
<include name="org/objectweb/asm/attrs/*.class"/>
</jar>
</target>
</project>
......@@ -176,14 +176,14 @@
<!-- copy all files and all non empty directories available in the doc -->
<!-- directory into dist/doc -->
<copy todir="${out.dist.doc}"
<!--copy todir="${out.dist.doc}"
preservelastmodified="yes"
includeEmptyDirs="false">
<fileset dir="${doc}">
<include name="**/*"/>
<exclude name="**/*.fig"/>
</fileset>
</copy>
</copy-->
<!-- create all jars -->
......
......@@ -144,12 +144,19 @@ class CommentAttribute extends Attribute {
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
return new CommentAttribute(cr.readUTF8(off, buf));
}
protected ByteVector write (ClassWriter cw, byte[] code, int len) {
protected ByteVector write (
ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
return new ByteVector().putShort(cw.newUTF8(comment));
}
}
......@@ -63,35 +63,15 @@ public abstract class Attribute {
}
/**
* Analyzes a {@link #type type} attribute and finds the corresponding labels.
* This method must analyze the attribute in the given class reader, at the
* given offset (whose type is equal to {@link #type type}), and must add to
* given label array the labels that corresponds to the bytecode offsets
* contained in the attribute (if there are such offsets, and if the
* corresponding labels do not already exist). The default implementation of
* this method, which is only called for code attributes, does nothing.
* Returns the labels corresponding to this attribute.
*
* @param cr the class that contains the attribute to be analyzed.
* @param off index of the first byte of the attribute's content in {@link
* ClassReader#b cr.b}. The 6 attribute header bytes, containing the type
* and the length of the attribute, are not taken into account here.
* @param len the length of the attribute's content.
* @param labels the array that must be completed with the labels contained in
* the attribute.
* @return the labels corresponding to this attribute, or <tt>null</tt> if
* this attribute is not a code attribute that contains labels.
*/
/*
protected void analyze (
ClassReader cr,
int off,
int len,
char[] buf,
Label[] labels,
int maxStack,
int maxLocals)
{
// does nothing
protected Label[] getLabels () {
return null;
}
*/
/**
* Reads a {@link #type type} attribute. This method must return a <i>new</i>
......@@ -105,15 +85,19 @@ public abstract class Attribute {
* @param len the length of the attribute's content.
* @param buf buffer to be used to call {@link ClassReader#readUTF8 readUTF8},
* {@link ClassReader#readClass readClass} or {@link
* ClassReader#readConst readConst}..
* ClassReader#readConst readConst}.
* @param codeOff index of the first byte of code's attribute content in
* {@link ClassReader#b cr.b}, or -1 if the attribute to be read is not a
* code attribute. The 6 attribute header bytes, containing the type and
* the length of the attribute, are not taken into account here.
* @param labels the labels of the method's code, or <tt>null</tt> if the
* attribute to be read is not a code attribute.
* @return a <i>new</i> {@link Attribute} object corresponding to the given
* bytes.
*/
protected abstract Attribute read ( ClassReader cr, int off, int len,
int codeOff, char[] buf, Label[] labels);
protected abstract Attribute read (
ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels);
/**
* Returns the byte array form of this attribute.
......@@ -127,11 +111,16 @@ public abstract class Attribute {
* @param len the length of the bytecode of the method corresponding to this
* code attribute, or <tt>null</tt> if this attribute is not a code
* attribute.
* @param maxStack the maximum stack size of the method corresponding to this
* code attribute, or -1 if this attribute is not a code attribute.
* @param maxLocals the maximum number of local variables of the method
* corresponding to this code attribute, or -1 if this attribute is not
* a code attribute.
* @return the byte array form of this attribute.
*/
protected abstract ByteVector write (ClassWriter cw, byte[] code, int len,
int maxStack, int maxLocals);
protected abstract ByteVector write (
ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals);
/**
* Returns the length of the attribute list that begins with this attribute.
......@@ -160,12 +149,22 @@ public abstract class Attribute {
* @param len the length of the bytecode of the method corresponding to these
* code attributes, or <tt>null</tt> if these attributes are not code
* attributes.
* @param maxStack the maximum stack size of the method corresponding to these
* code attributes, or -1 if these attributes are not code attributes.
* @param maxLocals the maximum number of local variables of the method
* corresponding to these code attributes, or -1 if these attributes are
* not code attributes.
* @return the size of all the attributes in this attribute list. This size
* includes the size of the attribute headers.
*/
final int getSize (final ClassWriter cw, final byte[] code,
final int len, final int maxStack, final int maxLocals) {
final int getSize (
final ClassWriter cw,
final byte[] code,
final int len,
final int maxStack,
final int maxLocals)
{
int size = 0;
Attribute attr = this;
while (attr != null) {
......@@ -187,11 +186,22 @@ public abstract class Attribute {
* @param len the length of the bytecode of the method corresponding to these
* code attributes, or <tt>null</tt> if these attributes are not code
* attributes.
* @param maxStack the maximum stack size of the method corresponding to these
* code attributes, or -1 if these attributes are not code attributes.
* @param maxLocals the maximum number of local variables of the method
* corresponding to these code attributes, or -1 if these attributes are
* not code attributes.
* @param out where the attributes must be written.
*/
final void put ( final ClassWriter cw, final byte[] code, final int len,
final int maxStack, final int maxLocals, final ByteVector out) {
final void put (
final ClassWriter cw,
final byte[] code,
final int len,
final int maxStack,
final int maxLocals,
final ByteVector out)
{
Attribute attr = this;
while (attr != null) {
ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
......
......@@ -48,7 +48,8 @@ public class ClassReader {
/**
* The class to be parsed. <i>The content of this array must not be
* modified.</i>
* modified. This field is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*/
public final byte[] b;
......@@ -299,7 +300,8 @@ public class ClassReader {
} else if (attrName.equals("InnerClasses")) {
w = v + 6;
} else {
attr = readAttribute(attrs, attrName, v + 6, readInt(v + 2), -1, c, null);
attr = readAttribute(
attrs, attrName, v + 6, readInt(v + 2), c, -1, null);
if (attr != null) {
attr.next = clattrs;
clattrs = attr;
......@@ -344,7 +346,8 @@ public class ClassReader {
} else if (attrName.equals("Deprecated")) {
access |= Constants.ACC_DEPRECATED;
} else {
attr = readAttribute(attrs, attrName, u + 6, readInt(u + 2), -1, c, null);
attr = readAttribute(
attrs, attrName, u + 6, readInt(u + 2), c, -1, null);
if (attr != null) {
attr.next = fattrs;
fattrs = attr;
......@@ -365,6 +368,7 @@ public class ClassReader {
String methName = readUTF8(u + 2, c);
String methDesc = readUTF8(u + 4, c);
Attribute mattrs = null;
Attribute cattrs = null;
v = 0;
w = 0;
// looks for Code and Exceptions attributes
......@@ -382,7 +386,7 @@ public class ClassReader {
} else if (attrName.equals("Deprecated")) {
access |= Constants.ACC_DEPRECATED;
} else {
attr = readAttribute(attrs, attrName, u, attrSize, -1, c, null);
attr = readAttribute(attrs, attrName, u, attrSize, c, -1, null);
if (attr != null) {
attr.next = mattrs;
mattrs = attr;
......@@ -555,8 +559,12 @@ public class ClassReader {
} else {
for (k = 0; k < attrs.length; ++k) {
if (attrs[k].type.equals(attrName)) {
// analyze labels if it is required
attrs[k].read(this, v + 6, readInt(v + 2), codeStart-8, c, labels);
attr = attrs[k].read(
this, v + 6, readInt(v + 2), c, codeStart - 8, labels);
if (attr != null) {
attr.next = cattrs;
cattrs = attr;
}
}
}
}
......@@ -705,12 +713,12 @@ public class ClassReader {
}
v += 8;
}
// visits the local variable, line number tables, and code attributes
// visits the local variable and line number tables
j = readUnsignedShort(v); v += 2;
for ( ; j > 0; --j) {
String attrName = readUTF8(v, c);
if (attrName.equals("LocalVariableTable")) {
if (!skipDebug) {
if (!skipDebug) {
for ( ; j > 0; --j) {
String attrName = readUTF8(v, c);
if (attrName.equals("LocalVariableTable")) {
k = readUnsignedShort(v + 6);
w = v + 8;
for ( ; k > 0; --k) {
......@@ -726,9 +734,7 @@ public class ClassReader {
readUnsignedShort(w + 8));
w += 10;
}
}
} else if (attrName.equals("LineNumberTable")) {
if (!skipDebug) {
} else if (attrName.equals("LineNumberTable")) {
k = readUnsignedShort(v + 6);
w = v + 8;
for ( ; k > 0; --k) {
......@@ -738,13 +744,15 @@ public class ClassReader {
w += 4;
}
}
} else {
attr = readAttribute( attrs, attrName, v + 6, readInt(v + 2), codeStart-8, c, labels);
if (attr != null) {
cv.visitAttribute(attr);
}
v += 6 + readInt(v + 2);
}
v += 6 + readInt(v + 2);
}
// visits the other attributes
while (cattrs != null) {
attr = cattrs.next;
cattrs.next = null;
cv.visitAttribute(cattrs);
cattrs = attr;
}
// visits the max stack and max locals values
cv.visitMaxs(maxStack, maxLocals);
......@@ -764,7 +772,9 @@ public class ClassReader {
// --------------------------------------------------------------------------
/**
* Reads an unsigned short value in {@link #b b}.
* Reads an unsigned short value in {@link #b b}. <i>This method is intended
* for {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index the start index of the value to be read in {@link #b b}.
* @return the read value.
......@@ -776,7 +786,9 @@ public class ClassReader {
}
/**
* Reads a signed short value in {@link #b b}.
* Reads a signed short value in {@link #b b}. <i>This method is intended
* for {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index the start index of the value to be read in {@link #b b}.
* @return the read value.
......@@ -788,7 +800,9 @@ public class ClassReader {
}
/**
* Reads a signed int value in {@link #b b}.
* Reads a signed int value in {@link #b b}. <i>This method is intended
* for {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index the start index of the value to be read in {@link #b b}.
* @return the read value.
......@@ -803,7 +817,9 @@ public class ClassReader {
}
/**
* Reads a signed long value in {@link #b b}.
* Reads a signed long value in {@link #b b}. <i>This method is intended
* for {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @param index the start index of the value to be read in {@link #b b}.
* @return the read value.
......@@ -816,7 +832,9 @@ public class ClassReader {
}
/**
* Reads an UTF8 string constant pool item in {@link #b b}.
* Reads an UTF8 string constant pool item in {@link #b b}. <i>This method is
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.</i>
*
* @param index the start index of an unsigned short value in {@link #b b},
* whose value is the index of an UTF8 constant pool item.
......@@ -877,7 +895,9 @@ public class ClassReader {
}
/**
* Reads a class constant pool item in {@link #b b}.
* Reads a class constant pool item in {@link #b b}. <i>This method is
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.</i>
*
* @param index the start index of an unsigned short value in {@link #b b},
* whose value is the index of a class constant pool item.
......@@ -894,7 +914,9 @@ public class ClassReader {
}
/**
* Reads a numeric or string constant pool item in {@link #b b}.
* Reads a numeric or string constant pool item in {@link #b b}. <i>This
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
*
* @param item the index of a constant pool item.
* @param buf buffer to be used to read the item. This buffer must be
......@@ -937,17 +959,28 @@ public class ClassReader {
* @param len the length of the attribute's content.
* @param buf buffer to be used to call {@link #readUTF8 readUTF8}, {@link
* #readClass readClass} or {@link #readConst readConst}.
* @param codeOff index of the first byte of code's attribute content in
* {@link #b b}, or -1 if the attribute to be read is not a code
* attribute. The 6 attribute header bytes, containing the type and the
* length of the attribute, are not taken into account here.
* @param labels the labels of the method's code, or <tt>null</tt> if the
* attribute to be read is not a code attribute.
* @return the attribute that has been read, or <tt>null</tt> to skip this
* attribute.
*/
public Attribute readAttribute ( final Attribute[] attrs, final String type, final int off,
final int len, final int codeOff, final char[] buf, final Label[] labels) {
protected Attribute readAttribute (
final Attribute[] attrs,
final String type,
final int off,
final int len,
final char[] buf,
final int codeOff,
final Label[] labels)
{
for (int i = 0; i < attrs.length; ++i) {
if (attrs[i].type.equals(type)) {
return attrs[i].read(this, off, len, codeOff, buf, labels);
return attrs[i].read(this, off, len, buf, codeOff, labels);
}
}
return null;
......
......@@ -695,6 +695,8 @@ public class ClassWriter implements ClassVisitor {
/**
* Adds a number or string constant to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param cst the value of the constant to be added to the constant pool. This
* parameter must be an {@link java.lang.Integer Integer}, a {@link
......@@ -710,7 +712,9 @@ public class ClassWriter implements ClassVisitor {
/**
* Adds an UTF8 string to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item.
* nothing if the constant pool already contains a similar item. <i>This
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
*
* @param value the String value.
* @return the index of a new or already existing UTF8 item.
......@@ -729,7 +733,9 @@ public class ClassWriter implements ClassVisitor {
/**
* Adds a class reference to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item.
* nothing if the constant pool already contains a similar item. <i>This
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
*
* @param value the internal name of the class.
* @return the index of a new or already existing class reference item.
......@@ -748,7 +754,9 @@ public class ClassWriter implements ClassVisitor {
/**
* Adds a field reference to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item.
* nothing if the constant pool already contains a similar item. <i>This
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
*
* @param owner the internal name of the field's owner class.
* @param name the field's name.
......@@ -800,7 +808,9 @@ public class ClassWriter implements ClassVisitor {
/**
* Adds a method reference to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item.
* nothing if the constant pool already contains a similar item. <i>This
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
*
* @param owner the internal name of the method's owner class.
* @param name the method's name.
......
......@@ -1185,7 +1185,7 @@ public class CodeWriter implements CodeVisitor {
size += 8 + lineNumber.length;
}
if (cattrs != null) {
size += cattrs.getSize(cw, code.data, code.length, -1, -1);
size += cattrs.getSize(cw, code.data, code.length, maxStack, maxLocals);
}
}
if (exceptionCount > 0) {
......@@ -1241,7 +1241,7 @@ public class CodeWriter implements CodeVisitor {
size += 8 + lineNumber.length;
}
if (cattrs != null) {
size += cattrs.getSize(cw, code.data, code.length, -1, -1);
size += cattrs.getSize(cw, code.data, code.length, maxStack, maxLocals);
}
out.putShort(cw.newUTF8("Code")).putInt(size);
out.putShort(maxStack).putShort(maxLocals);
......@@ -1684,6 +1684,19 @@ public class CodeWriter implements CodeVisitor {
u += 4;
}
}
// updates the labels of the other attributes
while (cattrs != null) {
Label[] labels = cattrs.getLabels();
if (labels != null) {
for (i = labels.length - 1; i >= 0; --i) {
if (!labels[i].resized) {
labels[i].position =
getNewOffset(allIndexes, allSizes, 0, labels[i].position);
labels[i].resized = true;
}
}
}
}
// replaces old bytecodes with new ones
code = newCode;
......
......@@ -59,6 +59,12 @@ public class Label {
int position;
/**
* If the label position has been updated, after instruction resizing.
*/
boolean resized;
/**
* Number of forward references to this label, times two.
*/
......@@ -137,16 +143,28 @@ public class Label {
public Label () {
}
public int getOffset() {
if( !resolved)
throw new IllegalStateException( "Label offset position has not been resolved yet");
return position;
}
// --------------------------------------------------------------------------
// Methods to compute offsets and to manage forward references
// --------------------------------------------------------------------------
/**
* Returns the offset corresponding to this label. This offset is computed
* from the start of the method's bytecode. <i>This method is intended for
* {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
*
* @return the offset corresponding to this label.
* @throws IllegalStateException if this label is not resolved yet.
*/
public int getOffset () {
if (!resolved) {
throw new IllegalStateException(
"Label offset position has not been resolved yet");
}
return position;
}
/**
* Puts a reference to this label in the bytecode of a method. If the position
* of the label is known, the offset is computed and written directly.
......
......@@ -41,25 +41,25 @@ import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
/**
* The Signature Attribute introduced in JSR-14 (Adding Generics to the
* Java Programming Language) and also defined in the Java Virtual Machine
* Specification, 3rd edition draft.
* The Signature Attribute introduced in JSR-14 (Adding Generics to the
* Java Programming Language) and also defined in the Java Virtual Machine
* Specification, 3rd edition draft.
* <p>
* Classfiles need to carry generic type information in a backwards
* compatible way. This is accomplished by introducing a new "Signature"
* Classfiles need to carry generic type information in a backwards
* compatible way. This is accomplished by introducing a new "Signature"
* attribute for classes, methods and fields. The structure of this
* attribute is as follows:
* <pre>
* "Signature" (u4 attr-length, u2 signature-index)
* </pre>
* When used as an attribute of a method or field, a signature gives the
* full (possibly generic) type of that method or field.
* When used as a class attribute, a signature indicates the type
* parameters of the class, followed by its supertype, followed by
* When used as an attribute of a method or field, a signature gives the
* full (possibly generic) type of that method or field.
* When used as a class attribute, a signature indicates the type
* parameters of the class, followed by its supertype, followed by
* all its interfaces.
* <p>
* The type syntax in signatures is extended to parameterized types and
* type variables. There is also a new signature syntax for formal type
* The type syntax in signatures is extended to parameterized types and
* type variables. There is also a new signature syntax for formal type
* parameters. The syntax extensions for signature strings are as follows:
* <pre>
* MethodOrFieldSignature ::= TypeSignature
......@@ -82,11 +82,11 @@ import org.objectweb.asm.Label;
* ParameterPart ::= '<' ParameterSignature ParameterSignatures '>'
* ParameterSignatures ::= ParameterSignatures ParameterSignature
* |
* ParameterSignature ::= Ident ':' bound_TypeSignature
* ParameterSignature ::= Ident ':' bound_TypeSignature
* </pre>
*
*
* @see <a href="http://www.jcp.org/en/jsr/detail?id=14">JSR 14 : Add Generic Types To The JavaTM Programming Language</a>
*
*
* @author Eugene Kuleshov
*/
public class SignatureAttribute extends Attribute {
......@@ -95,21 +95,21 @@ public class SignatureAttribute extends Attribute {
public SignatureAttribute() {
super( "Signature");
}
public SignatureAttribute( String signature) {
this();
this.signature = signature;
}
public String getSignature() {
return signature;
}
protected Attribute read(ClassReader cr, int off, int len, int codeOff, char[] buf, Label[] labels) {
protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
return new SignatureAttribute( cr.readUTF8( off, buf));
}
protected ByteVector write( ClassWriter cw, byte[] code,
protected ByteVector write(