diff options
Diffstat (limited to 'library/src/dotty/runtime')
-rw-r--r-- | library/src/dotty/runtime/Arrays.scala | 31 | ||||
-rw-r--r-- | library/src/dotty/runtime/LazyHolders.scala | 44 | ||||
-rw-r--r-- | library/src/dotty/runtime/LazyVals.scala | 103 | ||||
-rw-r--r-- | library/src/dotty/runtime/LegacyApp.scala | 9 | ||||
-rw-r--r-- | library/src/dotty/runtime/vc/VCPrototype.scala | 486 |
5 files changed, 673 insertions, 0 deletions
diff --git a/library/src/dotty/runtime/Arrays.scala b/library/src/dotty/runtime/Arrays.scala new file mode 100644 index 000000000..9ec5512ad --- /dev/null +++ b/library/src/dotty/runtime/Arrays.scala @@ -0,0 +1,31 @@ +package dotty.runtime + +import scala.reflect.ClassTag + +import java.lang.{reflect => jlr} + +/** All but the first two operations should be short-circuited and implemented specially by + * the backend. + */ +object Arrays { + + // note: this class is magical. Do not touch it unless you know what you are doing.` + + /** Creates an array of some element type determined by the given `ClassTag` + * argument. The erased type of applications of this method is `Object`. + */ + def newGenericArray[T](length: Int)(implicit tag: ClassTag[T]): Array[T] = + tag.newArray(length) + + /** Convert a sequence to a Java array with element type given by `clazz`. */ + def seqToArray[T](xs: Seq[T], clazz: Class[_]): Array[T] = { + val arr = java.lang.reflect.Array.newInstance(clazz, xs.length).asInstanceOf[Array[T]] + xs.copyToArray(arr) + arr + } + + /** Create an array of a reference type T. + */ + def newArray[Arr](componentType: Class[_], returnType: Class[Arr], dimensions: Array[Int]): Arr = + jlr.Array.newInstance(componentType, dimensions: _*).asInstanceOf[Arr] +} diff --git a/library/src/dotty/runtime/LazyHolders.scala b/library/src/dotty/runtime/LazyHolders.scala new file mode 100644 index 000000000..1e31cda66 --- /dev/null +++ b/library/src/dotty/runtime/LazyHolders.scala @@ -0,0 +1,44 @@ +package dotty.runtime + +/** + * Classes used as holders for local lazy vals + */ +class LazyInt { + var value: Int = _ + @volatile var initialized: Boolean = false +} + +class LazyLong { + var value: Long = _ + @volatile var initialized: Boolean = false +} + +class LazyBoolean { + var value: Boolean = _ + @volatile var initialized: Boolean = false +} + +class LazyDouble { + var value: Double = _ + @volatile var initialized: Boolean = false +} + +class LazyByte { + var value: Byte = _ + @volatile var initialized: Boolean = false +} + +class LazyRef { + var value: AnyRef = _ + @volatile var initialized: Boolean = false +} + +class LazyShort { + var value: Short = _ + @volatile var initialized: Boolean = false +} + +class LazyChar { + var value: Char = _ + @volatile var initialized: Boolean = false +} diff --git a/library/src/dotty/runtime/LazyVals.scala b/library/src/dotty/runtime/LazyVals.scala new file mode 100644 index 000000000..4dea0d34d --- /dev/null +++ b/library/src/dotty/runtime/LazyVals.scala @@ -0,0 +1,103 @@ +package dotty.runtime + +import scala.annotation.tailrec + +/** + * Helper methods used in thread-safe lazy vals. + */ +object LazyVals { + private val unsafe = scala.concurrent.util.Unsafe.instance + + final val BITS_PER_LAZY_VAL = 2L + final val LAZY_VAL_MASK = 3L + final val debug = false + + @inline def STATE(cur: Long, ord: Int) = { + val r = (cur >> (ord * BITS_PER_LAZY_VAL)) & LAZY_VAL_MASK + if (debug) + println(s"STATE($cur, $ord) = $r") + r + } + @inline def CAS(t: Object, offset: Long, e: Long, v: Int, ord: Int) = { + if (debug) + println(s"CAS($t, $offset, $e, $v, $ord)") + val mask = ~(LAZY_VAL_MASK << ord * BITS_PER_LAZY_VAL) + val n = (e & mask) | (v << (ord * BITS_PER_LAZY_VAL)) + compareAndSet(t, offset, e, n) + } + @inline def setFlag(t: Object, offset: Long, v: Int, ord: Int) = { + if (debug) + println(s"setFlag($t, $offset, $v, $ord)") + var retry = true + while (retry) { + val cur = get(t, offset) + if (STATE(cur, ord) == 1) retry = CAS(t, offset, cur, v, ord) + else { + // cur == 2, somebody is waiting on monitor + if (CAS(t, offset, cur, v, ord)) { + val monitor = getMonitor(t, ord) + monitor.synchronized { + monitor.notifyAll() + } + retry = false + } + } + } + } + @inline def wait4Notification(t: Object, offset: Long, cur: Long, ord: Int) = { + if (debug) + println(s"wait4Notification($t, $offset, $cur, $ord)") + var retry = true + while (retry) { + val cur = get(t, offset) + val state = STATE(cur, ord) + if (state == 1) CAS(t, offset, cur, 2, ord) + else if (state == 2) { + val monitor = getMonitor(t, ord) + monitor.synchronized { + monitor.wait() + } + } + else retry = false + } + } + + @inline def compareAndSet(t: Object, off: Long, e: Long, v: Long) = unsafe.compareAndSwapLong(t, off, e, v) + @inline def get(t: Object, off: Long) = { + if (debug) + println(s"get($t, $off)") + unsafe.getLongVolatile(t, off) + } + + val processors: Int = java.lang.Runtime.getRuntime.availableProcessors() + val base: Int = 8 * processors * processors + val monitors: Array[Object] = (0 to base).map { + x => new Object() + }.toArray + + @inline def getMonitor(obj: Object, fieldId: Int = 0) = { + var id = ( + /*java.lang.System.identityHashCode(obj) + */ // should be here, but #548 + fieldId) % base + + if (id < 0) id += base + monitors(id) + } + + @inline def getOffset(clz: Class[_], name: String) = { + val r = unsafe.objectFieldOffset(clz.getDeclaredField(name)) + if (debug) + println(s"getOffset($clz, $name) = $r") + r + } + + object Names { + final val state = "STATE" + final val cas = "CAS" + final val setFlag = "setFlag" + final val wait4Notification = "wait4Notification" + final val compareAndSet = "compareAndSet" + final val get = "get" + final val getOffset = "getOffset" + } +} diff --git a/library/src/dotty/runtime/LegacyApp.scala b/library/src/dotty/runtime/LegacyApp.scala new file mode 100644 index 000000000..2c4b295d0 --- /dev/null +++ b/library/src/dotty/runtime/LegacyApp.scala @@ -0,0 +1,9 @@ +package dotty.runtime + + +/** + * replaces the `scala.App` class which relies on `DelayedInit` functionality, not supported by Dotty. + */ +class LegacyApp { + def main(args: Array[String]): Unit = () +} diff --git a/library/src/dotty/runtime/vc/VCPrototype.scala b/library/src/dotty/runtime/vc/VCPrototype.scala new file mode 100644 index 000000000..212046ef8 --- /dev/null +++ b/library/src/dotty/runtime/vc/VCPrototype.scala @@ -0,0 +1,486 @@ +package dotty.runtime.vc + +import scala.reflect.ClassTag + +abstract class VCPrototype { +} + + +abstract class VCArrayPrototype[T <: VCPrototype] extends Object with Cloneable { + def apply(idx: Int): Object + def update(idx: Int, el: T): Unit + def length: Int + override def clone(): Object = super.clone() +} + + +abstract class VCFloatPrototype(val underlying: Float) extends VCPrototype {} + +abstract class VCFloatCasePrototype(underlying: Float) extends VCFloatPrototype(underlying) with Product1[Float] { + + final def _1: Float = underlying + + override final def hashCode(): Int = { + underlying.hashCode() + } + + override final def toString: String = { + s"$productPrefix($underlying)" + } +} + +abstract class VCFloatCompanion[T <: VCFloatPrototype] extends ClassTag[T] { + def box(underlying: Float): T + final def unbox(boxed: T) = boxed.underlying + + implicit def classTag: this.type = this + override def newArray(len: Int): Array[T] = + new VCFloatArray(this, len).asInstanceOf[Array[T]] + + + final def _1$extension(underlying: Float) = underlying + final def hashCode$extension(underlying: Float) = underlying.hashCode() + final def toString$extension(underlying: Float) = s"${productPrefix$extension(underlying)}($underlying)" + def productPrefix$extension(underlying: Float): String +} + +final class VCFloatArray[T <: VCFloatPrototype] private (val arr: Array[Float], val ct: VCFloatCompanion[T]) + extends VCArrayPrototype[T] { + def this(ct: VCFloatCompanion[T], sz: Int) = + this(new Array[Float](sz), ct) + + def apply(idx: Int) = + ct.box(arr(idx)) + def update(idx: Int, elem: T) = + arr(idx) = ct.unbox(elem) + def length: Int = arr.length + + override def clone(): VCFloatArray[T] = { + new VCFloatArray[T](arr.clone(), ct) + } + + override def toString: String = { + "[" + ct.runtimeClass + } +} + + +abstract class VCObjectPrototype(val underlying: Object) extends VCPrototype {} + +abstract class VCObjectCasePrototype(underlying: Object) extends VCObjectPrototype(underlying) with Product1[Object] { + + final def _1: Object = underlying + + override final def hashCode(): Int = { + underlying.hashCode() + } + + override final def toString: String = { + s"$productPrefix($underlying)" + } +} + +abstract class VCObjectCompanion[T <: VCObjectPrototype] extends ClassTag[T] { + def box(underlying: Object): T + final def unbox(boxed: T) = boxed.underlying + + implicit def classTag: this.type = this + override def newArray(len: Int): Array[T] = + new VCObjectArray(this, len).asInstanceOf[Array[T]] + + + final def _1$extension(underlying: Object) = underlying + final def hashCode$extension(underlying: Object) = underlying.hashCode() + final def toString$extension(underlying: Object) = s"${productPrefix$extension(underlying)}($underlying)" + def productPrefix$extension(underlying: Object): String +} + +final class VCObjectArray[T <: VCObjectPrototype] private (val arr: Array[Object], val ct: VCObjectCompanion[T]) + extends VCArrayPrototype[T] { + def this(ct: VCObjectCompanion[T], sz: Int) = + this(new Array[Object](sz), ct) + + def apply(idx: Int) = + ct.box(arr(idx)) + + def update(idx: Int, elem: T) = + arr(idx) = ct.unbox(elem) + + def length: Int = arr.length + + override def clone(): VCObjectArray[T] = { + new VCObjectArray[T](arr.clone(), ct) + } + + override def toString: String = { + "[" + ct.runtimeClass + } +} + + +abstract class VCShortPrototype(val underlying: Short) extends VCPrototype {} + +abstract class VCShortCasePrototype(underlying: Short) extends VCShortPrototype(underlying) with Product1[Short] { + + final def _1: Short = underlying + + override final def hashCode(): Int = { + underlying.hashCode() + } + + override final def toString: String = { + s"$productPrefix($underlying)" + } +} + +abstract class VCShortCompanion[T <: VCShortPrototype] extends ClassTag[T] { + def box(underlying: Short): T + final def unbox(boxed: T) = boxed.underlying + + implicit def classTag: this.type = this + override def newArray(len: Int): Array[T] = + new VCShortArray(this, len).asInstanceOf[Array[T]] + + + final def _1$extension(underlying: Short) = underlying + final def hashCode$extension(underlying: Short) = underlying.hashCode() + final def toString$extension(underlying: Short) = s"${productPrefix$extension(underlying)}($underlying)" + def productPrefix$extension(underlying: Short): String +} + +final class VCShortArray[T <: VCShortPrototype] private (val arr: Array[Short], val ct: VCShortCompanion[T]) + extends VCArrayPrototype[T] { + def this(ct: VCShortCompanion[T], sz: Int) = + this(new Array[Short](sz), ct) + + def apply(idx: Int) = + ct.box(arr(idx)) + + def update(idx: Int, elem: T) = + arr(idx) = ct.unbox(elem) + + def length: Int = arr.length + + override def clone(): VCShortArray[T] = { + new VCShortArray[T](arr.clone(), ct) + } + + override def toString: String = { + "[" + ct.runtimeClass + } + +} + + +abstract class VCLongPrototype(val underlying: Long) extends VCPrototype {} + +abstract class VCLongCasePrototype(underlying: Long) extends VCLongPrototype(underlying) with Product1[Long] { + + final def _1: Long = underlying + + override final def hashCode(): Int = { + underlying.hashCode() + } + + override final def toString: String = { + s"$productPrefix($underlying)" + } +} + +abstract class VCLongCompanion[T <: VCLongPrototype] extends ClassTag[T] { + def box(underlying: Long): T + final def unbox(boxed: T) = boxed.underlying + + implicit def classTag: this.type = this + override def newArray(len: Int): Array[T] = + new VCLongArray(this, len).asInstanceOf[Array[T]] + + + final def _1$extension(underlying: Long) = underlying + final def hashCode$extension(underlying: Long) = underlying.hashCode() + final def toString$extension(underlying: Long) = s"${productPrefix$extension(underlying)}($underlying)" + def productPrefix$extension(underlying: Long): String +} + +final class VCLongArray[T <: VCLongPrototype] private (val arr: Array[Long], val ct: VCLongCompanion[T]) + extends VCArrayPrototype[T] { + def this(ct: VCLongCompanion[T], sz: Int) = + this(new Array[Long](sz), ct) + + def apply(idx: Int) = + ct.box(arr(idx)) + + def update(idx: Int, elem: T) = + arr(idx) = ct.unbox(elem) + + def length: Int = arr.length + + override def clone(): VCLongArray[T] = { + new VCLongArray[T](arr.clone(), ct) + } + + override def toString: String = { + "[" + ct.runtimeClass + } +} + + +abstract class VCIntPrototype(val underlying: Int) extends VCPrototype {} + +abstract class VCIntCasePrototype(underlying: Int) extends VCIntPrototype(underlying) with Product1[Int] { + + final def _1: Int = underlying + + override final def hashCode(): Int = { + underlying.hashCode() + } + + override final def toString: String = { + s"$productPrefix($underlying)" + } +} + +abstract class VCIntCompanion[T <: VCIntPrototype] extends ClassTag[T] { + def box(underlying: Int): T + final def unbox(boxed: T) = boxed.underlying + + implicit def classTag: this.type = this + override def newArray(len: Int): Array[T] = + new VCIntArray(this, len).asInstanceOf[Array[T]] + + + final def _1$extension(underlying: Int) = underlying + final def hashCode$extension(underlying: Int) = underlying.hashCode() + final def toString$extension(underlying: Int) = s"${productPrefix$extension(underlying)}($underlying)" + def productPrefix$extension(underlying: Int): String +} + +final class VCIntArray[T <: VCIntPrototype] private (val arr: Array[Int], val ct: VCIntCompanion[T]) + extends VCArrayPrototype[T] { + def this(ct: VCIntCompanion[T], sz: Int) = + this(new Array[Int](sz), ct) + + def apply(idx: Int) = + ct.box(arr(idx)) + def update(idx: Int, elem: T) = + arr(idx) = ct.unbox(elem) + def length: Int = arr.length + + override def clone(): VCIntArray[T] = { + new VCIntArray[T](arr.clone(), ct) + } + + override def toString: String = { + "[" + ct.runtimeClass + } +} + + +abstract class VCDoublePrototype(val underlying: Double) extends VCPrototype {} + +abstract class VCDoubleCasePrototype(underlying: Double) extends VCDoublePrototype(underlying) with Product1[Double] { + + final def _1: Double = underlying + + override final def hashCode(): Int = { + underlying.hashCode() + } + + override final def toString: String = { + s"$productPrefix($underlying)" + } +} + +abstract class VCDoubleCompanion[T <: VCDoublePrototype] extends ClassTag[T] { + def box(underlying: Double): T + final def unbox(boxed: T) = boxed.underlying + + implicit def classTag: this.type = this + override def newArray(len: Int): Array[T] = + new VCDoubleArray(this, len).asInstanceOf[Array[T]] + + + final def _1$extension(underlying: Double) = underlying + final def hashCode$extension(underlying: Double) = underlying.hashCode() + final def toString$extension(underlying: Double) = s"${productPrefix$extension(underlying)}($underlying)" + def productPrefix$extension(underlying: Double): String +} + +final class VCDoubleArray[T <: VCDoublePrototype] private (val arr: Array[Double], val ct: VCDoubleCompanion[T]) + extends VCArrayPrototype[T] { + def this(ct: VCDoubleCompanion[T], sz: Int) = + this(new Array[Double](sz), ct) + + def apply(idx: Int) = + ct.box(arr(idx)) + def update(idx: Int, elem: T) = + arr(idx) = ct.unbox(elem) + def length: Int = arr.length + + override def clone(): VCDoubleArray[T] = { + new VCDoubleArray[T](arr.clone(), ct) + } + + override def toString: String = { + "[" + ct.runtimeClass + } +} + + +abstract class VCBooleanPrototype(val underlying: Boolean) extends VCPrototype {} + +abstract class VCBooleanCasePrototype(underlying: Boolean) extends VCBooleanPrototype(underlying) with Product1[Boolean] { + + final def _1: Boolean = underlying + + override final def hashCode(): Int = { + underlying.hashCode() + } + + override final def toString: String = { + s"$productPrefix($underlying)" + } +} + +abstract class VCBooleanCompanion[T <: VCBooleanPrototype] extends ClassTag[T] { + def box(underlying: Boolean): T + final def unbox(boxed: T) = boxed.underlying + + implicit def classTag: this.type = this + override def newArray(len: Int): Array[T] = + new VCBooleanArray(this, len).asInstanceOf[Array[T]] + + + final def _1$extension(underlying: Boolean) = underlying + final def hashCode$extension(underlying: Boolean) = underlying.hashCode() + final def toString$extension(underlying: Boolean) = s"${productPrefix$extension(underlying)}($underlying)" + def productPrefix$extension(underlying: Boolean): String +} + +final class VCBooleanArray[T <: VCBooleanPrototype] private (val arr: Array[Boolean], val ct: VCBooleanCompanion[T]) + extends VCArrayPrototype[T] { + def this(ct: VCBooleanCompanion[T], sz: Int) = + this(new Array[Boolean](sz), ct) + + def apply(idx: Int) = + ct.box(arr(idx)) + + def update(idx: Int, elem: T) = + arr(idx) = ct.unbox(elem) + + def length: Int = arr.length + + override def clone(): VCBooleanArray[T] = { + new VCBooleanArray[T](arr.clone(), ct) + } + + override def toString: String = { + "[" + ct.runtimeClass + } +} + + +abstract class VCCharPrototype(val underlying: Char) extends VCPrototype {} + +abstract class VCCharCasePrototype(underlying: Char) extends VCCharPrototype(underlying) with Product1[Char] { + + final def _1: Char = underlying + + override final def hashCode(): Int = { + underlying.hashCode() + } + + override final def toString: String = { + s"$productPrefix($underlying)" + } + + // subclasses are expected to implement equals, productPrefix, and canEqual +} + +abstract class VCCharCompanion[T <: VCCharPrototype] extends ClassTag[T] { + def box(underlying: Char): T + final def unbox(boxed: T) = boxed.underlying + + implicit def classTag: this.type = this + override def newArray(len: Int): Array[T] = + new VCCharArray(this, len).asInstanceOf[Array[T]] + + + final def _1$extension(underlying: Char) = underlying + final def hashCode$extension(underlying: Char) = underlying.hashCode() + final def toString$extension(underlying: Char) = s"${productPrefix$extension(underlying)}($underlying)" + def productPrefix$extension(underlying: Char): String +} + +final class VCCharArray[T <: VCCharPrototype] private (val arr: Array[Char], val ct: VCCharCompanion[T]) + extends VCArrayPrototype[T] { + def this(ct: VCCharCompanion[T], sz: Int) = + this(new Array[Char](sz), ct) + + def apply(idx: Int) = + ct.box(arr(idx)) + def update(idx: Int, elem: T) = + arr(idx) = ct.unbox(elem) + def length: Int = arr.length + + override def clone(): VCCharArray[T] = { + new VCCharArray[T](arr.clone(), ct) + } + + override def toString: String = { + "[" + ct.runtimeClass + } +} + + +abstract class VCBytePrototype(val underlying: Byte) extends VCPrototype {} + +abstract class VCByteCasePrototype(underlying: Byte) extends VCBytePrototype(underlying) with Product1[Byte] { + + final def _1: Byte = underlying + + override final def hashCode(): Int = { + underlying.hashCode() + } + + override final def toString: String = { + s"$productPrefix($underlying)" + } +} + +abstract class VCByteCompanion[T <: VCBytePrototype] extends ClassTag[T] { + def box(underlying: Byte): T + final def unbox(boxed: T) = boxed.underlying + + implicit def classTag: this.type = this + override def newArray(len: Int): Array[T] = + new VCByteArray(this, len).asInstanceOf[Array[T]] + + + final def _1$extension(underlying: Byte) = underlying + final def hashCode$extension(underlying: Byte) = underlying.hashCode() + final def toString$extension(underlying: Byte) = s"${productPrefix$extension(underlying)}($underlying)" + def productPrefix$extension(underlying: Byte): String +} + +final class VCByteArray[T <: VCBytePrototype] private (val arr: Array[Byte], val ct: VCByteCompanion[T]) + extends VCArrayPrototype[T] { + def this(ct: VCByteCompanion[T], sz: Int) = + this(new Array[Byte](sz), ct) + + def apply(idx: Int) = + ct.box(arr(idx)) + def update(idx: Int, elem: T) = + arr(idx) = ct.unbox(elem) + def length: Int = arr.length + + override def clone(): VCByteArray[T] = { + new VCByteArray[T](arr.clone(), ct) + } + + override def toString: String = { + "[" + ct.runtimeClass + } + +} + |