summaryrefslogtreecommitdiff
path: root/sources/scalac/symtab/classfile/ConstantPool.java
diff options
context:
space:
mode:
authorpaltherr <paltherr@epfl.ch>2004-03-13 22:19:42 +0000
committerpaltherr <paltherr@epfl.ch>2004-03-13 22:19:42 +0000
commit7155dffc81e96cb3f77e086d77593a511c6d80e3 (patch)
treed685c929a637dce3b82279b5abd1758a31c8f426 /sources/scalac/symtab/classfile/ConstantPool.java
parentf108d5429fbf1515c0820a327becd5fbd06180f9 (diff)
downloadscala-7155dffc81e96cb3f77e086d77593a511c6d80e3.tar.gz
scala-7155dffc81e96cb3f77e086d77593a511c6d80e3.tar.bz2
scala-7155dffc81e96cb3f77e086d77593a511c6d80e3.zip
- Rewrote Signatures and ConstantPool to avoid ...
- Rewrote Signatures and ConstantPool to avoid creation of unnecessary names
Diffstat (limited to 'sources/scalac/symtab/classfile/ConstantPool.java')
-rw-r--r--sources/scalac/symtab/classfile/ConstantPool.java336
1 files changed, 184 insertions, 152 deletions
diff --git a/sources/scalac/symtab/classfile/ConstantPool.java b/sources/scalac/symtab/classfile/ConstantPool.java
index 8d80446342..09108d950a 100644
--- a/sources/scalac/symtab/classfile/ConstantPool.java
+++ b/sources/scalac/symtab/classfile/ConstantPool.java
@@ -2,184 +2,216 @@
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
-** **
-** $Id$
\* */
+// $Id$
+
package scalac.symtab.classfile;
-import scalac.*;
-import scalac.symtab.*;
-import scalac.util.*;
+import scalac.atree.AConstant;
+import scalac.symtab.Symbol;
+import scalac.symtab.Type;
+import scalac.util.AbstractFileReader;
+import scalac.util.Debug;
+import scalac.util.Name;
+import scalac.util.SourceRepresentation;
+/** This class implements the parsing of class file constant pools. */
public class ConstantPool implements ClassfileConstants {
- AbstractFileReader in;
- Signatures sigparser;
+ //########################################################################
+ // Private Fields
- /** the objects of the constant pool
- */
- protected Object[] poolObj;
+ /** The input file */
+ private final AbstractFileReader in;
- /** for every constant pool entry, an index into in.buf where the
- * defining section of the entry is found
- */
- protected int[] poolIdx;
+ /** The signature parser */
+ private final Signatures parser;
- /** constructor
- */
- protected ConstantPool(AbstractFileReader in, Signatures sigparser) {
- this.in = in;
- this.sigparser = sigparser;
- }
-
- /** index all constant pool entries, writing their start
- * addresses into poolIdx
- */
- public void indexPool() {
- poolIdx = new int[in.nextChar()];
- poolObj = new Object[poolIdx.length];
- int i = 1;
- while (i < poolIdx.length) {
- poolIdx[i++] = in.bp;
- byte tag = in.nextByte();
- switch (tag) {
- case CONSTANT_UTF8:
- case CONSTANT_UNICODE: {
- int len = in.nextChar();
- in.skip(len);
- break;
- }
- case CONSTANT_CLASS:
- case CONSTANT_STRING:
- in.skip(2);
- break;
- case CONSTANT_FIELDREF:
- case CONSTANT_METHODREF:
- case CONSTANT_INTFMETHODREF:
- case CONSTANT_NAMEANDTYPE:
- case CONSTANT_INTEGER:
- case CONSTANT_FLOAT:
- in.skip(4);
- break;
- case CONSTANT_LONG:
- case CONSTANT_DOUBLE:
- in.skip(8);
- i++;
- break;
- default:
- throw new RuntimeException("bad constant pool tag: " + tag +
- " at " + (in.bp - 1));
- }
- }
- }
+ /** The start addresses of all constants */
+ private final int[] starts;
+
+ /** The values of the constants (or null if not yet read) */
+ private final Object[] values;
- /** if name is an array type or class signature, return the
- * corresponding type; otherwise return a class definition with given name
- */
- protected Object classOrType(Name name) {
- if ((name.charAt(0) == '[') || (name.charAt(name.length() - 1) == ';')) {
- byte[] ascii = SourceRepresentation.string2ascii(name.toString());
- return sigparser.sigToType(ascii, 0, ascii.length);
- } else
- return name;
- }
-
- /** read constant pool entry at start address i, use poolObj as a cache.
- */
- public Object readPool(int i) {
- if (poolObj[i] != null)
- return poolObj[i];
- int index = poolIdx[i];
- if (index == 0)
- return null;
- switch (in.byteAt(index)) {
+ //########################################################################
+ // Public Constructors
+
+ /** Initializes this instance by reading constant pool in file. */
+ public ConstantPool(AbstractFileReader in, Signatures parser) {
+ this.in = in;
+ this.parser = parser;
+ this.starts = new int[in.nextChar()];
+ this.values = new Object[starts.length];
+ for (int index = 1; index < starts.length; ) {
+ starts[index++] = in.bp;
+ switch (in.nextByte()) {
case CONSTANT_UTF8:
- poolObj[i] = Name.fromAscii(in.buf, index + 3, in.getChar(index + 1));
- break;
case CONSTANT_UNICODE:
- throw new RuntimeException("can't read unicode strings in classfiles");
+ in.skip(in.nextChar());
+ continue;
case CONSTANT_CLASS:
- poolObj[i] = classOrType(readExternal(in.getChar(index + 1)));
- break;
- case CONSTANT_FIELDREF: {
- //Symbol owner = (Symbol)readPool(in.getChar(index + 1));
- //NameAndType nt = (NameAndType)readPool(in.getChar(index + 3));
- //poolObj[i] = new TermSymbol(Kinds.VAR, Position.NOPOS, nt.name, owner, 0)
- // .type(sigparser.sigToType(Name.names, nt.sig.index, nt.sig.length()));
- throw new RuntimeException("can't read constant_fieldrefs in classfiles");
- }
+ case CONSTANT_STRING:
+ in.skip(2);
+ continue;
+ case CONSTANT_FIELDREF:
case CONSTANT_METHODREF:
- case CONSTANT_INTFMETHODREF: {
- //Symbol owner = (Symbol)readPool(in.getChar(index + 1));
- //NameAndType nt = (NameAndType)readPool(in.getChar(index + 3));
- //poolObj[i] = new TermSymbol(Kinds.FUN, Position.NOPOS, nt.name, owner, 0)
- // .type(sigparser.sigToType(Name.names, nt.sig.index, nt.sig.length()));
- throw new RuntimeException("can't read constant_methodrefs in classfiles");
- }
+ case CONSTANT_INTFMETHODREF:
case CONSTANT_NAMEANDTYPE:
- poolObj[i] = new NameAndType((Name)readPool(in.getChar(index + 1)),
- readExternal(in.getChar(index + 3)));
- break;
- case CONSTANT_STRING:
- poolObj[i] = ((Name)readPool(in.getChar(index + 1))).toString();
- break;
case CONSTANT_INTEGER:
- poolObj[i] = new Integer(in.getInt(index + 1));
- break;
case CONSTANT_FLOAT:
- poolObj[i] = new Float(in.getFloat(index + 1));
- break;
+ in.skip(4);
+ continue;
case CONSTANT_LONG:
- poolObj[i] = new Long(in.getLong(index + 1));
- break;
case CONSTANT_DOUBLE:
- poolObj[i] = new Double(in.getDouble(index + 1));
- break;
+ in.skip(8);
+ index++;
+ continue;
default:
- throw new RuntimeException("bad constant pool tag: " + in.byteAt(index));
- }
- return poolObj[i];
- }
-
- /** return internal representation of buf[offset..offset+len-1],
- * converting '/' to '.'
- */
- public byte[] internalize(byte[] buf, int offset, int len) {
- byte[] translated = new byte[len];
- for (int j = 0; j < len; j++) {
- byte b = buf[offset + j];
- if (b == '/')
- translated[j] = '.';
- else
- translated[j] = b;
- }
- return translated;
- }
-
- /** read a constant pool string and convert to internal representation.
- */
- public Name readExternal(int i) {
- if (poolObj[i] == null) {
- int index = poolIdx[i];
- if (in.byteAt(index) == CONSTANT_UTF8) {
- int len = in.getChar(index + 1);
- byte[] translated = internalize(in.buf, index + 3, len);
- poolObj[i] = Name.fromAscii(translated, 0, len);
+ throw errorBadTag(in.bp - 1);
}
}
- return (Name)poolObj[i];
}
- /** the name and type signature of a method or field
- */
- public static final class NameAndType {
- public Name name;
- public Name sig;
+ //########################################################################
+ // Public Methods
+
+ /** Returns the string at given index. */
+ public String getString(int index) {
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ if (values[index] instanceof String) return (String)values[index];
+ if (values[index] instanceof Name) return values[index].toString();
+ String value = readString(starts[index]);
+ values[index] = value;
+ return value;
+ }
+
+ /** Returns the name at given index. */
+ public Name getName(int index) {
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ if (values[index] instanceof Name) return (Name)values[index];
+ Name value = readName(starts[index]);
+ values[index] = value;
+ return value;
+ }
- public NameAndType(Name name, Name sig) {
- this.name = name;
- this.sig = sig;
+ /** Returns the class at given index. */
+ public Symbol getClass(int index) {
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ if (values[index] instanceof Symbol) return (Symbol)values[index];
+ Symbol value = readClass(starts[index]);
+ values[index] = value;
+ return value;
+ }
+
+ /** Returns the field type at given index. */
+ public Type getFieldType(int index) {
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ if (values[index] instanceof Type) return (Type)values[index];
+ Type value = readFieldType(starts[index]);
+ values[index] = value;
+ return value;
+ }
+
+ /** Returns the method type at given index. */
+ public Type getMethodType(int index) {
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ if (values[index] instanceof Type) return clone((Type)values[index]);
+ Type value = readMethodType(starts[index]);
+ values[index] = value;
+ return value;
+ }
+
+ /** Returns the constant value at given index. */
+ public AConstant getConstantValue(int index) {
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ if (values[index] != null) return (AConstant)values[index];
+ AConstant value = readConstantValue(starts[index]);
+ values[index] = value;
+ return value;
+ }
+
+ //########################################################################
+ // Private Fields
+
+ /** Reads the string at given address. */
+ private String readString(int address) {
+ if (in.byteAt(address) != CONSTANT_UTF8) throw errorBadTag(address);
+ return parser.at(address).getSignature();
+ }
+
+ /** Reads the name at given address. */
+ private Name readName(int address) {
+ return Name.fromString(readString(address));
+ }
+
+ /** Reads the class at given address. */
+ private Symbol readClass(int address) {
+ if (in.byteAt(address) != CONSTANT_CLASS) throw errorBadTag(address);
+ int index = in.getChar(address + 1);
+ if (index <= 0 || starts.length <= index) throw errorBadIndex(index);
+ address = starts[index];
+ if (in.byteAt(address) != CONSTANT_UTF8) throw errorBadTag(address);
+ return parser.at(address).readClassName();
+ }
+
+ /** Reads the field type at given address. */
+ private Type readFieldType(int address) {
+ if (in.byteAt(address) != CONSTANT_UTF8) throw errorBadTag(address);
+ return parser.at(address).readValueType();
+ }
+
+ /** Reads the method type at given address. */
+ private Type readMethodType(int address) {
+ if (in.byteAt(address) != CONSTANT_UTF8) throw errorBadTag(address);
+ return parser.at(address).readMethodType();
+ }
+
+ /** Reads the constant value at given address. */
+ private AConstant readConstantValue(int address) {
+ switch (in.byteAt(address)) {
+ case CONSTANT_STRING:
+ return AConstant.STRING(getString(in.getChar(address + 1)));
+ case CONSTANT_INTEGER:
+ return AConstant.INT(in.getInt(address + 1));
+ case CONSTANT_FLOAT:
+ return AConstant.FLOAT(in.getFloat(address + 1));
+ case CONSTANT_LONG:
+ return AConstant.LONG(in.getLong(address + 1));
+ case CONSTANT_DOUBLE:
+ return AConstant.DOUBLE(in.getDouble(address + 1));
+ default:
+ throw errorBadTag(address);
+ }
+ }
+
+ /** Returns the type with all its parameters symbols cloned. */
+ private Type clone(Type type) {
+ switch (type) {
+ case MethodType(Symbol[] params, Type result):
+ Symbol[] clones = new Symbol[params.length];
+ for (int i = 0; i < clones.length; i++)
+ clones[i] = params[i].cloneSymbol(Symbol.NONE);
+ return Type.MethodType(clones, result);
+ case ErrorType:
+ return type;
+ default:
+ throw Debug.abort("illegal case", type);
}
}
+
+ /** Throws an exception signaling a bad constant index. */
+ private RuntimeException errorBadIndex(int index) {
+ String error = "bad constant pool index: " + index;
+ throw new RuntimeException(error);
+ }
+
+ /** Throws an exception signaling a bad tag at given address. */
+ private RuntimeException errorBadTag(int address) {
+ int tag = in.byteAt(address);
+ String error = "bad constant pool tag " + tag + " at byte " + address;
+ throw new RuntimeException(error);
+ }
+
+ //########################################################################
}