Skip to content

Commit ce44ce8

Browse files
committed
Add Scaladoc for undocumented scala.runtime APIs
Documents declarations that had no doc comment at all across scala.runtime: the boxed and unboxed value-class runtime support, the array and tuple helpers, and the 87 files of scala.runtime.java8 that back Java function interop. Comment-only: no declaration, body, import, annotation or blank line is touched.
1 parent 190abc3 commit ce44ce8

119 files changed

Lines changed: 3912 additions & 7 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

library/src/scala/runtime/ArrayCharSequence.scala

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,53 @@ import scala.language.`2.13`
1717

1818
// Still need this one since the implicit class ArrayCharSequence only converts
1919
// a single argument.
20+
/** A `CharSequence` view of a slice of an `Array[Char]`.
21+
*
22+
* The sequence consists of the characters of `xs` from index `start` until
23+
* `end`. Characters are read from the array on demand, so later writes to
24+
* the array are visible through this sequence. The bounds are not validated
25+
* on construction: `end <= start` yields an empty sequence, and out-of-range
26+
* bounds only surface when characters are accessed.
27+
*
28+
* @param xs the underlying character array
29+
* @param start the index in `xs` of the first character of the sequence
30+
* @param end the index in `xs` one past the last character of the sequence
31+
*/
2032
final class ArrayCharSequence(val xs: Array[Char], start: Int, end: Int) extends CharSequence {
2133
// yikes
2234
// java.lang.VerifyError: (class: scala/runtime/ArrayCharSequence, method: <init> signature: ([C)V)
2335
// Constructor must call super() or this()
2436
//
2537
// def this(xs: Array[Char]) = this(xs, 0, xs.length)
2638

39+
/** Returns the number of characters in this sequence: `end - start`, or `0` if `end <= start`. */
2740
def length: Int = math.max(0, end - start)
41+
/** Returns the character at the given index of this sequence, that is, the
42+
* character at index `start + index` of the underlying array.
43+
*
44+
* @param index the index of the character to return, from `0` to `length - 1`
45+
* @throws ArrayIndexOutOfBoundsException if `index` is negative or not less
46+
* than `length` (the exception message reports the bounds of the
47+
* underlying array, not of this sequence)
48+
*/
2849
def charAt(index: Int): Char = {
2950
if (0 <= index && index < length)
3051
xs(start + index)
3152
else throw new ArrayIndexOutOfBoundsException(s"$index is out of bounds (min 0, max ${xs.length - 1})")
3253
}
54+
/** Returns a new `ArrayCharSequence` over the characters of this sequence
55+
* from index `start0` until `end0`.
56+
*
57+
* The result is a view over the same underlying array; no characters are
58+
* copied.
59+
*
60+
* @param start0 the index in this sequence of the first character of the subsequence
61+
* @param end0 the index in this sequence one past the last character of the subsequence
62+
* @return the subsequence view; empty if `end0 <= start0` (no exception is
63+
* thrown for an inverted range, unlike the `CharSequence` contract)
64+
* @throws ArrayIndexOutOfBoundsException if `start0` is negative or `end0`
65+
* is greater than `length`
66+
*/
3367
def subSequence(start0: Int, end0: Int): CharSequence = {
3468
if (start0 < 0) throw new ArrayIndexOutOfBoundsException(s"$start0 is out of bounds (min 0, max ${length -1})")
3569
else if (end0 > length) throw new ArrayIndexOutOfBoundsException(s"$end0 is out of bounds (min 0, max ${xs.length -1})")
@@ -40,6 +74,13 @@ final class ArrayCharSequence(val xs: Array[Char], start: Int, end: Int) extends
4074
new ArrayCharSequence(xs, start1, start1 + newlen)
4175
}
4276
}
77+
/** Returns the characters of this sequence as a `String`.
78+
*
79+
* The bounds are clamped to the underlying array before copying: a
80+
* negative `start` is treated as `0` and the end is capped at the array's
81+
* length, so a sequence constructed with out-of-range bounds yields its
82+
* in-range characters (or the empty string) rather than throwing.
83+
*/
4384
override def toString() = {
4485
val start = math.max(this.start, 0)
4586
val end = math.min(xs.length, start + length)

library/src/scala/runtime/ClassValueCompat.scala

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,78 @@ private[scala] abstract class ClassValueCompat[T] extends ClassValueInterface[T]
2121
else new FallbackClassValue()
2222

2323
private class JavaClassValue extends ClassValue[T] with ClassValueInterface[T] {
24+
/** Computes the value for `cls` by delegating to the enclosing
25+
* `ClassValueCompat`'s `computeValue`; `java.lang.ClassValue` caches
26+
* the result per class.
27+
*
28+
* @param cls the class to compute the value for
29+
* @return the computed value
30+
*/
2431
override def computeValue(cls: Class[?]): T = self.computeValue(cls)
2532
}
2633

2734
private class FallbackClassValue extends ClassValueInterface[T] {
35+
/** Returns the value for `cls`, computed by the enclosing
36+
* `ClassValueCompat`'s `computeValue` on every call: the fallback
37+
* caches nothing.
38+
*
39+
* @param cls the class to compute the value for
40+
*/
2841
override def get(cls: Class[?]): T = self.computeValue(cls)
2942

43+
/** Does nothing: the fallback caches no values, so there is nothing to
44+
* remove.
45+
*
46+
* @param cls never used
47+
*/
3048
override def remove(cls: Class[?]): Unit = {}
3149
}
3250

51+
/** Returns the value associated with `cls`: when `java.lang.ClassValue`
52+
* is available, from its per-class cache, computed by `computeValue` on
53+
* first access; otherwise by calling `computeValue` on every call.
54+
*
55+
* @param cls the class to get the value for
56+
*/
3357
def get(cls: Class[?]): T = instance.get(cls)
3458

59+
/** Removes the cached value for `cls`, so that the next `get` recomputes
60+
* it; does nothing when `java.lang.ClassValue` is unavailable, since
61+
* nothing is cached then.
62+
*
63+
* @param cls the class whose cached value to remove
64+
*/
3565
def remove(cls: Class[?]): Unit = instance.remove(cls)
3666

67+
/** Computes the value to associate with `cls`.
68+
*
69+
* Called by `get`: when backed by `java.lang.ClassValue`, on the first
70+
* access for each class (and again after `remove`); otherwise on every
71+
* call.
72+
*
73+
* @param cls the class to compute the value for
74+
* @return the value to associate with `cls`
75+
*/
3776
protected def computeValue(cls: Class[?]): T
3877
}
3978

