summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschinz <schinz@epfl.ch>2005-03-26 17:50:46 +0000
committerschinz <schinz@epfl.ch>2005-03-26 17:50:46 +0000
commita274f949c3aa9db16bd5addd0eed4f85388e74ed (patch)
tree437fff9bdb61876ccbf5fee5ef8b78ffa611f25b
parent9917c668018f845f55e09f74323509791063a463 (diff)
downloadscala-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.
-rwxr-xr-xsources/scala/tools/scalac/typechecker/RefCheck.scala2
-rw-r--r--sources/scala/tools/scalai/ExpressionCompiler.java5
-rw-r--r--sources/scalac/Global.java1
-rw-r--r--sources/scalac/ast/TreeGen.java12
-rw-r--r--sources/scalac/atree/ATreeFromSTree.java4
-rw-r--r--sources/scalac/backend/Primitives.java4
-rw-r--r--sources/scalac/backend/jvm/GenJVM.java4
-rw-r--r--sources/scalac/symtab/Definitions.java12
-rw-r--r--sources/scalac/transformer/Erasure.java4
-rw-r--r--sources/scalac/transformer/TypesAsValuesPhase.java72
-rw-r--r--sources/scalac/util/Names.java2
11 files changed, 93 insertions, 29 deletions
diff --git a/sources/scala/tools/scalac/typechecker/RefCheck.scala b/sources/scala/tools/scalac/typechecker/RefCheck.scala
index 25eab9e202..48390d2777 100755
--- a/sources/scala/tools/scalac/typechecker/RefCheck.scala
+++ b/sources/scala/tools/scalac/typechecker/RefCheck.scala
@@ -776,7 +776,7 @@ class RefCheck(globl: scalac.Global) extends Transformer(globl) {
gen.TypeApply(
gen.Select(
gen.mkLocalRef(clazz.pos, equalsParam),
- defs.ANY_AS),
+ defs.ANY_AS_ERASED),
NewArray.Tree(gen.mkType(clazz.pos, testtp)));
val that1sym = equalsSym.newVariable(clazz.pos, 0, Names.that1)
.setType(testtp);
diff --git a/sources/scala/tools/scalai/ExpressionCompiler.java b/sources/scala/tools/scalai/ExpressionCompiler.java
index f2442df655..80dd874a3b 100644
--- a/sources/scala/tools/scalai/ExpressionCompiler.java
+++ b/sources/scala/tools/scalai/ExpressionCompiler.java
@@ -223,10 +223,11 @@ public class ExpressionCompiler {
private Code tapply(Tree target, Symbol symbol, Tree[] targs, Tree[]vargs){
Code object = object(target);
- if (symbol == definitions.ANY_IS || symbol == definitions.ANY_AS) {
+ if (symbol == definitions.ANY_IS_ERASED
+ || symbol == definitions.ANY_AS_ERASED) {
assert targs.length == 1: Debug.show(targs);
assert vargs.length == 0 : Debug.show(vargs);
- boolean cast = symbol == definitions.ANY_AS;
+ boolean cast = symbol == definitions.ANY_AS_ERASED;
Type type = targs[0].type();
return Code.IsAs(object, type, context.getClass(type), cast);
}
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");