Skip to content

Commit ffdac7b

Browse files
committed
Merge '0.6.x' into 'master'.
2 parents 1525030 + 5f8ba2a commit ffdac7b

25 files changed

Lines changed: 266 additions & 84 deletions

File tree

compiler/src/main/scala/org/scalajs/nscplugin/GenJSCode.scala

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
5353
import jsDefinitions._
5454
import jsInterop.{jsNameOf, jsNativeLoadSpecOfOption, JSName}
5555

56-
import treeInfo.hasSynthCaseSymbol
56+
import treeInfo.{hasSynthCaseSymbol, StripCast}
5757

5858
import platform.isMaybeBoxed
5959

@@ -2061,6 +2061,23 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
20612061
}
20622062
}
20632063

2064+
/* !!! Copy-pasted from `CleanUp.scala` upstream and simplified with
2065+
* our `WrapArray` extractor.
2066+
*
2067+
* Replaces `Array(Predef.wrapArray(ArrayValue(...).$asInstanceOf[...]), <tag>)`
2068+
* with just `ArrayValue(...).$asInstanceOf[...]`
2069+
*
2070+
* See scala/bug#6611; we must *only* do this for literal vararg arrays.
2071+
*
2072+
* This is normally done by `cleanup` but it comes later than this phase.
2073+
*/
2074+
case Apply(appMeth, Apply(wrapRefArrayMeth, (arg @ StripCast(ArrayValue(_, _))) :: Nil) :: _ :: Nil)
2075+
if wrapRefArrayMeth.symbol == WrapArray.wrapRefArrayMethod && appMeth.symbol == ArrayModule_genericApply =>
2076+
genStatOrExpr(arg, isStat)
2077+
case Apply(appMeth, elem0 :: WrapArray(rest @ ArrayValue(elemtpt, _)) :: Nil)
2078+
if appMeth.symbol == ArrayModule_apply(elemtpt.tpe) =>
2079+
genStatOrExpr(treeCopy.ArrayValue(rest, rest.elemtpt, elem0 :: rest.elems), isStat)
2080+
20642081
case app: Apply =>
20652082
genApply(app, isStat)
20662083

@@ -5060,11 +5077,14 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
50605077
}
50615078

