summaryrefslogtreecommitdiff
path: root/src/compiler/scala/reflect/internal/TreeGen.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@epfl.ch>2011-11-29 00:03:40 +0100
committerAdriaan Moors <adriaanm@gmail.com>2011-12-24 17:36:52 +0100
commit08ec6ba4e4aeb94f6505ecb462b94362ff0af096 (patch)
treea54bad8e6b329e672b64835c5eaa1fae9d25272b /src/compiler/scala/reflect/internal/TreeGen.scala
parentfc0c123e3560da190a3daae35214c2be50fd59e6 (diff)
downloadscala-08ec6ba4e4aeb94f6505ecb462b94362ff0af096.tar.gz
scala-08ec6ba4e4aeb94f6505ecb462b94362ff0af096.tar.bz2
scala-08ec6ba4e4aeb94f6505ecb462b94362ff0af096.zip
[vpm] optimized codegen avoids option-boxing
introducing two mutable variables per pattern match: matchRes and keepGoing keepGoing denotes whether the result was Some or None, and matchRes holds the Some's contents or the right zero for the match's type Race(() => fastMatch(list), () => virtMatch_no_option(list))(100000).converge() is a virtual tie on my machine after this see https://gist.github.com/1400910 conveniently also works around SI-5245 don't assign to Unit-typed var's, in fact, make matchRes a val when its only prospect in life is to be unit-valued propagate eventual type for matchRes thru codegen so that we can have more robust checks for unit&nothing, when assignment makes no sense also, added a hack to caseResult to avoid boxed units in if(keepGoing) { matchRes = ... } else zero after erasure, we get if(keepGoing) { matchRes = ...; BoxedUNIT } else zero genicode broke because i was sharing trees: [scalacfork] error: java.lang.AssertionError: assertion failed: type error: can't convert from UNIT to REF(class Object) in unit ScalaSig.scala at source-/Users/adriaan/git/scala-dev/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala,line-26,offset=868 fixed by duplicating -- so be it (for now -- make this more fine-grained, more efficient) dodging inliner issues with one/zero (it won't inline, so also directly inline those methods)
Diffstat (limited to 'src/compiler/scala/reflect/internal/TreeGen.scala')
-rw-r--r--src/compiler/scala/reflect/internal/TreeGen.scala29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/compiler/scala/reflect/internal/TreeGen.scala b/src/compiler/scala/reflect/internal/TreeGen.scala
index 1c93a904c0..e537c6b83f 100644
--- a/src/compiler/scala/reflect/internal/TreeGen.scala
+++ b/src/compiler/scala/reflect/internal/TreeGen.scala
@@ -154,9 +154,13 @@ abstract class TreeGen {
debuglog("casting " + tree + ":" + tree.tpe + " to " + pt + " at phase: " + phase)
assert(!tree.tpe.isInstanceOf[MethodType], tree)
assert(!pt.typeSymbol.isPackageClass && !pt.typeSymbol.isPackageObjectClass, pt)
- // @MAT only called during erasure, which already takes care of that
- // @PP: "only called during erasure" is not very true these days.
- // In addition, at least, are: typer, uncurry, explicitouter, cleanup.
+ // called during (at least): typer, uncurry, explicitouter, cleanup.
+ // TODO: figure out the truth table for any/wrapInApply
+ // - the `any` flag seems to relate to erasure's adaptMember: "x.asInstanceOf[T] becomes x.$asInstanceOf[T]",
+ // where asInstanceOf is Any_asInstanceOf and $asInstanceOf is Object_asInstanceOf
+ // erasure will only unbox the value in a tree made by mkCast if `any && wrapInApply`
+ // - the `wrapInApply` flag need not be true if the tree will be adapted to have the empty argument list added before it gets to erasure
+ // in fact, I think it should be false for trees that will be type checked during typer
assert(pt eq pt.normalize, tree +" : "+ debugString(pt) +" ~>"+ debugString(pt.normalize))
atPos(tree.pos)(mkAsInstanceOf(tree, pt, any = false, wrapInApply = true))
}
@@ -262,6 +266,25 @@ abstract class TreeGen {
tree setType tp
}
+ def mkZeroContravariantAfterTyper(tp: Type): Tree = {
+ // contravariant -- for replacing an argument in a method call
+ // must use subtyping, as otherwise we miss types like `Any with Int`
+ val tree =
+ if (NullClass.tpe <:< tp) Literal(Constant(null))
+ else if (UnitClass.tpe <:< tp) Literal(Constant())
+ else if (BooleanClass.tpe <:< tp) Literal(Constant(false))
+ else if (FloatClass.tpe <:< tp) Literal(Constant(0.0f))
+ else if (DoubleClass.tpe <:< tp) Literal(Constant(0.0d))
+ else if (ByteClass.tpe <:< tp) Literal(Constant(0.toByte))
+ else if (ShortClass.tpe <:< tp) Literal(Constant(0.toShort))
+ else if (IntClass.tpe <:< tp) Literal(Constant(0))
+ else if (LongClass.tpe <:< tp) Literal(Constant(0L))
+ else if (CharClass.tpe <:< tp) Literal(Constant(0.toChar))
+ else mkCast(Literal(Constant(null)), tp)
+
+ tree
+ }
+
/** Builds a tuple */
def mkTuple(elems: List[Tree]): Tree =
if (elems.isEmpty) Literal(Constant())