Skip to content
Permalink
Browse files

SI-7814 Updates the instrumented version of ScalaRuntime.

Some tests for specialization use a modified version of
the standard library that count boxing, array lookups etc.

These sources are updated manually with the script:

    % test/instrumented/mkinstrumented.sh build

Looks that that wasn't done for a while, though.

This commit brings it up to date, and adjusts a few braces in
ScalaRuntime.scala so the  srt.scala (used by that script)
is shorter.

We should really avoid checking in the products of that script and
run it as part of the build, or, better, use the bytecode
instrumentation framework instead of a modified standard library.
But I have to leave that for another day.
  • Loading branch information...
@retronym
retronym committedSep 5, 2013
1 parent fb43ec8 commit a19babc952c1e30d9b92452505e85752ff2d5460
@@ -67,33 +67,37 @@ object ScalaRunTime {
classTag[T].runtimeClass.asInstanceOf[jClass[T]]

/** Retrieve generic array element */
def array_apply(xs: AnyRef, idx: Int): Any = xs match {
case x: Array[AnyRef] => x(idx).asInstanceOf[Any]
case x: Array[Int] => x(idx).asInstanceOf[Any]
case x: Array[Double] => x(idx).asInstanceOf[Any]
case x: Array[Long] => x(idx).asInstanceOf[Any]
case x: Array[Float] => x(idx).asInstanceOf[Any]
case x: Array[Char] => x(idx).asInstanceOf[Any]
case x: Array[Byte] => x(idx).asInstanceOf[Any]
case x: Array[Short] => x(idx).asInstanceOf[Any]
case x: Array[Boolean] => x(idx).asInstanceOf[Any]
case x: Array[Unit] => x(idx).asInstanceOf[Any]
case null => throw new NullPointerException
def array_apply(xs: AnyRef, idx: Int): Any = {
xs match {
case x: Array[AnyRef] => x(idx).asInstanceOf[Any]
case x: Array[Int] => x(idx).asInstanceOf[Any]
case x: Array[Double] => x(idx).asInstanceOf[Any]
case x: Array[Long] => x(idx).asInstanceOf[Any]
case x: Array[Float] => x(idx).asInstanceOf[Any]
case x: Array[Char] => x(idx).asInstanceOf[Any]
case x: Array[Byte] => x(idx).asInstanceOf[Any]
case x: Array[Short] => x(idx).asInstanceOf[Any]
case x: Array[Boolean] => x(idx).asInstanceOf[Any]
case x: Array[Unit] => x(idx).asInstanceOf[Any]
case null => throw new NullPointerException
}
}

/** update generic array element */
def array_update(xs: AnyRef, idx: Int, value: Any): Unit = xs match {
case x: Array[AnyRef] => x(idx) = value.asInstanceOf[AnyRef]
case x: Array[Int] => x(idx) = value.asInstanceOf[Int]
case x: Array[Double] => x(idx) = value.asInstanceOf[Double]
case x: Array[Long] => x(idx) = value.asInstanceOf[Long]
case x: Array[Float] => x(idx) = value.asInstanceOf[Float]
case x: Array[Char] => x(idx) = value.asInstanceOf[Char]
case x: Array[Byte] => x(idx) = value.asInstanceOf[Byte]
case x: Array[Short] => x(idx) = value.asInstanceOf[Short]
case x: Array[Boolean] => x(idx) = value.asInstanceOf[Boolean]
case x: Array[Unit] => x(idx) = value.asInstanceOf[Unit]
case null => throw new NullPointerException
def array_update(xs: AnyRef, idx: Int, value: Any): Unit = {
xs match {
case x: Array[AnyRef] => x(idx) = value.asInstanceOf[AnyRef]
case x: Array[Int] => x(idx) = value.asInstanceOf[Int]
case x: Array[Double] => x(idx) = value.asInstanceOf[Double]
case x: Array[Long] => x(idx) = value.asInstanceOf[Long]
case x: Array[Float] => x(idx) = value.asInstanceOf[Float]
case x: Array[Char] => x(idx) = value.asInstanceOf[Char]
case x: Array[Byte] => x(idx) = value.asInstanceOf[Byte]
case x: Array[Short] => x(idx) = value.asInstanceOf[Short]
case x: Array[Boolean] => x(idx) = value.asInstanceOf[Boolean]
case x: Array[Unit] => x(idx) = value.asInstanceOf[Unit]
case null => throw new NullPointerException
}
}

/** Get generic array length */
@@ -1,5 +1,5 @@
9c9
<
<
---
> /* INSTRUMENTED VERSION */
51a52,59
@@ -1,6 +1,6 @@
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2006-2011, LAMP/EPFL **
** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
@@ -244,7 +244,7 @@ private static boolean equalsNumChar(java.lang.Number xn, java.lang.Character yc
* as yet have not.
*
* Note: Among primitives, Float.NaN != Float.NaN, but the boxed
* verisons are equal. This still needs reconciliation.
* versions are equal. This still needs reconciliation.
*/
public static int hashFromLong(java.lang.Long n) {
int iv = n.intValue();
@@ -258,6 +258,9 @@ public static int hashFromDouble(java.lang.Double n) {

long lv = n.longValue();
if (lv == dv) return java.lang.Long.valueOf(lv).hashCode();

float fv = n.floatValue();
if (fv == dv) return java.lang.Float.valueOf(fv).hashCode();
else return n.hashCode();
}
public static int hashFromFloat(java.lang.Float n) {
@@ -1,14 +1,15 @@
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */

/* INSTRUMENTED VERSION */

package scala.runtime
package scala
package runtime

import scala.collection.{ Seq, IndexedSeq, TraversableView, AbstractIterator }
import scala.collection.mutable.WrappedArray
@@ -17,6 +18,7 @@ import scala.collection.generic.{ Sorted }
import scala.reflect.{ ClassTag, classTag }
import scala.util.control.ControlThrowable
import scala.xml.{ Node, MetaData }
import java.lang.{ Class => jClass }

import java.lang.Double.doubleToLongBits
import java.lang.reflect.{ Modifier, Method => JMethod }
@@ -30,48 +32,41 @@ object ScalaRunTime {
def isArray(x: Any, atLevel: Int): Boolean =
x != null && isArrayClass(x.getClass, atLevel)

private def isArrayClass(clazz: Class[_], atLevel: Int): Boolean =
private def isArrayClass(clazz: jClass[_], atLevel: Int): Boolean =
clazz.isArray && (atLevel == 1 || isArrayClass(clazz.getComponentType, atLevel - 1))

def isValueClass(clazz: Class[_]) = clazz.isPrimitive()
def isTuple(x: Any) = x != null && tupleNames(x.getClass.getName)
def isValueClass(clazz: jClass[_]) = clazz.isPrimitive()

// includes specialized subclasses and future proofed against hypothetical TupleN (for N > 22)
def isTuple(x: Any) = x != null && x.getClass.getName.startsWith("scala.Tuple")
def isAnyVal(x: Any) = x match {
case _: Byte | _: Short | _: Char | _: Int | _: Long | _: Float | _: Double | _: Boolean | _: Unit => true
case _ => false
}
// Avoiding boxing which messes up the specialized tests. Don't ask.
private val tupleNames = {
var i = 22
var names: List[String] = Nil
while (i >= 1) {
names ::= ("scala.Tuple" + String.valueOf(i))
i -= 1
}
names.toSet
}

/** Return the class object representing an array with element class `clazz`.
*/
def arrayClass(clazz: Class[_]): Class[_] = {
def arrayClass(clazz: jClass[_]): jClass[_] = {
// newInstance throws an exception if the erasure is Void.TYPE. see SI-5680
if (clazz == java.lang.Void.TYPE) classOf[Array[Unit]]
else java.lang.reflect.Array.newInstance(clazz, 0).getClass
}

/** Return the class object representing elements in arrays described by a given schematic.
*/
def arrayElementClass(schematic: Any): Class[_] = schematic match {
case cls: Class[_] => cls.getComponentType
def arrayElementClass(schematic: Any): jClass[_] = schematic match {
case cls: jClass[_] => cls.getComponentType
case tag: ClassTag[_] => tag.runtimeClass
case _ => throw new UnsupportedOperationException("unsupported schematic %s (%s)".format(schematic, if (schematic == null) "null" else schematic.getClass))
case _ =>
throw new UnsupportedOperationException(s"unsupported schematic $schematic (${schematic.getClass})")
}

/** Return the class object representing an unboxed value type,
* e.g. classOf[int], not classOf[java.lang.Integer]. The compiler
* rewrites expressions like 5.getClass to come here.
*/
def anyValClass[T <: AnyVal : ClassTag](value: T): Class[T] =
classTag[T].runtimeClass.asInstanceOf[Class[T]]
def anyValClass[T <: AnyVal : ClassTag](value: T): jClass[T] =
classTag[T].runtimeClass.asInstanceOf[jClass[T]]

var arrayApplyCount = 0

@@ -93,11 +88,9 @@ object ScalaRunTime {
}
}

var arrayUpdateCount = 0

/** update generic array element */
def array_update(xs: AnyRef, idx: Int, value: Any): Unit = {
arrayUpdateCount += 1
arrayApplyCount += 1
xs match {
case x: Array[AnyRef] => x(idx) = value.asInstanceOf[AnyRef]
case x: Array[Int] => x(idx) = value.asInstanceOf[Int]
@@ -156,7 +149,7 @@ object ScalaRunTime {
dest
}

def toArray[T](xs: collection.Seq[T]) = {
def toArray[T](xs: scala.collection.Seq[T]) = {
val arr = new Array[AnyRef](xs.length)
var i = 0
for (x <- xs) {
@@ -179,39 +172,10 @@ object ScalaRunTime {
def checkInitialized[T <: AnyRef](x: T): T =
if (x == null) throw new UninitializedError else x

abstract class Try[+A] {
def Catch[B >: A](handler: PartialFunction[Throwable, B]): B
def Finally(fin: => Unit): A
}

def Try[A](block: => A): Try[A] = new Try[A] with Runnable {
private var result: A = _
private var exception: Throwable =
try { run() ; null }
catch {
case e: ControlThrowable => throw e // don't catch non-local returns etc
case e: Throwable => e
}

def run() { result = block }

def Catch[B >: A](handler: PartialFunction[Throwable, B]): B =
if (exception == null) result
else if (handler isDefinedAt exception) handler(exception)
else throw exception

def Finally(fin: => Unit): A = {
fin

if (exception == null) result
else throw exception
}
}

def _toString(x: Product): String =
x.productIterator.mkString(x.productPrefix + "(", ",", ")")

def _hashCode(x: Product): Int = scala.util.MurmurHash3.productHash(x)
def _hashCode(x: Product): Int = scala.util.hashing.MurmurHash3.productHash(x)

/** A helper for case classes. */
def typedProductIterator[T](x: Product): Iterator[T] = {
@@ -246,12 +210,12 @@ object ScalaRunTime {
// Note that these are the implementations called by ##, so they
// must not call ## themselves.

@inline def hash(x: Any): Int =
def hash(x: Any): Int =
if (x == null) 0
else if (x.isInstanceOf[java.lang.Number]) BoxesRunTime.hashFromNumber(x.asInstanceOf[java.lang.Number])
else x.hashCode

@inline def hash(dv: Double): Int = {
def hash(dv: Double): Int = {
val iv = dv.toInt
if (iv == dv) return iv

@@ -261,37 +225,37 @@ object ScalaRunTime {
val fv = dv.toFloat
if (fv == dv) fv.hashCode else dv.hashCode
}
@inline def hash(fv: Float): Int = {
def hash(fv: Float): Int = {
val iv = fv.toInt
if (iv == fv) return iv

val lv = fv.toLong
if (lv == fv) return hash(lv)
else fv.hashCode
}
@inline def hash(lv: Long): Int = {
def hash(lv: Long): Int = {
val low = lv.toInt
val lowSign = low >>> 31
val high = (lv >>> 32).toInt
low ^ (high + lowSign)
}
@inline def hash(x: Number): Int = runtime.BoxesRunTime.hashFromNumber(x)
def hash(x: Number): Int = runtime.BoxesRunTime.hashFromNumber(x)

// The remaining overloads are here for completeness, but the compiler
// inlines these definitions directly so they're not generally used.
@inline def hash(x: Int): Int = x
@inline def hash(x: Short): Int = x.toInt
@inline def hash(x: Byte): Int = x.toInt
@inline def hash(x: Char): Int = x.toInt
@inline def hash(x: Boolean): Int = if (x) true.hashCode else false.hashCode
@inline def hash(x: Unit): Int = 0
def hash(x: Int): Int = x
def hash(x: Short): Int = x.toInt
def hash(x: Byte): Int = x.toInt
def hash(x: Char): Int = x.toInt
def hash(x: Boolean): Int = if (x) true.hashCode else false.hashCode
def hash(x: Unit): Int = 0

/** A helper method for constructing case class equality methods,
* because existential types get in the way of a clean outcome and
* it's performing a series of Any/Any equals comparisons anyway.
* See ticket #2867 for specifics.
*/
def sameElements(xs1: collection.Seq[Any], xs2: collection.Seq[Any]) = xs1 sameElements xs2
def sameElements(xs1: scala.collection.Seq[Any], xs2: scala.collection.Seq[Any]) = xs1 sameElements xs2

/** Given any Scala value, convert it to a String.
*
@@ -358,7 +322,7 @@ object ScalaRunTime {
case x: String => if (x.head.isWhitespace || x.last.isWhitespace) "\"" + x + "\"" else x
case x if useOwnToString(x) => x.toString
case x: AnyRef if isArray(x) => arrayToString(x)
case x: collection.Map[_, _] => x.iterator take maxElements map mapInner mkString (x.stringPrefix + "(", ", ", ")")
case x: scala.collection.Map[_, _] => x.iterator take maxElements map mapInner mkString (x.stringPrefix + "(", ", ", ")")
case x: Iterable[_] => x.iterator take maxElements map inner mkString (x.stringPrefix + "(", ", ", ")")
case x: Traversable[_] => x take maxElements map inner mkString (x.stringPrefix + "(", ", ", ")")
case x: Product1[_] if isTuple(x) => "(" + inner(x._1) + ",)" // that special trailing comma
@@ -1,67 +1,10 @@
8a9,10
> /* INSTRUMENTED VERSION */
>
73a76,77
68a71,72
> var arrayApplyCount = 0
>
75,86c79,93
< def array_apply(xs: AnyRef, idx: Int): Any = xs match {
< case x: Array[AnyRef] => x(idx).asInstanceOf[Any]
< case x: Array[Int] => x(idx).asInstanceOf[Any]
< case x: Array[Double] => x(idx).asInstanceOf[Any]
< case x: Array[Long] => x(idx).asInstanceOf[Any]
< case x: Array[Float] => x(idx).asInstanceOf[Any]
< case x: Array[Char] => x(idx).asInstanceOf[Any]
< case x: Array[Byte] => x(idx).asInstanceOf[Any]
< case x: Array[Short] => x(idx).asInstanceOf[Any]
< case x: Array[Boolean] => x(idx).asInstanceOf[Any]
< case x: Array[Unit] => x(idx).asInstanceOf[Any]
< case null => throw new NullPointerException
---
> def array_apply(xs: AnyRef, idx: Int): Any = {
70a75
> arrayApplyCount += 1
87a93
> arrayApplyCount += 1
> xs match {
> case x: Array[AnyRef] => x(idx).asInstanceOf[Any]
> case x: Array[Int] => x(idx).asInstanceOf[Any]
> case x: Array[Double] => x(idx).asInstanceOf[Any]
> case x: Array[Long] => x(idx).asInstanceOf[Any]
> case x: Array[Float] => x(idx).asInstanceOf[Any]
> case x: Array[Char] => x(idx).asInstanceOf[Any]
> case x: Array[Byte] => x(idx).asInstanceOf[Any]
> case x: Array[Short] => x(idx).asInstanceOf[Any]
> case x: Array[Boolean] => x(idx).asInstanceOf[Any]
> case x: Array[Unit] => x(idx).asInstanceOf[Any]
> case null => throw new NullPointerException
> }
88a96,97
> var arrayUpdateCount = 0
>
90,101c99,113
< def array_update(xs: AnyRef, idx: Int, value: Any): Unit = xs match {
< case x: Array[AnyRef] => x(idx) = value.asInstanceOf[AnyRef]
< case x: Array[Int] => x(idx) = value.asInstanceOf[Int]
< case x: Array[Double] => x(idx) = value.asInstanceOf[Double]
< case x: Array[Long] => x(idx) = value.asInstanceOf[Long]
< case x: Array[Float] => x(idx) = value.asInstanceOf[Float]
< case x: Array[Char] => x(idx) = value.asInstanceOf[Char]
< case x: Array[Byte] => x(idx) = value.asInstanceOf[Byte]
< case x: Array[Short] => x(idx) = value.asInstanceOf[Short]
< case x: Array[Boolean] => x(idx) = value.asInstanceOf[Boolean]
< case x: Array[Unit] => x(idx) = value.asInstanceOf[Unit]
< case null => throw new NullPointerException
---
> def array_update(xs: AnyRef, idx: Int, value: Any): Unit = {
> arrayUpdateCount += 1
> xs match {
> case x: Array[AnyRef] => x(idx) = value.asInstanceOf[AnyRef]
> case x: Array[Int] => x(idx) = value.asInstanceOf[Int]
> case x: Array[Double] => x(idx) = value.asInstanceOf[Double]
> case x: Array[Long] => x(idx) = value.asInstanceOf[Long]
> case x: Array[Float] => x(idx) = value.asInstanceOf[Float]
> case x: Array[Char] => x(idx) = value.asInstanceOf[Char]
> case x: Array[Byte] => x(idx) = value.asInstanceOf[Byte]
> case x: Array[Short] => x(idx) = value.asInstanceOf[Short]
> case x: Array[Boolean] => x(idx) = value.asInstanceOf[Boolean]
> case x: Array[Unit] => x(idx) = value.asInstanceOf[Unit]
> case null => throw new NullPointerException
> }

0 comments on commit a19babc

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.