diff options
author | paltherr <paltherr@epfl.ch> | 2004-03-13 22:19:42 +0000 |
---|---|---|
committer | paltherr <paltherr@epfl.ch> | 2004-03-13 22:19:42 +0000 |
commit | 7155dffc81e96cb3f77e086d77593a511c6d80e3 (patch) | |
tree | d685c929a637dce3b82279b5abd1758a31c8f426 /sources/scalac/symtab/classfile/ConstantPool.java | |
parent | f108d5429fbf1515c0820a327becd5fbd06180f9 (diff) | |
download | scala-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.java | 336 |
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); + } + + //######################################################################## } |