8000 Merge pull request #4998 from sjrd/primitive-jl-class-operations · scala-js/scala-js@48b179d · GitHub
[go: up one dir, main page]

Skip to content

Commit 48b179d

Browse files
authored
Merge pull request #4998 from sjrd/primitive-jl-class-operations
Replace the JS object given to jl.Class by primitive IR operations.
2 parents b699082 + e0fff46 commit 48b179d

Some content is hidden

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

43 files changed

+1214
-892
lines changed

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

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,15 +2188,45 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
21882188
isJSFunctionDef(currentClassSym)) {
21892189
val flags = js.MemberFlags.empty.withNamespace(namespace)
21902190
val body = {
2191+
def genAsUnaryOp(op: js.UnaryOp.Code): js.Tree =
2192+
js.UnaryOp(op, genThis())
2193+
def genAsBinaryOp(op: js.BinaryOp.Code): js.Tree =
2194+
js.BinaryOp(op, genThis(), jsParams.head.ref)
2195+
def genAsBinaryOpRhsNotNull(op: js.BinaryOp.Code): js.Tree =
2196+
js.BinaryOp(op, genThis(), js.UnaryOp(js.UnaryOp.CheckNotNull, jsParams.head.ref))
2197+
21912198
if (currentClassSym.get == HackedStringClass) {
21922199
/* Hijack the bodies of String.length and String.charAt and replace
21932200
* them with String_length and String_charAt operations, respectively.
21942201
*/
21952202
methodName.name match {
2196-
case `lengthMethodName` =>
2197-
js.UnaryOp(js.UnaryOp.String_length, genThis())
2198-
case `charAtMethodName` =>
2199-
js.BinaryOp(js.BinaryOp.String_charAt, genThis(), jsParams.head.ref)
2203+
case `lengthMethodName` => genAsUnaryOp(js.UnaryOp.String_length)
2204+
case `charAtMethodName` => genAsBinaryOp(js.BinaryOp.String_charAt)
2205+
case _ => genBody()
2206+
}
2207+
} else if (currentClassSym.get == ClassClass) {
2208+
// Similar, for the Class_x operations
2209+
methodName.name match {
2210+
case `getNameMethodName` => genAsUnaryOp(js.UnaryOp.Class_name)
2211+
case `isPrimitiveMethodName` => genAsUnaryOp(js.UnaryOp.Class_isPrimitive)
2212+
case `isInterfaceMethodName` => genAsUnaryOp(js.UnaryOp.Class_isInterface)
2213+
case `isArrayMethodName` => genAsUnaryOp(js.UnaryOp.Class_isArray)
2214+
case `getComponentTypeMethodName` => genAsUnaryOp(js.UnaryOp.Class_componentType)
2215+
case `getSuperclassMethodName` => genAsUnaryOp(js.UnaryOp.Class_superClass)
2216+
2217+
case `isInstanceMethodName` => genAsBinaryOp(js.BinaryOp.Class_isInstance)
2218+
case `isAssignableFromMethodName` => genAsBinaryOpRhsNotNull(js.BinaryOp.Class_isAssignableFrom)
2219+
case `castMethodName` => genAsBinaryOp(js.BinaryOp.Class_cast)
2220+
2221+
case _ => genBody()
2222+
}
2223+
} else if (currentClassSym.get == JavaLangReflectArrayModClass) {
2224+
methodName.name match {
2225+
case `arrayNewInstanceMethodName` =>
2226+
val List(jlClassParam, lengthParam) = jsParams
2227+
js.BinaryOp(js.BinaryOp.Class_newArray,
2228+
js.UnaryOp(js.UnaryOp.CheckNotNull, jlClassParam.ref),
2229+
lengthParam.ref)
22002230
case _ =>
22012231
genBody()
22022232
}
@@ -3644,12 +3674,11 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
36443674
*/
36453675
def genNewArray(arrayTypeRef: jstpe.ArrayTypeRef, arguments: List[js.Tree])(
36463676
implicit pos: Position): js.Tree = {
3647-
assert(arguments.length <= arrayTypeRef.dimensions,
3648-
"too many arguments for array constructor: found " + arguments.length +
3649-
" but array has only " + arrayTypeRef.dimensions +
3650-
" dimension(s)")
3677+
assert(arguments.size == 1,
3678+
"expected exactly 1 argument for array constructor: found " +
3679+ s"${arguments.length} at $pos")
36513680

3652-
js.NewArray(arrayTypeRef, arguments)
3681+
js.NewArray(arrayTypeRef, arguments.head)
36533682
}
36543683

36553684
/** Gen JS code for an array literal. */
@@ -7084,6 +7113,32 @@ private object GenJSCode {
70847113
private val charAtMethodName =
70857114
MethodName("charAt", List(jstpe.IntRef), jstpe.CharRef)
70867115

7116+
private val getNameMethodName =
7117+
MethodName("getName", Nil, jstpe.ClassRef(ir.Names.BoxedStringClass))
7118+
private val isPrimitiveMethodName =
7119+
MethodName("isPrimitive", Nil, jstpe.BooleanRef)
7120+
private val isInterfaceMethodName =
7121+
MethodName("isInterface", Nil, jstpe.BooleanRef)
7122+
private val isArrayMethodName =
7123+
MethodName("isArray", Nil, jstpe.BooleanRef)
7124+
private val getComponentTypeMethodName =
7125+
MethodName("getComponentType", Nil, jstpe.ClassRef(ir.Names.ClassClass))
7126+
private val getSuperclassMethodName =
7127+
MethodName("getSuperclass", Nil, jstpe.ClassRef(ir.Names.ClassClass))
7128+
7129+
private val isInstanceMethodName =
7130+
MethodName("isInstance", List(jstpe.ClassRef(ir.Names.ObjectClass)), jstpe.BooleanRef)
7131+
private val isAssignableFromMethodName =
7132+
MethodName("isAssignableFrom", List(jstpe.ClassRef(ir.Names.ClassClass)), jstpe.BooleanRef)
7133+
private val castMethodName =
7134+
MethodName("cast", List(jstpe.ClassRef(ir.Names.ObjectClass)), jstpe.ClassRef(ir.Names.ObjectClass))
7135+
7136+
private val arrayNewInstanceMethodName = {
7137+
MethodName("newInstance",
7138+
List(jstpe.ClassRef(ir.Names.ClassClass), jstpe.IntRef),
7139+
jstpe.ClassRef(ir.Names.ObjectClass))
7140+
}
7141+
70877142
private val thisOriginalName = OriginalName("this")
70887143

70897144
private object BlockOrAlone {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ trait JSDefinitions {
3737

3838
lazy val JavaLangVoidClass = getRequiredClass("java.lang.Void")
3939

40+
lazy val JavaLangReflectArrayModClass = getModuleIfDefined("java.lang.reflect.Array").moduleClass
41+
4042
lazy val BoxedUnitModClass = BoxedUnitModule.moduleClass
4143

4244
lazy val ScalaJSJSPackageModule = getPackageObject("scala.scalajs.js")

ir/shared/src/main/scala/org/scalajs/ir/Hashers.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,10 +321,10 @@ object Hashers {
321321
mixTree(lhs)
322322
mixTree(rhs)
323323

324-
case NewArray(typeRef, lengths) =>
324+
case NewArray(typeRef, length) =>
325325
mixTag(TagNewArray)
326326
mixArrayTypeRef(typeRef)
327-
mixTrees(lengths)
327+
mixTrees(length :: Nil) // mixed as a list for historical reasons
328328

329329
case ArrayValue(typeRef, elems) =>
330330
mixTag(TagArrayValue)

ir/shared/src/main/scala/org/scalajs/ir/Printers.scala

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,14 @@ object Printers {
371371
} else {
372372
print(lhs)
373373
print((op: @switch) match {
374-
case String_length => ".length"
375-
case CheckNotNull => ".notNull"
374+
case String_length => ".length"
375+
case CheckNotNull => ".notNull"
376+
case Class_name => ".name"
377+
case Class_isPrimitive => ".isPrimitive"
378+
case Class_isInterface => ".isInterface"
379+
case Class_isArray => ".isArray"
380+
case Class_componentType => ".componentType"
381+
case Class_superClass => ".superClass"
376382
})
377383
}
378384

@@ -413,6 +419,19 @@ object Printers {
413419
print(rhs)
414420
print(']')
415421

422+
case BinaryOp(op, lhs, rhs) if BinaryOp.isClassOp(op) =>
423+
import BinaryOp._
424+
print((op: @switch) match {
425+
case Class_isInstance => "isInstance("
426+
case Class_isAssignableFrom => "isAssignableFrom("
427+
case Class_cast => "cast("
428+
case Class_newArray => "newArray("
429+
})
430+
print(lhs)
431+
print(", ")
432+
print(rhs)
433+
print(')')
434+
416435
case BinaryOp(op, lhs, rhs) =>
417436
import BinaryOp._
418437
print('(')
@@ -492,15 +511,13 @@ object Printers {
492511
print(rhs)
493512
print(')')
494513

495-
case NewArray(typeRef, lengths) =>
514+
case NewArray(typeRef, length) =>
496515
print("new ")
497516
print(typeRef.base)
498-
for (length <- lengths) {
499-
print('[')
500-
print(length)
501-
print(']')
502-
}
503-
for (dim <- lengths.size until typeRef.dimensions)
517+
print('[')
518+
print(length)
519+
print(']')
520+
for (dim <- 1 until typeRef.dimensions)
504521
print("[]")
505522

506523
case ArrayValue(typeRef, elems) =>

0 commit comments

Comments
 (0)
0