summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2003-07-17 14:29:40 +0000
committerMartin Odersky <odersky@gmail.com>2003-07-17 14:29:40 +0000
commit086e26c6bb594514e533ae2f3410f7ccfa399b99 (patch)
tree1936db734d7753a3e64258e269762868ca447bcc /sources
parentd4945a881b5b25ededfc990ac9a50dc288690f49 (diff)
downloadscala-086e26c6bb594514e533ae2f3410f7ccfa399b99.tar.gz
scala-086e26c6bb594514e533ae2f3410f7ccfa399b99.tar.bz2
scala-086e26c6bb594514e533ae2f3410f7ccfa399b99.zip
*** empty log message ***
Diffstat (limited to 'sources')
-rw-r--r--sources/scalac/symtab/EntryTags.java12
-rw-r--r--sources/scalac/symtab/classfile/Pickle.java426
-rw-r--r--sources/scalac/symtab/classfile/UnPickle.java35
3 files changed, 470 insertions, 3 deletions
diff --git a/sources/scalac/symtab/EntryTags.java b/sources/scalac/symtab/EntryTags.java
index a2e1b32068..1b695a213f 100644
--- a/sources/scalac/symtab/EntryTags.java
+++ b/sources/scalac/symtab/EntryTags.java
@@ -30,8 +30,16 @@ public interface EntryTags {
OVERLOADEDtpe = 18,
UNBOXEDtpe = 19,
UNBOXEDARRAYtpe = 20,
- ERRORtpe = 21;
+ FLAGGEDtpe = 21,
+ ERRORtpe = 22;
int firstSymTag = NONEsym, lastSymTag = VALsym;
- int firstTypeTag = NOtpe, lastTypeTag = UNBOXEDARRAYtpe;
+ int firstTypeTag = NOtpe, lastTypeTag = FLAGGEDtpe;
+
+// flag encodings
+
+ int COVARflag = 1,
+ CONTRAVARflag = 2,
+ REPEATEDflag = 4,
+ DEFflag = 8;
}
diff --git a/sources/scalac/symtab/classfile/Pickle.java b/sources/scalac/symtab/classfile/Pickle.java
new file mode 100644
index 0000000000..bbd0ff7526
--- /dev/null
+++ b/sources/scalac/symtab/classfile/Pickle.java
@@ -0,0 +1,426 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scalac.symtab.classfile;
+
+import java.util.HashMap;
+import scalac.Global;
+import scalac.ApplicationError;
+import scalac.util.*;
+import scalac.symtab.*;
+import Symbol.*;
+import Type.*;
+
+public class Pickle implements Kinds, Modifiers, EntryTags {
+
+ final static boolean debug = false;
+
+/***************************************************
+ * Symbol table attribute format: see UnPickle.java
+ */
+ public byte[] bytes;
+ private int bp;
+
+ private Symbol root;
+ private HashMap index;
+ private Object[] entries;
+ private int ep;
+ private Symbol root1;
+ private Symbol root2;
+
+ /** Write symbol table info for root.
+ * root must be either a module or a class.
+ */
+ Pickle(Symbol root) {
+ this.root = root;
+ this.root1 = root.moduleClass();
+ this.root2 = root1.constructor();
+ index = new HashMap();
+ entries = new Object[256];
+ ep = 0;
+ putSymbol(root);
+ bytes = new byte[4096];
+ bp = 0;
+ writeAttr();
+ }
+
+/* **************************************************
+ * Phase 1: Build entry table
+ ************************************************* */
+
+ /** Is root in symbol.owner*?
+ */
+ private boolean isLocal(Symbol sym) {
+ return
+ sym == root || sym == root1 || sym == root2 ||
+ (sym.kind != NONE && isLocal(sym.owner()));
+ }
+
+ /** Store entry `e' in index at next available position unless it it
+ * already there. Return true iff entry is new.
+ */
+ private boolean putEntry(Object e) {
+ Integer n = (Integer) index.get(e);
+ if (n == null) {
+ //System.out.println("entry " + e);//DEBUG
+ if (ep == entries.length) {
+ Object[] entries1 = new Object[ep * 2];
+ System.arraycopy(entries, 0, entries1, 0, ep);
+ entries = entries1;
+ }
+ entries[ep] = e;
+ index.put(e, new Integer(ep));
+ ep++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /** Store symbol in index. If symbol is local, also store
+ * everything it refers to. Excepted are local primary
+ * constructors; their information is stored together with
+ * another symbol.
+ */
+ private void putSymbol(Symbol sym) {
+ if (putEntry(sym)) {
+ if (isLocal(sym)) {
+ putEntry(sym.name);
+ putSymbol(sym.owner());
+ putType(sym.info());
+ switch (sym.kind) {
+ case TYPE:
+ putType(sym.loBound());
+ break;
+ case ALIAS:
+ break;
+ case CLASS:
+ putType(sym.typeOfThis());
+ putSymbol(sym.constructor());
+ for (Scope.SymbolIterator it = sym.members().iterator();
+ it.hasNext();)
+ putSymbol(it.next());
+ break;
+ case VAL:
+ if (sym.isPrimaryConstructor())
+ putSymbol(sym.primaryConstructorClass());
+ else if (sym.isModule())
+ putSymbol(sym.moduleClass());
+ break;
+ default:
+ throw new ApplicationError();
+ }
+ } else if (sym.kind != NONE) {
+ putEntry(sym.name);
+ if (sym.owner() != Global.instance.definitions.ROOT_CLASS)
+ putSymbol(sym.owner());
+ }
+ }
+ }
+
+ private void putSymbols(Symbol[] syms) {
+ for (int i = 0; i < syms.length; i++)
+ putSymbol(syms[i]);
+ }
+
+ /** Store type and everythig it refers to in index.
+ */
+ private void putType(Type tp) {
+ if (putEntry(tp)) {
+ switch (tp) {
+ case NoType:
+ break;
+ case ThisType(Symbol sym):
+ putSymbol(sym);
+ break;
+ case SingleType(Type pre, Symbol sym):
+ putType(pre);
+ putSymbol(sym);
+ break;
+ case TypeRef(Type pre, Symbol sym, Type[] args):
+ putType(pre);
+ putSymbol(sym);
+ putTypes(args);
+ break;
+ case CompoundType(Type[] parents, Scope members):
+ putTypes(parents);
+ putSymbols(members.elements());
+ break;
+ case MethodType(Symbol[] vparams, Type result):
+ putType(result);
+ for (int i = 0; i < vparams.length; i++) {
+ Type ptype= vparams[i].type();
+ putType(ptype);
+ int pflags = vparams[i].flags;
+ if ((pflags & (COVARIANT | CONTRAVARIANT | REPEATED | DEF)) != 0)
+ putEntry(new FlagsAndType(encodeFlags(pflags), ptype));
+ }
+ break;
+ case PolyType(Symbol[] tparams, Type result):
+ putType(result);
+ putSymbols(tparams);
+ break;
+ case OverloadedType(Symbol[] alts, Type[] alttypes):
+ putSymbols(alts);
+ putTypes(alttypes);
+ break;
+ default:
+ throw new ApplicationError();
+ }
+ }
+ }
+
+ private void putTypes(Type[] tps) {
+ for (int i = 0; i < tps.length; i++)
+ putType(tps[i]);
+ }
+
+/* **************************************************
+ * Phase 2: Write byte array
+ ************************************************* */
+
+ private void resizeTo(int size) {
+ byte[] bytes1 = new byte[size];
+ System.arraycopy(bytes, 0, bytes1, 0, bp);
+ bytes = bytes1;
+ }
+
+ /** Write a byte of data
+ */
+ private void writeByte(int b) {
+ if (bp == bytes.length) resizeTo(bytes.length * 2);
+ bytes[bp++] = (byte)b;
+ if (debug) System.out.print(b + " ");
+ }
+
+ /** Write a natural number in big endian format, base 128.
+ * All but the last digits have bit 0x80 set.
+ */
+ private void writeNat(int x) {
+ int y = x >>> 7;
+ if (y != 0) writeNatPrefix(y);
+ writeByte(x & 0x7f);
+ }
+
+ private void writeNatPrefix(int x) {
+ int y = x >>> 7;
+ if (y != 0) writeNatPrefix(y);
+ writeByte((x & 0x7f) | 0x80);
+ }
+
+ /** Write a natural number at `pos'
+ * If number is more than one byte, shift rest of array to make space.
+ */
+ private void patchNat(int pos, int x) {
+ bytes[pos] = (byte) (x & 0x7f);
+ int y = x >>> 7;
+ if (y != 0) patchNatPrefix(pos, y);
+ }
+
+ private void patchNatPrefix(int pos, int x) {
+ writeByte(0);
+ System.arraycopy(bytes, pos, bytes, pos+1, bp - (pos+1));
+ bytes[pos] = (byte) ((x & 0x7f) | 0x80);
+ int y = x >>> 7;
+ if (y != 0) patchNatPrefix(pos, y);
+ }
+
+ /** Write a reference to object, i.e., the object's number in the index.
+ */
+ private void writeRef(Object ref) {
+ Integer i = (Integer) index.get(ref);
+ assert i != null : ref + " " + ref.getClass();
+ writeNat(i.intValue());
+ }
+
+ private void writeRefs(Object[] es) {
+ for (int i = 0; i < es.length; i++) writeRef(es[i]);
+ }
+
+ /** Write a name entry. Names are stored in Utf8 format.
+ */
+ private void writeName(Name name) {
+ if (name.isTermName()) writeByte(TERMname);
+ else if (name.isConstrName()) writeByte(CONSTRname);
+ else writeByte(TYPEname);
+ writeByte(0); // space for length
+ while (bp + name.length() > bytes.length) resizeTo(bytes.length * 2);
+ name.copyAscii(bytes, bp);
+ if (debug) System.out.print(name);
+ bp = bp + name.length();
+ }
+
+ /** Write a symbol entry.
+ */
+ private void writeSymbol(Symbol sym) {
+ if (isLocal(sym)) {
+ writeByte(sym.kind);
+ writeByte(0); // space for length
+ writeRef(sym.name);
+ writeRef(sym.owner());
+ writeNat(sym.flags);
+ writeRef(sym.info());
+ switch (sym.kind) {
+ case TYPE:
+ writeRef(sym.loBound());
+ break;
+ case ALIAS:
+ break;
+ case CLASS:
+ writeRef(sym.typeOfThis());
+ writeRef(sym.constructor());
+ break;
+ case VAL:
+ if (sym.isPrimaryConstructor())
+ writeRef(sym.primaryConstructorClass());
+ else if (sym.isModule())
+ writeRef(sym.moduleClass());
+ break;
+ default:
+ throw new ApplicationError();
+ }
+ } else if (sym.kind == NONE) {
+ writeByte(NONE);
+ writeByte(0); // space for length
+ } else {
+ writeByte(EXTsym);
+ writeByte(0); // space for length
+ writeRef(sym.name);
+ if (sym.owner() != Global.instance.definitions.ROOT_CLASS)
+ writeRef(sym.owner());
+ }
+ }
+
+ /** Write a type entry.
+ */
+ private void writeType(Type tp) {
+ switch (tp) {
+ case NoType:
+ writeByte(NOtpe);
+ writeByte(0); // space for length
+ break;
+
+ case ThisType(Symbol sym):
+ writeByte(THIStpe);
+ writeByte(0); // space for length
+ writeRef(sym);
+ break;
+
+ case SingleType(Type pre, Symbol sym):
+ writeByte(SINGLEtpe);
+ writeByte(0); // space for length
+ writeRef(pre);
+ writeRef(sym);
+ break;
+
+ case TypeRef(Type pre, Symbol sym, Type[] args):
+ writeByte(TYPEREFtpe);
+ writeByte(0); // space for length
+ writeRef(pre);
+ writeRef(sym);
+ writeRefs(args);
+ break;
+
+ case CompoundType(Type[] parents, Scope members):
+ writeByte(COMPOUNDtpe);
+ writeByte(0); // space for length
+ writeRefs(parents);
+ writeRefs(members.elements());
+ break;
+
+ case MethodType(Symbol[] vparams, Type result):
+ writeByte(METHODtpe);
+ writeByte(0); // space for length
+ writeRef(result);
+ for (int i = 0; i < vparams.length; i++) {
+ Type ptype = vparams[i].type();
+ int pflags = vparams[i].flags;
+ if ((pflags & (COVARIANT | CONTRAVARIANT | REPEATED | DEF)) != 0)
+ writeRef(new FlagsAndType(encodeFlags(pflags), ptype));
+ else
+ writeRef(ptype);
+ }
+ break;
+
+ case PolyType(Symbol[] tparams, Type result):
+ writeByte(POLYtpe);
+ writeByte(0); // space for length
+ writeRef(result);
+ writeRefs(tparams);
+ break;
+
+ case OverloadedType(Symbol[] alts, Type[] alttypes):
+ writeByte(OVERLOADEDtpe);
+ writeByte(0); // space for length
+ writeRefs(alts);
+ writeRefs(alttypes);
+ break;
+
+ default:
+ throw new ApplicationError();
+ }
+ }
+
+ private void writeFlagsAndType(FlagsAndType ft) {
+ writeByte(FLAGGEDtpe);
+ writeByte(0); // space for length
+ writeNat(ft.flags);
+ writeRef(ft.type);
+ }
+
+ private void writeEntry(Object e) {
+ int startpos = bp;
+ if (e instanceof Symbol) writeSymbol((Symbol) e);
+ else if (e instanceof Type) writeType((Type) e);
+ else if (e instanceof Name) writeName((Name) e);
+ else if (e instanceof FlagsAndType) writeFlagsAndType((FlagsAndType) e);
+ else throw new ApplicationError();
+ patchNat(startpos + 1, bp - (startpos + 2));
+ }
+
+ private void writeAttr() {
+ writeNat(ep);
+ for (int i = 0; i < ep; i++) {
+ if (debug) System.out.print(i + "," + bp + ": ");
+ writeEntry(entries[i]);
+ if (debug) System.out.println();
+ }
+ resizeTo(bp);
+ }
+
+ private static int encodeFlags(int flags) {
+ int n = 0;
+ if ((flags & COVARIANT) != 0) n |= COVARflag;
+ if ((flags & CONTRAVARIANT) != 0) n |= CONTRAVARflag;
+ if ((flags & REPEATED) != 0) n |= REPEATEDflag;
+ if ((flags & DEF) != 0) n |= DEFflag;
+ return n;
+ }
+
+ static class FlagsAndType {
+ int flags;
+ Type type;
+ FlagsAndType(int flags, Type type) {
+ this.flags = flags;
+ this.type = type;
+ }
+ public boolean equals(Object other) {
+ if (other instanceof FlagsAndType) {
+ FlagsAndType that = (FlagsAndType) other;
+ return this.type.equals(that.type) &&
+ this.flags == that.flags;
+ } else {
+ return false;
+ }
+ }
+ public int hashCode() {
+ return 37 + ((flags * 41) ^ type.hashCode());
+ }
+ }
+}
+
diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java
index eed1fdc00a..7c46a2d6e4 100644
--- a/sources/scalac/symtab/classfile/UnPickle.java
+++ b/sources/scalac/symtab/classfile/UnPickle.java
@@ -39,6 +39,7 @@ public class UnPickle implements Kinds, Modifiers, EntryTags {
* | METHODtpe len_Nat tpe_Ref {tpe_Ref}
* | POLYTtpe len_Nat tpe_Ref {sym_Ref}
* | OVERLOADEDtpe len_Nat {sym_Ref} {tpe_Ref}
+ * | FLAGGEDtype len_Nat flags_Nat tpe_Ref
* SymbolInfo = name_Ref owner_Ref flags_Nat info_Ref
* NameInfo = <character sequence of length len_Nat in Utf8 format>
* Ref = Nat
@@ -54,6 +55,7 @@ public class UnPickle implements Kinds, Modifiers, EntryTags {
Name sourceName;
int[] index;
Object[] entries;
+ int paramFlags;
UnPickle(Symbol root, byte[] data, Name sourceName) {
assert root.rawInfoAt(Symbol.FIRST_ID) instanceof LazyType;
@@ -318,12 +320,16 @@ public class UnPickle implements Kinds, Modifiers, EntryTags {
break;
case METHODtpe:
Type restype = readTypeRef();
+ int bp1 = bp;
Type[] argtypes = readTypeRefs(end);
+ int[] flags = new int[argtypes.length];
+ bp = bp1;
+ readFlags(flags);
Symbol[] params = new Symbol[argtypes.length];
for (int i = 0; i < argtypes.length; i++) {
params[i] = new TermSymbol(
Position.NOPOS, Name.fromString("$" + i),
- Symbol.NONE, PARAM);
+ Symbol.NONE, PARAM | flags[i]);
params[i].setInfo(argtypes[i]);
}
tpe = Type.MethodType(params, restype);
@@ -339,6 +345,9 @@ public class UnPickle implements Kinds, Modifiers, EntryTags {
alttypes[i] = setOwner(alttypes[i], alts[i]);
tpe = Type.OverloadedType(alts, alttypes);
break;
+ case FLAGGEDtpe:
+ paramFlags = getFlags(readNat());
+ return readTypeRef();
default:
throw new BadSignature(this);
}
@@ -373,6 +382,30 @@ public class UnPickle implements Kinds, Modifiers, EntryTags {
}
}
+ void readFlags(int[] flags) {
+ for (int i = 0; i < flags.length; i++)
+ flags[i] = getFlags(readNat());
+ }
+
+ int getFlags(int n) {
+ int savedBp = bp;
+ bp = index[n];
+ int tag = bytes[bp++];
+ int end = readNat() + bp;
+ int flags = (tag == FLAGGEDtpe) ? decodeFlags(readNat()) : 0;
+ bp = savedBp;
+ return flags;
+ }
+
+ private static int decodeFlags(int n) {
+ int flags = 0;
+ if ((n & COVARflag) != 0) flags |= COVARIANT;
+ if ((n & CONTRAVARflag) != 0) flags |= CONTRAVARIANT;
+ if ((n & REPEATEDflag) != 0) flags |= REPEATED;
+ if ((n & DEFflag) != 0) flags |= DEF;
+ return flags;
+ }
+
public static class BadSignature extends java.lang.Error {
public BadSignature(UnPickle outer, String msg) {
super("symbol data " + outer.sourceName +