diff options
author | schinz <schinz@epfl.ch> | 2005-03-26 17:50:46 +0000 |
---|---|---|
committer | schinz <schinz@epfl.ch> | 2005-03-26 17:50:46 +0000 |
commit | a274f949c3aa9db16bd5addd0eed4f85388e74ed (patch) | |
tree | 437fff9bdb61876ccbf5fee5ef8b78ffa611f25b /sources/scalac | |
parent | 9917c668018f845f55e09f74323509791063a463 (diff) | |
download | scala-a274f949c3aa9db16bd5addd0eed4f85388e74ed.tar.gz scala-a274f949c3aa9db16bd5addd0eed4f85388e74ed.tar.bz2 scala-a274f949c3aa9db16bd5addd0eed4f85388e74ed.zip |
- introduced isInstanceOf$erased and asInstance...
- introduced isInstanceOf$erased and asInstanceOf$erased methods, which
work on the erased types; things to note:
* before TypesAsValues phase, either variant can be used, although
the erased ones need to be used with caution, when speed
matters;
* after TypesAsValues phase, only the erased variants should be
used (done automatically by TreeGen);
* when run time types are disabled, the TypesAsValues phase is not
skipped anymore: it is turned into a trivial phase which
rewrites all non-erased instanceof/casts into erased ones.
Diffstat (limited to 'sources/scalac')
-rw-r--r-- | sources/scalac/Global.java | 1 | ||||
-rw-r--r-- | sources/scalac/ast/TreeGen.java | 12 | ||||
-rw-r--r-- | sources/scalac/atree/ATreeFromSTree.java | 4 | ||||
-rw-r--r-- | sources/scalac/backend/Primitives.java | 4 | ||||
-rw-r--r-- | sources/scalac/backend/jvm/GenJVM.java | 4 | ||||
-rw-r--r-- | sources/scalac/symtab/Definitions.java | 12 | ||||
-rw-r--r-- | sources/scalac/transformer/Erasure.java | 4 | ||||
-rw-r--r-- | sources/scalac/transformer/TypesAsValuesPhase.java | 72 | ||||
-rw-r--r-- | sources/scalac/util/Names.java | 2 |
9 files changed, 89 insertions, 26 deletions
diff --git a/sources/scalac/Global.java b/sources/scalac/Global.java index ead3469865..6c2b9ac200 100644 --- a/sources/scalac/Global.java +++ b/sources/scalac/Global.java @@ -276,7 +276,6 @@ public abstract class Global { args.phases.WHOLEPROG.addSkipFlag(); // !!! // if (!optimize) PHASE.remove(args.phases.OPTIMIZE); // TODO: Enable TailCall for other backends when they handle LabelDefs - if (!runTimeTypes) args.phases.TYPESASVALUES.addSkipFlag(); if (target != TARGET_JVMFROMICODE) args.phases.ICODE.addSkipFlag(); PHASE.freeze(); PhaseDescriptor[] descriptors = PHASE.phases(); diff --git a/sources/scalac/ast/TreeGen.java b/sources/scalac/ast/TreeGen.java index 31389a3227..43d1fc1ed5 100644 --- a/sources/scalac/ast/TreeGen.java +++ b/sources/scalac/ast/TreeGen.java @@ -641,8 +641,10 @@ public class TreeGen implements Kinds, Modifiers, TypeTags { /** Builds an instance test with given value and type. */ public Tree mkIsInstanceOf(int pos, Tree value, Type type) { - Type[] targs = new Type[]{type}; - return mkApplyT_(pos, Select(value, definitions.ANY_IS), targs); + Symbol sym = global.currentPhase.id >= global.PHASE.TYPESASVALUES.id() + ? definitions.ANY_IS_ERASED + : definitions.ANY_IS; + return mkApplyT_(pos, Select(value, sym), new Type[]{type}); } public Tree mkIsInstanceOf(Tree value, Type type) { return mkIsInstanceOf(value.pos, value, type); @@ -650,8 +652,10 @@ public class TreeGen implements Kinds, Modifiers, TypeTags { /** Builds a cast with given value and type. */ public Tree mkAsInstanceOf(int pos, Tree value, Type type) { - Type[] targs = new Type[]{type}; - return mkApplyT_(pos, Select(value, definitions.ANY_AS), targs); + Symbol sym = global.currentPhase.id >= global.PHASE.TYPESASVALUES.id() + ? definitions.ANY_AS_ERASED + : definitions.ANY_AS; + return mkApplyT_(pos, Select(value, sym), new Type[]{type}); } public Tree mkAsInstanceOf(Tree value, Type type) { return mkAsInstanceOf(value.pos, value, type); diff --git a/sources/scalac/atree/ATreeFromSTree.java b/sources/scalac/atree/ATreeFromSTree.java index ba5cb03155..43944c47c2 100644 --- a/sources/scalac/atree/ATreeFromSTree.java +++ b/sources/scalac/atree/ATreeFromSTree.java @@ -476,8 +476,8 @@ public class ATreeFromSTree { if (clasz == definitions.ANY_CLASS) { addGenerator(definitions.ANY_EQEQ, Generator.ANYEQ); addGenerator(definitions.ANY_BANGEQ, Generator.ANYNE); - addGenerator(definitions.ANY_IS, Generator.ISAS(false)); - addGenerator(definitions.ANY_AS, Generator.ISAS(true)); + addGenerator(definitions.ANY_IS_ERASED, Generator.ISAS(false)); + addGenerator(definitions.ANY_AS_ERASED, Generator.ISAS(true)); } if (clasz == definitions.OBJECT_CLASS) { addGenerator(definitions.OBJECT_EQ, Generator.ANYID); diff --git a/sources/scalac/backend/Primitives.java b/sources/scalac/backend/Primitives.java index 3334b35748..76869c2f78 100644 --- a/sources/scalac/backend/Primitives.java +++ b/sources/scalac/backend/Primitives.java @@ -467,8 +467,8 @@ public class Primitives { Definitions defs = definitions; // scala.Any - addPrimitive(defs.ANY_IS, Primitive.IS); - addPrimitive(defs.ANY_AS, Primitive.AS); + addPrimitive(defs.ANY_IS_ERASED, Primitive.IS); + addPrimitive(defs.ANY_AS_ERASED, Primitive.AS); addPrimitive(defs.ANY_EQEQ, Primitive.EQ); addPrimitive(defs.ANY_BANGEQ, Primitive.NE); // !!! addPrimitive(defs.ANY_EQUALS, Primitive.EQUALS); diff --git a/sources/scalac/backend/jvm/GenJVM.java b/sources/scalac/backend/jvm/GenJVM.java index 84108ed57c..9ba9b67939 100644 --- a/sources/scalac/backend/jvm/GenJVM.java +++ b/sources/scalac/backend/jvm/GenJVM.java @@ -299,10 +299,10 @@ public class GenJVM { genLoadQualifier(ctx, fun); JType type = typeStoJ(args[0].type); - if (fun.symbol() == defs.ANY_IS) { + if (fun.symbol() == defs.ANY_IS_ERASED) { ctx.code.emitINSTANCEOF((JReferenceType)type); generatedType = JType.BOOLEAN; - } else if (fun.symbol() == defs.ANY_AS) { + } else if (fun.symbol() == defs.ANY_AS_ERASED) { ctx.code.emitCHECKCAST((JReferenceType)type); generatedType = type; } else diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java index a5b3951ac8..6dda72353e 100644 --- a/sources/scalac/symtab/Definitions.java +++ b/sources/scalac/symtab/Definitions.java @@ -320,7 +320,9 @@ public class Definitions { public final Symbol ANY_TOSTRING; //public final Symbol ANY_PLUS; public final Symbol ANY_IS; + public final Symbol ANY_IS_ERASED; public final Symbol ANY_AS; + public final Symbol ANY_AS_ERASED; public final Symbol ANY_MATCH; //######################################################################## @@ -815,7 +817,9 @@ public class Definitions { ANY_TOSTRING = newMethod(ANY_CLASS,Names.toString ,0); // ANY_PLUS = newMethod(ANY_CLASS,Names.PLUS ,Modifiers.FINAL); ANY_IS = newMethod(ANY_CLASS,Names.isInstanceOf,Modifiers.FINAL); + ANY_IS_ERASED= newMethod(ANY_CLASS,Names.isInstanceOfE,Modifiers.FINAL); ANY_AS = newMethod(ANY_CLASS,Names.asInstanceOf,Modifiers.FINAL); + ANY_AS_ERASED= newMethod(ANY_CLASS,Names.asInstanceOfE,Modifiers.FINAL); ANY_MATCH = newMethod(ANY_CLASS,Names._match ,Modifiers.FINAL); initMethod(ANY_EQEQ , new Type[]{ANY_TYPE()} , boolean_TYPE()); @@ -827,9 +831,17 @@ public class Definitions { Symbol[] ANY_IS_TPARAMS = {newTParam(ANY_IS, 0, ANY_TYPE())}; ANY_IS.setInfo(Type.PolyType(ANY_IS_TPARAMS, boolean_TYPE())); + Symbol[] ANY_IS_ERASED_TPARAMS = + {newTParam(ANY_IS_ERASED, 0, ANY_TYPE())}; + ANY_IS_ERASED.setInfo(Type.PolyType(ANY_IS_ERASED_TPARAMS, + boolean_TYPE())); Symbol[] ANY_AS_TPARAMS = {newTParam(ANY_AS, 0, ANY_TYPE())}; ANY_AS.setInfo(Type.PolyType(ANY_AS_TPARAMS,ANY_AS_TPARAMS[0].type())); + Symbol[] ANY_AS_ERASED_TPARAMS = + {newTParam(ANY_AS_ERASED, 0, ANY_TYPE())}; + ANY_AS_ERASED.setInfo(Type.PolyType(ANY_AS_ERASED_TPARAMS, + ANY_AS_ERASED_TPARAMS[0].type())); Symbol[] ANY_MATCH_TPARAMS = { newTParam(ANY_MATCH, 0, ANY_TYPE()), diff --git a/sources/scalac/transformer/Erasure.java b/sources/scalac/transformer/Erasure.java index ea77bdf926..67a462b1f4 100644 --- a/sources/scalac/transformer/Erasure.java +++ b/sources/scalac/transformer/Erasure.java @@ -163,11 +163,11 @@ public class Erasure extends GenTransformer implements Modifiers { fun = transform(fun); vargs = transform(vargs); Symbol symbol = fun.symbol(); - if (symbol == definitions.ANY_AS) { + if (symbol == definitions.ANY_AS_ERASED) { assert targs.length == 1 && vargs.length == 0: tree; return coerce(getQualifier(fun), targs[0].getType().erasure()); } - if (symbol == definitions.ANY_IS) { + if (symbol == definitions.ANY_IS_ERASED) { assert targs.length == 1 && vargs.length == 0: tree; Type type = targs[0].type.erasure(); if (isUnboxedSimpleType(type)) type = targs[0].type; diff --git a/sources/scalac/transformer/TypesAsValuesPhase.java b/sources/scalac/transformer/TypesAsValuesPhase.java index 11dcaa2487..b5dc28a0c0 100644 --- a/sources/scalac/transformer/TypesAsValuesPhase.java +++ b/sources/scalac/transformer/TypesAsValuesPhase.java @@ -21,6 +21,7 @@ import scalac.atree.AConstant; import scalac.ast.Transformer; import scalac.ast.GenTransformer; import scalac.ast.Tree; +import scalac.ast.TreeGen; import scalac.ast.TreeList; import scalac.backend.Primitives; @@ -63,7 +64,7 @@ import java.util.Collections; // time. public class TypesAsValuesPhase extends Phase { - private final TV_Transformer transformer; + private final GenTransformer transformer; /** * The list of members to add to a given class (either type @@ -108,7 +109,12 @@ public class TypesAsValuesPhase extends Phase { public TypesAsValuesPhase(Global global, PhaseDescriptor descriptor) { super(global, descriptor); - transformer = new TV_Transformer(global); + // If RTT are disabled, use a minimal transformer which simply + // replaces [ia]sInstanceOf with their erased counterpart. + if (global.runTimeTypes) + transformer = new TV_Transformer(global); + else + transformer = new TV_MiniTransformer(global); predefTypes = new HashMap(); predefTypes.put(defs.DOUBLE_CLASS, defs.RTT_DOUBLE()); @@ -271,10 +277,14 @@ public class TypesAsValuesPhase extends Phase { || sym == ARRAY_CONSTRUCTOR || sym == defs.OBJECT_SYNCHRONIZED || sym == defs.ANY_IS - || sym == defs.ANY_AS; + || sym == defs.ANY_IS_ERASED + || sym == defs.ANY_AS + || sym == defs.ANY_AS_ERASED; } public Type transformInfo(Symbol symbol, Type type) { + if (!global.runTimeTypes) return type; + if (symbol.isClass()) { Symbol[] toAdd = membersToAdd(symbol); @@ -925,16 +935,6 @@ public class TypesAsValuesPhase extends Phase { return tparamsPerm; } - /** - * Extract qualifier from a tree, which must be a Select node. - */ - private Tree qualifierOf(Tree tree) { - switch (tree) { - case Select(Tree qualifier, _): return qualifier; - default: throw Debug.abort("cannot extract qualifier from ", tree); - } - } - private boolean isValuePrefix(Type pre) { switch (pre) { case ThisType(Symbol clazz): @@ -1056,6 +1056,52 @@ public class TypesAsValuesPhase extends Phase { } } + /** + * Minimalistic transformer, which simply transforms calls to + * isInstanceOf/asInstanceOf by calls to their erased + * counterparts. Used when full run time types are disabled. + */ + private class TV_MiniTransformer extends GenTransformer { + private final Definitions defs; + + public TV_MiniTransformer(Global global) { + super(global); + defs = global.definitions; + } + + public Tree transform(Tree tree) { + switch (tree) { + case Apply(TypeApply(Tree fun, Tree[] targs), Tree[] vargs): + Symbol funSym = fun.symbol(); + if (funSym == defs.ANY_IS || funSym == defs.ANY_AS) { + Symbol erasedSym = (funSym == defs.ANY_AS) + ? defs.ANY_AS_ERASED + : defs.ANY_IS_ERASED; + return gen.mkApplyTV(tree.pos, + gen.Select(fun.pos, + qualifierOf(fun), + erasedSym), + targs, + vargs); + } else + return super.transform(tree); + + default: + return super.transform(tree); + } + } + } + + /** + * Extract qualifier from a tree, which must be a Select node. + */ + private Tree qualifierOf(Tree tree) { + switch (tree) { + case Select(Tree qualifier, _): return qualifier; + default: throw Debug.abort("cannot extract qualifier from ", tree); + } + } + // Debugging function private void debugPrintAncestor(Symbol sym, Ancestor[][] ancestor) { System.out.println("ancestor for " + Debug.show(sym)); diff --git a/sources/scalac/util/Names.java b/sources/scalac/util/Names.java index c2e759920c..18013be172 100644 --- a/sources/scalac/util/Names.java +++ b/sources/scalac/util/Names.java @@ -157,6 +157,7 @@ public class Names { public static final Name apply = Name.fromString("apply"); public static final Name array = Name.fromString("array"); public static final Name asInstanceOf = Name.fromString("asInstanceOf"); + public static final Name asInstanceOfE = Name.fromString("asInstanceOf$erased"); public static final Name box = Name.fromString("box"); public static final Name caseArity = Name.fromString("caseArity"); public static final Name caseElement = Name.fromString("caseElement"); @@ -185,6 +186,7 @@ public class Names { public static final Name hasNext = Name.fromString("hasNext"); public static final Name head = Name.fromString("head"); public static final Name isInstanceOf = Name.fromString("isInstanceOf"); + public static final Name isInstanceOfE = Name.fromString("isInstanceOf$erased"); public static final Name isDefinedAt = Name.fromString("isDefinedAt"); public static final Name isEmpty = Name.fromString("isEmpty"); public static final Name instantiate = Name.fromString("instantiate"); |