Skip to content

WiP Separate the scalalib from the Scala.js library. #4787

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Move the uniqueness cache of Symbol in a separate file.
This way, we have only one implementation for all the versions of
Scala. This will become more useful as we make its implementation
less trivial.

We also rename it back to `UniquenessCache`, which is the name it
has on the JVM, and reinstate the `Null` lower bound on `V`. There
was no reason to name it differently, and keeping the name may be
better for binary compatibility (even though it is `private[scala]`
and nobody should be using it). It is still different for the key
type, which is fixed to `String`.
  • Loading branch information
sjrd committed Oct 27, 2023
commit 781ff15847ffb2461753ff8c4b649e954fc32bdd
71 changes: 1 addition & 70 deletions scalalib/overrides-2.13.0/scala/Symbol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,77 +37,8 @@ final class Symbol private (val name: String) extends Serializable {
override def equals(other: Any) = this eq other.asInstanceOf[AnyRef]
}

// Modified to use Scala.js specific cache
object Symbol extends JSUniquenessCache[Symbol] {
object Symbol extends UniquenessCache[Symbol] {
override def apply(name: String): Symbol = super.apply(name)
protected def valueFromKey(name: String): Symbol = new Symbol(name)
protected def keyFromValue(sym: Symbol): Option[String] = Some(sym.name)
}

private[scala] abstract class JSUniquenessCache[V]
{
private val cache = js.Dictionary.empty[V]

protected def valueFromKey(k: String): V
protected def keyFromValue(v: V): Option[String]

def apply(name: String): V =
cache.getOrElseUpdate(name, valueFromKey(name))

def unapply(other: V): Option[String] = keyFromValue(other)
}

/** This is private so it won't appear in the library API, but
* abstracted to offer some hope of reusability. */
/* DELETED for Scala.js
private[scala] abstract class UniquenessCache[K >: js.String, V >: Null]
{

import java.lang.ref.WeakReference
import java.util.WeakHashMap
import java.util.concurrent.locks.ReentrantReadWriteLock

private[this] val rwl = new ReentrantReadWriteLock()
private[this] val rlock = rwl.readLock
private[this] val wlock = rwl.writeLock
private[this] val map = new WeakHashMap[K, WeakReference[V]]

protected def valueFromKey(k: K): V
protected def keyFromValue(v: V): Option[K]

def apply(name: K): V = {
def cached(): V = {
rlock.lock
try {
val reference = map get name
if (reference == null) null
else reference.get // will be null if we were gc-ed
}
finally rlock.unlock
}
def updateCache(): V = {
wlock.lock
try {
val res = cached()
if (res != null) res
else {
// If we don't remove the old String key from the map, we can
// wind up with one String as the key and a different String as
// the name field in the Symbol, which can lead to surprising GC
// behavior and duplicate Symbols. See scala/bug#6706.
map remove name
val sym = valueFromKey(name)
map.put(name, new WeakReference(sym))
sym
}
}
finally wlock.unlock
}

val res = cached()
if (res == null) updateCache()
else res
}
def unapply(other: V): Option[K] = keyFromValue(other)
}
*/
71 changes: 1 addition & 70 deletions scalalib/overrides-2.13.1/scala/Symbol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,77 +37,8 @@ final class Symbol private (val name: String) extends Serializable {
override def equals(other: Any) = this eq other.asInstanceOf[AnyRef]
}

// Modified to use Scala.js specific cache
object Symbol extends JSUniquenessCache[Symbol] {
object Symbol extends UniquenessCache[Symbol] {
override def apply(name: String): Symbol = super.apply(name)
protected def valueFromKey(name: String): Symbol = new Symbol(name)
protected def keyFromValue(sym: Symbol): Option[String] = Some(sym.name)
}

private[scala] abstract class JSUniquenessCache[V]
{
private val cache = js.Dictionary.empty[V]

protected def valueFromKey(k: String): V
protected def keyFromValue(v: V): Option[String]

def apply(name: String): V =
cache.getOrElseUpdate(name, valueFromKey(name))

def unapply(other: V): Option[String] = keyFromValue(other)
}

/** This is private so it won't appear in the library API, but
* abstracted to offer some hope of reusability. */
/* DELETED for Scala.js
private[scala] abstract class UniquenessCache[K >: js.String, V >: Null]
{

import java.lang.ref.WeakReference
import java.util.WeakHashMap
import java.util.concurrent.locks.ReentrantReadWriteLock

private[this] val rwl = new ReentrantReadWriteLock()
private[this] val rlock = rwl.readLock
private[this] val wlock = rwl.writeLock
private[this] val map = new WeakHashMap[K, WeakReference[V]]

protected def valueFromKey(k: K): V
protected def keyFromValue(v: V): Option[K]

def apply(name: K): V = {
def cached(): V = {
rlock.lock
try {
val reference = map get name
if (reference == null) null
else reference.get // will be null if we were gc-ed
}
finally rlock.unlock
}
def updateCache(): V = {
wlock.lock
try {
val res = cached()
if (res != null) res
else {
// If we don't remove the old String key from the map, we can
// wind up with one String as the key and a different String as
// the name field in the Symbol, which can lead to surprising GC
// behavior and duplicate Symbols. See scala/bug#6706.
map remove name
val sym = valueFromKey(name)
map.put(name, new WeakReference(sym))
sym
}
}
finally wlock.unlock
}

val res = cached()
if (res == null) updateCache()
else res
}
def unapply(other: V): Option[K] = keyFromValue(other)
}
*/
71 changes: 1 addition & 70 deletions scalalib/overrides-2.13.2/scala/Symbol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,77 +37,8 @@ final class Symbol private (val name: String) extends Serializable {
override def equals(other: Any) = this eq other.asInstanceOf[AnyRef]
}

// Modified to use Scala.js specific cache
object Symbol extends JSUniquenessCache[Symbol] {
object Symbol extends UniquenessCache[Symbol] {
override def apply(name: String): Symbol = super.apply(name)
protected def valueFromKey(name: String): Symbol = new Symbol(name)
protected def keyFromValue(sym: Symbol): Option[String] = Some(sym.name)
}

private[scala] abstract class JSUniquenessCache[V]
{
private val cache = js.Dictionary.empty[V]

protected def valueFromKey(k: String): V
protected def keyFromValue(v: V): Option[String]

def apply(name: String): V =
cache.getOrElseUpdate(name, valueFromKey(name))

def unapply(other: V): Option[String] = keyFromValue(other)
}

/** This is private so it won't appear in the library API, but
* abstracted to offer some hope of reusability. */
/* DELETED for Scala.js
private[scala] abstract class UniquenessCache[K >: js.String, V >: Null]
{

import java.lang.ref.WeakReference
import java.util.WeakHashMap
import java.util.concurrent.locks.ReentrantReadWriteLock

private[this] val rwl = new ReentrantReadWriteLock()
private[this] val rlock = rwl.readLock
private[this] val wlock = rwl.writeLock
private[this] val map = new WeakHashMap[K, WeakReference[V]]

protected def valueFromKey(k: K): V
protected def keyFromValue(v: V): Option[K]

def apply(name: K): V = {
def cached(): V = {
rlock.lock
try {
val reference = map get name
if (reference == null) null
else reference.get // will be null if we were gc-ed
}
finally rlock.unlock
}
def updateCache(): V = {
wlock.lock
try {
val res = cached()
if (res != null) res
else {
// If we don't remove the old String key from the map, we can
// wind up with one String as the key and a different String as
// the name field in the Symbol, which can lead to surprising GC
// behavior and duplicate Symbols. See scala/bug#6706.
map remove name
val sym = valueFromKey(name)
map.put(name, new WeakReference(sym))
sym
}
}
finally wlock.unlock
}

val res = cached()
if (res == null) updateCache()
else res
}
def unapply(other: V): Option[K] = keyFromValue(other)
}
*/
71 changes: 1 addition & 70 deletions scalalib/overrides-2.13/scala/Symbol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,77 +37,8 @@ final class Symbol private (val name: String) extends Serializable {
override def equals(other: Any) = this eq other.asInstanceOf[AnyRef]
}

// Modified to use Scala.js specific cache
object Symbol extends JSUniquenessCache[Symbol] {
object Symbol extends UniquenessCache[Symbol] {
override def apply(name: String): Symbol = super.apply(name)
protected def valueFromKey(name: String): Symbol = new Symbol(name)
protected def keyFromValue(sym: Symbol): Option[String] = Some(sym.name)
}

private[scala] abstract class JSUniquenessCache[V]
{
private val cache = js.Dictionary.empty[V]

protected def valueFromKey(k: String): V
protected def keyFromValue(v: V): Option[String]

def apply(name: String): V =
cache.getOrElseUpdate(name, valueFromKey(name))

def unapply(other: V): Option[String] = keyFromValue(other)
}

/** This is private so it won't appear in the library API, but
* abstracted to offer some hope of reusability. */
/* DELETED for Scala.js
private[scala] abstract class UniquenessCache[K >: js.String, V >: Null]
{

import java.lang.ref.WeakReference
import java.util.WeakHashMap
import java.util.concurrent.locks.ReentrantReadWriteLock

private[this] val rwl = new ReentrantReadWriteLock()
private[this] val rlock = rwl.readLock
private[this] val wlock = rwl.writeLock
private[this] val map = new WeakHashMap[K, WeakReference[V]]

protected def valueFromKey(k: K): V
protected def keyFromValue(v: V): Option[K]

def apply(name: K): V = {
def cached(): V = {
rlock.lock
try {
val reference = map get name
if (reference == null) null
else reference.get // will be null if we were gc-ed
}
finally rlock.unlock
}
def updateCache(): V = {
wlock.lock
try {
val res = cached()
if (res != null) res
else {
// If we don't remove the old String key from the map, we can
// wind up with one String as the key and a different String as
// the name field in the Symbol, which can lead to surprising GC
// behavior and duplicate Symbols. See scala/bug#6706.
map remove name
val sym = valueFromKey(name)
map.put(name, new WeakReference(sym))
sym
}
}
finally wlock.unlock
}

val res = cached()
if (res == null) updateCache()
else res
}
def unapply(other: V): Option[K] = keyFromValue(other)
}
*/
71 changes: 1 addition & 70 deletions scalalib/overrides/scala/Symbol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,77 +37,8 @@ final class Symbol private (val name: String) extends Serializable {
override def equals(other: Any) = this eq other.asInstanceOf[AnyRef]
}

// Modified to use Scala.js specific cache
object Symbol extends JSUniquenessCache[Symbol] {
object Symbol extends UniquenessCache[Symbol] {
override def apply(name: String): Symbol = super.apply(name)
protected def valueFromKey(name: String): Symbol = new Symbol(name)
protected def keyFromValue(sym: Symbol): Option[String] = Some(sym.name)
}

private[scala] abstract class JSUniquenessCache[V]
{
private val cache = js.Dictionary.empty[V]

protected def valueFromKey(k: String): V
protected def keyFromValue(v: V): Option[String]

def apply(name: String): V =
cache.getOrElseUpdate(name, valueFromKey(name))

def unapply(other: V): Option[String] = keyFromValue(other)
}

/** This is private so it won't appear in the library API, but
* abstracted to offer some hope of reusability. */
/* DELETED for Scala.js
private[scala] abstract class UniquenessCache[K >: js.String, V >: Null]
{

import java.lang.ref.WeakReference
import java.util.WeakHashMap
import java.util.concurrent.locks.ReentrantReadWriteLock

private[this] val rwl = new ReentrantReadWriteLock()
private[this] val rlock = rwl.readLock
private[this] val wlock = rwl.writeLock
private[this] val map = new WeakHashMap[K, WeakReference[V]]

protected def valueFromKey(k: K): V
protected def keyFromValue(v: V): Option[K]

def apply(name: K): V = {
def cached(): V = {
rlock.lock
try {
val reference = map get name
if (reference == null) null
else reference.get // will be null if we were gc-ed
}
finally rlock.unlock
}
def updateCache(): V = {
wlock.lock
try {
val res = cached()
if (res != null) res
else {
// If we don't remove the old String key from the map, we can
// wind up with one String as the key and a different String as
// the name field in the Symbol, which can lead to surprising GC
// behavior and duplicate Symbols. See scala/bug#6706.
map remove name
val sym = valueFromKey(name)
map.put(name, new WeakReference(sym))
sym
}
}
finally wlock.unlock
}

val res = cached()
if (res == null) updateCache()
else res
}
def unapply(other: V): Option[K] = keyFromValue(other)
}
*/
Loading