50625079
object WrapArray {
5063-
private val isWrapArray: Set[Symbol] = {
5064-
val wrapArrayModule =
5065-
if (hasNewCollections) ScalaRunTimeModule
5066-
else PredefModule
5080+
private val wrapArrayModule =
5081+
if (hasNewCollections) ScalaRunTimeModule
5082+
else PredefModule
50675083

5084+
val wrapRefArrayMethod: Symbol =
5085+
getMemberMethod(wrapArrayModule, nme.wrapRefArray)
5086+
5087+
private val isWrapArray: Set[Symbol] = {
50685088
Seq(
50695089
nme.wrapRefArray,
50705090
nme.wrapByteArray,

compiler/src/test/scala/org/scalajs/nscplugin/test/OptimizationTest.scala

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,45 @@ import org.scalajs.ir.{Trees => js, Types => jstpe}
2121
class OptimizationTest extends JSASTTest {
2222
import OptimizationTest._
2323

24+
@Test
25+
def testArrayApplyOptimization: Unit = {
26+
/* Make sure Array(...) is optimized away completely for several kinds
27+
* of data types, with both the generic overload and the ones specialized
28+
* for primitives.
29+
*/
30+
"""
31+
class A {
32+
val a = Array(5, 7, 9, -3)
33+
val b = Array("hello", "world")
34+
val c = Array('a', 'b')
35+
val d = Array(Nil)
36+
val e = Array(5.toByte, 7.toByte, 9.toByte, -3.toByte)
37+
}
38+
""".
39+
hasNot("any LoadModule of the scala.Array companion") {
40+
case js.LoadModule(jstpe.ClassRef("s_Array$")) =>
41+
}
42+
43+
/* Using [] with primitives produces suboptimal trees, which cannot be
44+
* optimized. We should improve this in the future, if possible. This is
45+
* particularly annoying for Byte and Short, as it means that we need to
46+
* write `.toByte` for every single element if we want the optimization to
47+
* kick in.
48+
*
49+
* Scala/JVM has the same limitation.
50+
*/
51+
"""
52+
class A {
53+
val a = Array[Int](5, 7, 9, -3)
54+
val b = Array[Byte](5, 7, 9, -3)
55+
}
56+
""".
57+
hasExactly(2, "calls to Array.apply methods") {
58+
case js.Apply(_, js.LoadModule(jstpe.ClassRef("s_Array$")), js.Ident(methodName, _), _)
59+
if methodName.startsWith("apply__") =>
60+
}
61+
}
62+
2463
@Test
2564
def testJSArrayApplyOptimization: Unit = {
2665
/* Make sure js.Array(...) is optimized away completely for several kinds

javalanglib/src/main/scala/java/lang/Boolean.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ final class Boolean private ()
4141
}
4242

4343
object Boolean {
44-
final val TYPE = classOf[scala.Boolean]
44+
final val TYPE = scala.Predef.classOf[scala.Boolean]
4545

4646
/* TRUE and FALSE are supposed to be vals. However, they are better
4747
* optimized as defs, because they end up being just the constant true and

javalanglib/src/main/scala/java/lang/Byte.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ final class Byte private () extends Number with Comparable[Byte] {
4545
}
4646

4747
object Byte {
48-
final val TYPE = classOf[scala.Byte]
48+
final val TYPE = scala.Predef.classOf[scala.Byte]
4949
final val SIZE = 8
5050
final val BYTES = 1
5151

javalanglib/src/main/scala/java/lang/Character.scala

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class Character private ()
4747
}
4848

4949
object Character {
50-
final val TYPE = classOf[scala.Char]
50+
final val TYPE = scala.Predef.classOf[scala.Char]
5151
final val MIN_VALUE = '\u0000'
5252
final val MAX_VALUE = '\uffff'
5353
final val SIZE = 16
@@ -114,10 +114,10 @@ object Character {
114114
}
115115

116116
@inline
117-
private[this] def getTypeLT256(codePoint: Int): scala.Byte =
117+
private[this] def getTypeLT256(codePoint: Int): Int =
118118
charTypesFirst256(codePoint)
119119

120-
private[this] def getTypeGE256(codePoint: Int): scala.Byte = {
120+
private[this] def getTypeGE256(codePoint: Int): Int = {
121121
// the idx is increased by 1 due to the differences in indexing
122122
// between charTypeIndices and charType
123123
val idx = Arrays.binarySearch(charTypeIndices, codePoint) + 1
@@ -448,8 +448,8 @@ object Character {
448448
//def getDirectionality(c: scala.Char): scala.Byte
449449

450450
/* Conversions */
451-
def toUpperCase(c: scala.Char): scala.Char = c.toString.toUpperCase()(0)
452-
def toLowerCase(c: scala.Char): scala.Char = c.toString.toLowerCase()(0)
451+
def toUpperCase(c: scala.Char): scala.Char = c.toString.toUpperCase().charAt(0)
452+
def toLowerCase(c: scala.Char): scala.Char = c.toString.toLowerCase().charAt(0)
453453
//def toTitleCase(c: scala.Char): scala.Char
454454
//def getNumericValue(c: scala.Char): Int
455455

@@ -508,7 +508,7 @@ object Character {
508508
// Based on Unicode 7.0.0
509509

510510
// Types of characters from 0 to 255
511-
private[this] lazy val charTypesFirst256 = Array[scala.Byte](15, 15, 15, 15,
511+
private[this] lazy val charTypesFirst256: Array[Int] = Array(15, 15, 15, 15,
512512
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
513513
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, 24, 24, 24, 26, 24, 24, 24,
514514
21, 22, 24, 25, 24, 20, 24, 24, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 24, 24, 25,
@@ -541,11 +541,11 @@ object Character {
541541
// .map(tup => tup._1 - tup._2)
542542
// val charTypes = indicesAndTypes.map(_._2)
543543
// println(charTypeIndicesDeltas.mkString(
544-
// "charTypeIndices: val deltas = Array[Int](", ", ", ")"))
545-
// println(charTypes.mkString("val charTypes = Array[scala.Byte](", ", ", ")"))
544+
// "charTypeIndices: val deltas = Array(", ", ", ")"))
545+
// println(charTypes.mkString("val charTypes = Array(", ", ", ")"))
546546
//
547-
private[this] lazy val charTypeIndices = {
548-
val deltas = Array[Int](257, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
547+
private[this] lazy val charTypeIndices: Array[Int] = {
548+
val deltas = Array(257, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
549549
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
550550
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1,
551551
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -695,7 +695,7 @@ object Character {
695695
uncompressDeltas(deltas)
696696
}
697697

698-
private[this] lazy val charTypes = Array[scala.Byte](1, 2, 1, 2, 1, 2,
698+
private[this] lazy val charTypes: Array[Int] = Array(1, 2, 1, 2, 1, 2,
699699
1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1,
700700
2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
701701
1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1,
@@ -859,8 +859,8 @@ object Character {
859859
// 0 :: isMirroredIndices.init).map(tup => tup._1 - tup._2)
860860
// println(isMirroredIndicesDeltas.mkString(
861861
// "isMirroredIndices: val deltas = Array[Int](", ", ", ")"))
862-
private[this] lazy val isMirroredIndices = {
863-
val deltas = Array[Int](40, 2, 18, 1, 1, 1, 28, 1, 1, 1, 29, 1, 1, 1,
862+
private[this] lazy val isMirroredIndices: Array[Int] = {
863+
val deltas = Array(40, 2, 18, 1, 1, 1, 28, 1, 1, 1, 29, 1, 1, 1,
864864
45, 1, 15, 1, 3710, 4, 1885, 2, 2460, 2, 10, 2, 54, 2, 14, 2, 177, 1,
865865
192, 4, 3, 6, 3, 1, 3, 2, 3, 4, 1, 4, 1, 1, 1, 1, 4, 9, 5, 1, 1, 18,
866866
5, 4, 9, 2, 1, 1, 1, 8, 2, 31, 2, 4, 5, 1, 9, 2, 2, 19, 5, 2, 9, 5, 2,
@@ -875,8 +875,14 @@ object Character {
875875
}
876876

877877
private[this] def uncompressDeltas(deltas: Array[Int]): Array[Int] = {
878-
for (i <- 1 until deltas.length)
879-
deltas(i) += deltas(i - 1)
878+
var acc = deltas(0)
879+
var i = 1
880+
val len = deltas.length
881+
while (i != len) {
882+
acc += deltas(i)
883+
deltas(i) = acc
884+
i += 1
885+
}
880886
deltas
881887
}
882888

@@ -887,7 +893,7 @@ object Character {
887893
* point mapping to digits from 0 to 9.
888894
*/
889895
private[this] lazy val nonASCIIZeroDigitCodePoints: Array[Int] = {
890-
Array[Int](0x660, 0x6f0, 0x7c0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xbe6,
896+
Array(0x660, 0x6f0, 0x7c0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xbe6,
891897
0xc66, 0xce6, 0xd66, 0xe50, 0xed0, 0xf20, 0x1040, 0x1090, 0x17e0,
892898
0x1810, 0x1946, 0x19d0, 0x1a80, 0x1a90, 0x1b50, 0x1bb0, 0x1c40, 0x1c50,
893899
0xa620, 0xa8d0, 0xa900, 0xa9d0, 0xaa50, 0xabf0, 0xff10, 0x104a0,

javalanglib/src/main/scala/java/lang/Class.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ final class Class[A] private (data0: Object) extends Object {
8585
@inline // optimize for the Unchecked case, where this becomes identity()
8686
def cast(obj: Object): A = {
8787
scala.scalajs.runtime.SemanticsUtils.asInstanceOfCheck(
88-
(this eq classOf[Nothing]) ||
8988
(obj != null && !isJSType && !isInstance(obj)),
9089
new ClassCastException("" + obj + " is not an instance of " + getName))
9190
obj.asInstanceOf[A]

javalanglib/src/main/scala/java/lang/Double.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ final class Double private () extends Number with Comparable[Double] {
6666
}
6767

6868
object Double {
69-
final val TYPE = classOf[scala.Double]
69+
final val TYPE = scala.Predef.classOf[scala.Double]
7070
final val POSITIVE_INFINITY = 1.0 / 0.0
7171
final val NEGATIVE_INFINITY = 1.0 / -0.0
7272
final val NaN = 0.0 / 0.0
@@ -186,7 +186,7 @@ object Double {
186186

187187
val mantissa =
188188
js.Dynamic.global.parseInt(truncatedMantissaStr, 16).asInstanceOf[scala.Double]
189-
assert(mantissa != 0.0 && mantissa != scala.Double.PositiveInfinity)
189+
// Assert: mantissa != 0.0 && mantissa != scala.Double.PositiveInfinity
190190

191191
val binaryExpDouble =
192192
js.Dynamic.global.parseInt(binaryExpStr, 10).asInstanceOf[scala.Double]

javalanglib/src/main/scala/java/lang/Enum.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ abstract class Enum[E <: Enum[E]] protected (_name: String, _ordinal: Int)
3030
override protected final def clone(): AnyRef =
3131
throw new CloneNotSupportedException("Enums are not cloneable")
3232

33-
final def compareTo(o: E): Int = _ordinal.compareTo(o.ordinal)
33+
final def compareTo(o: E): Int = Integer.compare(_ordinal, o.ordinal)
3434

3535
// Not implemented:
3636
// final def getDeclaringClass(): Class[E]

javalanglib/src/main/scala/java/lang/Float.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ final class Float private () extends Number with Comparable[Float] {
5050
}
5151

5252
object Float {
53-
final val TYPE = classOf[scala.Float]
53+
final val TYPE = scala.Predef.classOf[scala.Float]
5454
final val POSITIVE_INFINITY = 1.0f / 0.0f
5555
final val NEGATIVE_INFINITY = 1.0f / -0.0f
5656
final val NaN = 0.0f / 0.0f

javalanglib/src/main/scala/java/lang/FloatingPointBits.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,10 @@ private[lang] object FloatingPointBits {
215215

216216
val bias = (1 << (ebits-1)) - 1 // constant
217217

218-
if (v.isNaN) {
218+
if (Double.isNaN(v)) {
219219
// http://dev.w3.org/2006/webapi/WebIDL/#es-type-mapping
220220
(false, (1 << ebits) - 1, pow(2, fbits-1))
221-
} else if (v.isInfinite) {
221+
} else if (Double.isInfinite(v)) {
222222
(v < 0, (1 << ebits) - 1, 0.0)
223223
} else if (v == 0.0) {
224224
(1 / v == scala.Double.NegativeInfinity, 0, 0.0)

0 commit comments

Comments
 (0)