From 0c5b3ad66ef8455068ee7f7ad46c08c8b1f5e4d2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 17 Jul 2003 12:15:31 +0000 Subject: *** empty log message *** --- config/list/compiler.lst | 2 +- sources/scalac/symtab/EntryTags.java | 37 +++ sources/scalac/symtab/Symbol.java | 7 - sources/scalac/symtab/Type.java | 17 +- sources/scalac/symtab/TypeTags.java | 19 -- sources/scalac/symtab/classfile/ClassParser.java | 42 +-- sources/scalac/symtab/classfile/UnPickle.java | 386 +++++++++++++++++++++++ sources/scalac/typechecker/Analyzer.java | 19 +- 8 files changed, 478 insertions(+), 51 deletions(-) create mode 100644 sources/scalac/symtab/EntryTags.java create mode 100644 sources/scalac/symtab/classfile/UnPickle.java diff --git a/config/list/compiler.lst b/config/list/compiler.lst index 944fe6660f..9adc38df32 100644 --- a/config/list/compiler.lst +++ b/config/list/compiler.lst @@ -64,9 +64,9 @@ symtab/classfile/JavaTypeFactory.java symtab/classfile/PackageParser.java symtab/classfile/Signatures.java symtab/classfile/UnPickle.java -symtab/classfile/EntryTags.java symtab/Definitions.java +symtab/EntryTags.java symtab/Kinds.java symtab/Modifiers.java symtab/NameMangler.java diff --git a/sources/scalac/symtab/EntryTags.java b/sources/scalac/symtab/EntryTags.java new file mode 100644 index 0000000000..a2e1b32068 --- /dev/null +++ b/sources/scalac/symtab/EntryTags.java @@ -0,0 +1,37 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id: EntryTags.java + +package scalac.symtab; + +public interface EntryTags { + + int TERMname = 1, + CONSTRname = 2, + TYPEname = 3, + NONEsym = 4, + TYPEsym = 5, + ALIASsym = 6, + CLASSsym = 7, + MODULEsym = 8, + VALsym = 9, + EXTsym = 10, + NOtpe = 11, + THIStpe = 12, + SINGLEtpe = 13, + TYPEREFtpe = 14, + COMPOUNDtpe = 15, + METHODtpe = 16, + POLYtpe = 17, + OVERLOADEDtpe = 18, + UNBOXEDtpe = 19, + UNBOXEDARRAYtpe = 20, + ERRORtpe = 21; + + int firstSymTag = NONEsym, lastSymTag = VALsym; + int firstTypeTag = NOtpe, lastTypeTag = UNBOXEDARRAYtpe; +} diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index 980e11fd01..b8edc68c3b 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -1268,13 +1268,6 @@ public class ClassSymbol extends TypeSymbol { this.mangled = name; } - /** Constructor for module classes and classes with static members. - public ClassSymbol(int pos, Name name, Symbol owner, int flags, Symbol module) { - this(pos, name, owner, flags); - this.module = module; - } - */ - /** Constructor for classes to load as source files */ public ClassSymbol(Name name, Symbol owner, SourceCompleter parser) { diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index eebcd5a865..f9d5823491 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -15,7 +15,7 @@ import scalac.ApplicationError; import scalac.util.*; import scalac.Global; -public class Type implements Modifiers, Kinds, TypeTags { +public class Type implements Modifiers, Kinds, TypeTags, EntryTags { public static boolean explainSwitch = false; private static int indent = 0; @@ -2444,7 +2444,7 @@ public class Type implements Modifiers, Kinds, TypeTags { return THIStpe ^ (sym.hashCode() * 41); case TypeRef(Type pre, Symbol sym, Type[] args): - return NAMEDtpe + return TYPEREFtpe ^ (pre.hashCode() * 41) ^ (sym.hashCode() * (41*41)) ^ (hashCode(args) * (41*41*41)); @@ -2457,7 +2457,10 @@ public class Type implements Modifiers, Kinds, TypeTags { ^ (hashCode(parts) * 41) ^ (members.hashCode() * (41 * 41)); case MethodType(Symbol[] vparams, Type result): - return METHODtpe + int h = METHODtpe; + for (int i = 0; i < vparams.length; i++) + h = (h << 4) ^ vparams[i].flags; + return h ^ (hashCode(Symbol.type(vparams)) * 41) ^ (result.hashCode() * (41 * 41)); case PolyType(Symbol[] tparams, Type result): @@ -2535,7 +2538,13 @@ public class Type implements Modifiers, Kinds, TypeTags { case MethodType(Symbol[] vparams, Type result): switch (that) { case MethodType(Symbol[] vparams1, Type result1): - return equals(Symbol.type(vparams), Symbol.type(vparams1)) && + if (vparams.length != vparams1.length) + return false; + for (int i = 0; i < vparams.length; i++) + if (vparams[i].flags != vparams1[i].flags) + return false; + return + equals(Symbol.type(vparams), Symbol.type(vparams1)) && result.equals(result1); default: return false; } diff --git a/sources/scalac/symtab/TypeTags.java b/sources/scalac/symtab/TypeTags.java index a3bd103432..0a0d25cfb6 100644 --- a/sources/scalac/symtab/TypeTags.java +++ b/sources/scalac/symtab/TypeTags.java @@ -25,23 +25,4 @@ public interface TypeTags { int FirstUnboxedTag = BYTE; int LastUnboxedTag = UNIT; - - /** other type tags (used for hashcodes and Pickling) - */ - int ERRORtpe = 20; - int NOtpe = 21; - int THIStpe = 22; - int NAMEDtpe = 23; - int SINGLEtpe = 24; - int COMPOUNDtpe = 25; - int METHODtpe = 26; - int POLYtpe = 27; - int CONSTRUCTORtpe = 28; - int COVARtpe = 29; - int OVERLOADEDtpe = 30; - int UNBOXEDtpe = 31; - int UNBOXEDARRAYtpe = 32; - - int firstTypeTag = ERRORtpe; - int lastTypeTag = UNBOXEDARRAYtpe; } diff --git a/sources/scalac/symtab/classfile/ClassParser.java b/sources/scalac/symtab/classfile/ClassParser.java index 5ebf85e774..43c0eaff01 100644 --- a/sources/scalac/symtab/classfile/ClassParser.java +++ b/sources/scalac/symtab/classfile/ClassParser.java @@ -28,26 +28,30 @@ public class ClassParser extends Type.LazyType { /** complete class symbol c by loading the class */ public void complete(Symbol c) { - //System.out.println("loading " + c);//DEBUG - try { - long msec = System.currentTimeMillis(); - String filename = externalizeFileName(c.fullName()) + ".class"; - AbstractFile f = global.classPath.openFile(filename); - if (f == null) - global.error("could not read class " + c); - else { - new ClassfileParser(global, new AbstractFileReader(f), c).parse(); - global.operation("loaded " + f.getPath() + " in " + - (System.currentTimeMillis() - msec) + "ms"); - //for (Definition e = c.locals().elems; e != null; e = e.sibling) - // if (e.def.kind == TYP) + if (completed) { + c.setInfo(Type.NoType); + } else { + //System.out.println("loading " + c);//DEBUG + try { + long msec = System.currentTimeMillis(); + String filename = externalizeFileName(c.fullName()) + ".class"; + AbstractFile f = global.classPath.openFile(filename); + if (f == null) + global.error("could not read class " + c); + else { + new ClassfileParser(global, new AbstractFileReader(f), c).parse(); + global.operation("loaded " + f.getPath() + " in " + + (System.currentTimeMillis() - msec) + "ms"); + //for (Definition e = c.locals().elems; e != null; e = e.sibling) + // if (e.def.kind == TYP) // e.def.complete(); - } - } catch (IOException e) { - e.printStackTrace(); - global.error("i/o error while loading " + c); - c.setInfo(Type.ErrorType); - } + } + } catch (IOException e) { + e.printStackTrace(); + global.error("i/o error while loading " + c); + c.setInfo(Type.ErrorType); + } + } } /** return external representation of file name s, diff --git a/sources/scalac/symtab/classfile/UnPickle.java b/sources/scalac/symtab/classfile/UnPickle.java new file mode 100644 index 0000000000..eed1fdc00a --- /dev/null +++ b/sources/scalac/symtab/classfile/UnPickle.java @@ -0,0 +1,386 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id$ + +package scalac.symtab.classfile; + +import java.util.HashMap; +import scalac.*; +import scalac.util.*; +import ch.epfl.lamp.util.Position; +import scalac.symtab.*; +import Symbol.*; +import Type.*; + +public class UnPickle implements Kinds, Modifiers, EntryTags { + +/*************************************************** + * Symbol table attribute format: + * Symtab = nentries_Nat {Entry} + * Entry = TERMNAME len_Nat NameInfo + * | CONSTRNAME len_Nat NameInfo + * | TYPENAME len_Nat NameInfo + * | NONEsym len_Nat + * | TYPEsym len_Nat SymbolInfo lobound_Ref + * | ALIASsym len_Nat SymbolInfo + * | CLASSsym len_Nat SymbolInfo thistype_Ref constrsym_Ref + * | MODULEsym len_Nat SymbolInfo classsym_Ref + * | VALsym len_Nat SymbolInfo [classsym_Ref] + * | EXTsym len_Nat name_Ref [owner_Ref] + * | NOtpe len_Nat + * | THIStpe len_Nat sym_Ref + * | SINGLEtpe len_Nat type_Ref sym_Ref + * | TYPEREFtpe len_Nat type_Ref sym_Ref {targ_Ref} + * | COMPOUNDtpe len_Nat sym_Ref {tpe_Ref} {sym_Ref} + * | METHODtpe len_Nat tpe_Ref {tpe_Ref} + * | POLYTtpe len_Nat tpe_Ref {sym_Ref} + * | OVERLOADEDtpe len_Nat {sym_Ref} {tpe_Ref} + * SymbolInfo = name_Ref owner_Ref flags_Nat info_Ref + * NameInfo = + * Ref = Nat + * + * len is remaining length after `len'. + */ + static final boolean debug = false; + + Symbol classroot; + Symbol moduleroot; + byte[] bytes; + int bp; + Name sourceName; + int[] index; + Object[] entries; + + UnPickle(Symbol root, byte[] data, Name sourceName) { + assert root.rawInfoAt(Symbol.FIRST_ID) instanceof LazyType; + //System.out.println("unpickle " + root);//DEBUG + this.classroot = root; + this.moduleroot = classroot.module(); + this.bytes = data; + this.bp = 0; + this.sourceName = sourceName; + index = new int[readNat()]; + for (int i = 0; i < index.length; i++) { + index[i] = bp; + bp++; + bp = readNat() + bp; + } + entries = new Object[index.length]; + if (debug) { + for (int i = 0; i < index.length; i++) { + System.out.print(i + "," + index[i] + ": "); + bp = index[i]; + System.out.print(readByte() + " "); + int len = readNat(); + System.out.print(len + " "); + for (int j = 0; j < len; j++) + System.out.print(readByte() + " "); + System.out.println(); + } + } + for (int i = 0; i < index.length; i++) { + if (isSymbolEntry(i)) getSymbol(i); + } + if (root.rawInfoAt(Symbol.FIRST_ID) instanceof LazyType) + throw new BadSignature(this, "it does not define " + root); + } + + Type setOwner(Type tp, Symbol owner) { + switch (tp) { + case PolyType(Symbol[] tparams, Type restpe): + Type restpe1 = setOwner(restpe, owner); + if (restpe1 == restpe) return tp; + else return Type.PolyType(tparams, restpe1); + case MethodType(Symbol[] params, Type restpe): + Symbol[] params1 = params; + for (int i = 0; i < params.length; i++) { + if (params[i].owner() != owner) { + if (params1 == params && params[i].owner() != Symbol.NONE) { + params1 = new Symbol[params.length]; + System.arraycopy(params, 0, params1, 0, i); + } + params1[i].setOwner(owner); + } + } + Type restpe1 = setOwner(restpe, owner); + if (params1 == params && restpe1 == restpe) return tp; + else return Type.MethodType(params1, restpe1); + default: + return tp; + } + } + + int readByte() { + return bytes[bp++]; + } + + int readNat() { + int b; + int x = 0; + do { + b = readByte(); + x = (x << 7) + (b & 0x7f); + } while ((b & 0x80) != 0); + return x; + } + + boolean isTypeEntry(int i) { + int tag = bytes[index[i]]; + return (firstTypeTag <= tag && tag <= lastTypeTag); + } + + boolean isSymbolEntry(int i) { + int tag = bytes[index[i]]; + return (firstSymTag <= tag && tag <= lastSymTag); + } + + Name getName(int n) { + if (entries[n] == null) { + int savedBp = bp; + bp = index[n]; + int tag = bytes[bp++]; + int len = readNat(); + Name name = Name.fromAscii(bytes, bp, len); + switch (tag) { + case TERMname : entries[n] = name; break; + case CONSTRname: entries[n] = name.toConstrName(); break; + case TYPEname : entries[n] = name.toTypeName(); break; + default: throw new BadSignature(this); + } + bp = savedBp; + } + return (Name) entries[n]; + } + + Name readNameRef() { + return getName(readNat()); + } + + Symbol getSymbol(int n) { + if (entries[n] == null) { + int savedBp = bp; + bp = index[n]; + int tag = bytes[bp++]; + int end = readNat() + bp; + Symbol sym; + Symbol owner; + switch (tag) { + case NONEsym: + entries[n] = sym = Symbol.NONE; + break; + case EXTsym: + Name name = readNameRef(); + if (bp == end) { + owner = Global.instance.definitions.ROOT_CLASS; + } else { + assert bp < end; + owner = readSymbolRef(); + } + if (name.length() == 0 && owner == Symbol.NONE) { + entries[n] = sym = Global.instance.definitions.ROOT_CLASS; + } else { + entries[n] = sym = owner.info().lookupNonPrivate(name); + } + if (sym.kind == NONE) { + throw new BadSignature(this, + "reference " + name + " of " + owner + + " refers to nonexisting symbol."); + } + break; + default: + assert isSymbolEntry(n) : n; + Name name = readNameRef(); + owner = readSymbolRef(); + if (entries[n] == null) { + int flags = readNat(); + int inforef = readNat(); + switch (tag) { + case TYPEsym: + entries[n] = sym = new AbsTypeSymbol( + Position.NOPOS, name, owner, flags); + sym.setInfo(getType(inforef)); + sym.setLoBound(readTypeRef()); + break; + + case ALIASsym: + entries[n] = sym = new TypeSymbol( + ALIAS, Position.NOPOS, name, owner, flags); + sym.setInfo(getType(inforef)); + break; + + case CLASSsym: + entries[n] = sym = new ClassSymbol( + Position.NOPOS, name, owner, flags); + if (name == classroot.name && owner == classroot.owner()) { + sym.copyTo(classroot); + entries[n] = sym = classroot; + } + sym.setInfo(getType(inforef)); + sym.setTypeOfThis(readTypeRef()); + Symbol constructor = readSymbolRef(); //will install itself! + break; + + case MODULEsym: + entries[n] = sym = TermSymbol.newModule( + Position.NOPOS, name, owner, flags, (ClassSymbol) readSymbolRef()); + if (name == moduleroot.name && owner == moduleroot.owner()) { + sym.copyTo(moduleroot); + entries[n] = sym = moduleroot; + } + sym.setInfo(getType(inforef)); + break; + + case VALsym: + if (bp < end) { + assert name.isConstrName(); + Symbol clazz = readSymbolRef(); + entries[n] = sym = clazz.constructor(); + TermSymbol.newConstructor(clazz, flags).copyTo(sym); + } else { + entries[n] = sym = new TermSymbol( + Position.NOPOS, name, owner, flags); + } + sym.setInfo(setOwner(getType(inforef), sym)); + break; + + default: + throw new BadSignature(this); + } + + if (owner.kind == CLASS && + !(sym == classroot || + sym.kind == CLASS && (sym.flags & MODUL) != 0 || + (sym.isPrimaryConstructor() && + (sym.primaryConstructorClass().flags & MODUL) != 0))) + owner.members().enter(sym); + } + } + bp = savedBp; + } + return (Symbol) entries[n]; + } + + Symbol readSymbolRef() { + return getSymbol(readNat()); + } + + Symbol[] readSymbolRefs(int end) { + return readSymbolRefs(0, end); + } + + Symbol[] readSymbolRefs(int nread, int end) { + if (bp == end) { + return new Symbol[nread]; + } else { + assert bp < end; + int ref = readNat(); + if (isSymbolEntry(ref)) { + Symbol s = getSymbol(ref); + Symbol[] ss = readSymbolRefs(nread+1, end); + ss[nread] = s; + return ss; + } else { + return new Symbol[nread]; + } + } + } + + Type getType(int n) { + if (entries[n] == null) { + int savedBp = bp; + bp = index[n]; + int tag = bytes[bp++]; + int end = readNat() + bp; + Type tpe; + switch (tag) { + case NOtpe: + tpe = Type.NoType; + break; + case THIStpe: + tpe = Type.ThisType(readSymbolRef()); + break; + case SINGLEtpe: + tpe = Type.singleType(readTypeRef(), readSymbolRef()); + break; + case TYPEREFtpe: + tpe = Type.TypeRef( + readTypeRef(), readSymbolRef(), readTypeRefs(end)); + break; + case COMPOUNDtpe: + Symbol clazz = readSymbolRef(); + Type[] parents = readTypeRefs(end); + Scope members = new Scope(readSymbolRefs(end)); + tpe = Type.compoundType(parents, members, clazz); + break; + case METHODtpe: + Type restype = readTypeRef(); + Type[] argtypes = readTypeRefs(end); + 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); + params[i].setInfo(argtypes[i]); + } + tpe = Type.MethodType(params, restype); + break; + case POLYtpe: + Type restype = readTypeRef(); + tpe = Type.PolyType(readSymbolRefs(end), restype); + break; + case OVERLOADEDtpe: + Symbol[] alts = readSymbolRefs(end); + Type[] alttypes = readTypeRefs(end); + for (int i = 0; i < alts.length; i++) + alttypes[i] = setOwner(alttypes[i], alts[i]); + tpe = Type.OverloadedType(alts, alttypes); + break; + default: + throw new BadSignature(this); + } + entries[n] = tpe; + bp = savedBp; + } + return (Type) entries[n]; + } + + Type readTypeRef() { + return getType(readNat()); + } + + Type[] readTypeRefs(int end) { + return readTypeRefs(0, end); + } + + Type[] readTypeRefs(int nread, int end) { + if (bp == end) { + return new Type[nread]; + } else { + assert bp < end; + int ref = readNat(); + if (isTypeEntry(ref)) { + Type t = getType(ref); + Type[] ts = readTypeRefs(nread + 1, end); + ts[nread] = t; + return ts; + } else { + return new Type[nread]; + } + } + } + + public static class BadSignature extends java.lang.Error { + public BadSignature(UnPickle outer, String msg) { + super("symbol data " + outer.sourceName + + " could not be loaded; " + msg); + } + public BadSignature(UnPickle outer) { + this(outer, "malformed signature at " + outer.bp); + } + } +} + diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index 2cd0853f76..8c427c3c84 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -795,7 +795,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (other.isPreloaded()) { // symbol was preloaded from package; // need to overwrite definition. - UnPickle.overwrite(sym, other); + overwrite(sym, other); result = other; } else if (sym.owner().isPackage()) { if (global.compiledNow.get(other) != null) { @@ -829,6 +829,23 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { return result; } + /** Overwrite symbol `to' from symbol `from' + */ + void overwrite(Symbol from, Symbol to) { + if (Global.instance.debug) System.out.println(from + " overwrites " + to);//debug + from.copyTo(to); + if (from.isModule()) { + from.moduleClass().copyTo( + to.moduleClass()); + from.moduleClass().constructor().copyTo( + to.moduleClass().constructor()); + to.moduleClass().constructor().setInfo( + Type.MethodType( + Symbol.EMPTY_ARRAY, + to.moduleClass().typeConstructor())); + } + } + /** Enter all symbols in statement list */ public void enterSyms(Tree[] stats) { -- cgit v1.2.3