4079
private[scala] object ClassValueCompat {
80+
/** A common interface over `java.lang.ClassValue` and the non-caching
81+
* fallback used on runtimes where that class cannot be loaded.
82+
*
83+
* @tparam T the type of the value derived from a class
84+
*/
4185
trait ClassValueInterface[T] {
86+
/** Returns the value for `cls`, computing it if necessary.
87+
*
88+
* @param cls the class to get the value for
89+
*/
4290
def get(cls: Class[?]): T
4391

92+
/** Removes any cached value for `cls`.
93+
*
94+
* @param cls the class whose cached value to remove
95+
*/
4496
def remove(cls: Class[?]): Unit
4597
}
4698

library/src/scala/runtime/EnumValue.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,27 @@ package scala.runtime
33
import language.experimental.captureChecking
44

55
transparent trait EnumValue extends Product, Serializable:
6+
/** Returns `true` if `that` is the same object as this one, by reference.
7+
*
8+
* Each simple enum case is a singleton, so it can only compare equal to
9+
* itself.
10+
*
11+
* @param that the value to compare with this enum value
12+
*/
613
override def canEqual(that: Any) = this eq that.asInstanceOf[AnyRef]
14+
/** Returns `0`: a simple enum case has no case fields. */
715
override def productArity: Int = 0
16+
/** Always throws: a simple enum case has no elements.
17+
*
18+
* @param n the index of the requested element; no index is valid
19+
* @throws IndexOutOfBoundsException always, with `n` as its message
20+
*/
821
override def productElement(n: Int): Any =
922
throw IndexOutOfBoundsException(n.toString)
23+
/** Always throws: a simple enum case has no elements.
24+
*
25+
* @param n the index of the requested element name; no index is valid
26+
* @throws IndexOutOfBoundsException always, with `n` as its message
27+
*/
1028
override def productElementName(n: Int): String =
1129
throw IndexOutOfBoundsException(n.toString)

library/src/scala/runtime/FunctionXXL.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ trait FunctionXXL {
1212
*/
1313
def apply(xs: IArray[Object]): Object
1414

15+
/** Returns the string `"<functionXXL>"`, mirroring the `"<functionN>"` rendering of the `Function0` to `Function22` traits. */
1516
override def toString() = "<functionXXL>"
1617
}

library/src/scala/runtime/LambdaDeserialize.scala

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ import scala.collection.immutable
2020

2121
import scala.language.`2.13`
2222

23+
/** The per-class state behind the synthetic `$deserializeLambda$` method of
24+
* a class hosting lambdas: the class's lookup, a map from implementation
25+
* method name-and-descriptor keys to their method handles, and a cache of
26+
* deserialization factories keyed the same way.
27+
*
28+
* Created by `LambdaDeserialize.bootstrap`, which the JVM invokes via
29+
* `invokedynamic`.
30+
*/
2331
final class LambdaDeserialize private (lookup: MethodHandles.Lookup, targetMethods: Array[MethodHandle]) {
2432
private val targetMethodMap: util.HashMap[String, MethodHandle] = new util.HashMap[String, MethodHandle](targetMethods.length)
2533

@@ -31,16 +39,47 @@ final class LambdaDeserialize private (lookup: MethodHandles.Lookup, targetMetho
3139

3240
private val cache = new util.HashMap[String, MethodHandle]
3341

42+
/** Returns an instance of the functional interface described by
43+
* `serialized`, delegating to [[LambdaDeserializer.deserializeLambda]]
44+
* with this instance's lookup, factory cache, and target method map.
45+
*
46+
* @param serialized the serialized form of the lambda to deserialize
47+
* @throws IllegalArgumentException if the implementation method named by
48+
* `serialized` is not among this instance's target methods
49+
*/
3450
def deserializeLambda(serialized: SerializedLambda): AnyRef = LambdaDeserializer.deserializeLambda(lookup, cache, targetMethodMap, serialized)
3551
}
3652

3753
object LambdaDeserialize {
54+
/** Bootstrap method that the JVM invokes, via the `invokedynamic`
55+
* instruction in the synthetic `$deserializeLambda$` method of a class
56+
* hosting lambdas, to link that method's call site.
57+
*
58+
* @param lookup the lookup of the class hosting the lambdas
59+
* @param invokedName never used
60+
* @param invokedType the type the call site's target is adapted to,
61+
* taking a `SerializedLambda` and returning the
62+
* deserialized object
63+
* @param targetMethods handles for the lambda implementation methods of
64+
* the class, from which deserialization requests
65+
* are resolved by name and descriptor
66+
* @return a `ConstantCallSite` whose target is `deserializeLambda` bound
67+
* to a `LambdaDeserialize` built over `lookup` and
68+
* `targetMethods`
69+
*/
3870
@varargs @throws[Throwable]
3971
def bootstrap(lookup: MethodHandles.Lookup, invokedName: String, invokedType: MethodType, targetMethods: MethodHandle*): CallSite = {
4072
val targetMethodsArray = targetMethods.asInstanceOf[immutable.ArraySeq[?]].unsafeArray.asInstanceOf[Array[MethodHandle]]
4173
val exact = MethodHandleConstants.LAMBDA_DESERIALIZE_DESERIALIZE_LAMBDA.bindTo(new LambdaDeserialize(lookup, targetMethodsArray)).asType(invokedType)
4274
new ConstantCallSite(exact)
4375
}
4476

77+
/** Returns the key under which an implementation method is stored in the
78+
* target method map and factory cache: `name` concatenated with
79+
* `descriptor`.
80+
*
81+
* @param name the name of the implementation method
82+
* @param descriptor the JVM method descriptor of its signature
83+
*/
4584
def nameAndDescriptorKey(name: String, descriptor: String): String = name + descriptor
4685
}

library/src/scala/runtime/LambdaDeserializer.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,21 @@ object LambdaDeserializer {
5151
else result
5252
}
5353

54+
/** Deserializes a lambda like [[deserializeLambda]], but returns `null`
55+
* instead of throwing when the implementation method named by
56+
* `serialized` has no entry in `targetMethodMap`.
57+
*
58+
* @param lookup The factory for method handles. Must have access to the implementation method, the
59+
* functional interface class, and `java.io.Serializable`.
60+
* @param cache A cache used to avoid spinning up a class for each deserialization of a given lambda. May be `null`
61+
* @param targetMethodMap a mapping from lambda implementation method name and signature keys (as produced by
62+
* `LambdaDeserialize.nameAndDescriptorKey`) to their `MethodHandle`s, used to look up the
63+
* implementation method during deserialization. Must not be `null`
64+
* @param serialized The lambda to deserialize. Note that this is typically created by the `readResolve`
65+
* member of the anonymous class created by `LambdaMetaFactory`.
66+
* @return an instance of the functional interface, or `null` if the implementation
67+
* method is not found in `targetMethodMap`
68+
*/
5469
def deserializeLambdaOrNull(lookup: MethodHandles.Lookup, cache: java.util.Map[String, MethodHandle],
5570
targetMethodMap: java.util.Map[String, MethodHandle], serialized: SerializedLambda): AnyRef | Null = {
5671
assert(targetMethodMap != null)

0 commit comments

Comments
 (0)