Skip to content
This repository was archived by the owner on Jul 12, 2024. It is now read-only.

Commit 02494ac

Browse files
committed
Implement support for classOf.
Including elementary support of methods of `java.lang.Class`. We implement this in a way that is similar to the JavaScript back-end: we have an internal `typeData` structure, which contains the raw metadata that will be needed by a `java.lang.Class` instance. It also contains a lazily evaluated pointer to the unique `java.lang.Class` and the `typeData` of an array of that type. If we need the `typeData` of a multi-dimensional array, we follow the chain of `arrayOf` pointers. The name is initially stored as an `(array u16)` so that it can be initialized as a constant expression in globals. The `string` value is lazily initialized from that raw data the first time it is requested. This machinery requires quite a bit of run-time helper functions. These are hard-coded in `HelperFunctions.scala`. Again, this is similar to the JS back-end, which defines a bunch of helper JS functions in its `CoreJSLib.scala`. The `typeData` of classes that have a `vtable` are inserted into the `vtable` itself, making the latter a subtype of `typeData`. This is done in anticipation of the support for `GetClass`: it will be able to fetch the `vtable` field of the object as the `typeData` from which to extract the `java.lang.Class` instance. The `typeData` of other classes are stored as independent globals.
1 parent 0852f41 commit 02494ac

File tree

13 files changed

+898
-30
lines changed

13 files changed

+898
-30
lines changed

Diff for: cli/src/main/scala/TestSuites.scala

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ object TestSuites {
88
TestSuite("testsuite.core.VirtualDispatch"),
99
TestSuite("testsuite.core.InterfaceCall"),
1010
TestSuite("testsuite.core.AsInstanceOfTest"),
11+
TestSuite("testsuite.core.ClassOfTest"),
1112
TestSuite("testsuite.core.JSInteropTest"),
1213
TestSuite("testsuite.core.HijackedClassesDispatchTest"),
1314
TestSuite("testsuite.core.HijackedClassesMonoTest"),

Diff for: loader.mjs

+3
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ const scalaJSHelpers = {
6161
tF: (x) => typeof x === 'number' && (Math.fround(x) === x || x !== x),
6262
tD: (x) => typeof x === 'number',
6363

64+
// Closure
65+
closure: (f, data) => f.bind(void 0, data),
66+
6467
// Strings
6568
emptyString: () => "",
6669
stringLength: (s) => s.length,

Diff for: test-suite/src/main/scala/testsuite/Assert.scala

+3
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,7 @@ package testsuite
1414
object Assert {
1515
def ok(cond: Boolean): Unit =
1616
if (!cond) null.toString() // Apply to Null should compile to unreachable
17+
18+
def assertSame(expected: Any, actual: Any): Unit =
19+
ok(expected.asInstanceOf[AnyRef] eq actual.asInstanceOf[AnyRef])
1720
}
+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package testsuite.core
2+
3+
import testsuite.Assert.ok
4+
import testsuite.Assert
5+
6+
object ClassOfTest {
7+
def main(): Unit = {
8+
testGetName()
9+
testUniqueness()
10+
testIsPrimitive()
11+
testIsInterface()
12+
testIsArray()
13+
testGetComponentType()
14+
}
15+
16+
def testGetName(): Unit = {
17+
Assert.assertSame("java.lang.String", classOf[String].getName())
18+
Assert.assertSame("java.lang.StringBuilder", classOf[java.lang.StringBuilder].getName())
19+
Assert.assertSame("int", classOf[Int].getName())
20+
Assert.assertSame("void", classOf[Unit].getName())
21+
22+
Assert.assertSame("[Ljava.lang.Object;", classOf[Array[AnyRef]].getName())
23+
Assert.assertSame("[Ljava.lang.String;", classOf[Array[String]].getName())
24+
Assert.assertSame("[[Ljava.lang.CharSequence;", classOf[Array[Array[CharSequence]]].getName())
25+
26+
Assert.assertSame("[Z", classOf[Array[Boolean]].getName())
27+
Assert.assertSame("[C", classOf[Array[Char]].getName())
28+
Assert.assertSame("[B", classOf[Array[Byte]].getName())
29+
Assert.assertSame("[S", classOf[Array[Short]].getName())
30+
Assert.assertSame("[I", classOf[Array[Int]].getName())
31+
Assert.assertSame("[J", classOf[Array[Long]].getName())
32+
Assert.assertSame("[F", classOf[Array[Float]].getName())
33+
Assert.assertSame("[D", classOf[Array[Double]].getName())
34+
}
35+
36+
def testUniqueness(): Unit = {
37+
Assert.assertSame(classOf[String], classOf[String])
38+
Assert.assertSame(classOf[java.lang.StringBuilder], classOf[java.lang.StringBuilder])
39+
Assert.assertSame(classOf[CharSequence], classOf[CharSequence])
40+
Assert.assertSame(classOf[Int], classOf[Int])
41+
42+
Assert.assertSame(classOf[Array[Int]], classOf[Array[Int]])
43+
Assert.assertSame(classOf[Array[Array[java.lang.Byte]]], classOf[Array[Array[java.lang.Byte]]])
44+
Assert.assertSame(classOf[Array[Array[Int]]], classOf[Array[Array[Int]]])
45+
}
46+
47+
def testIsPrimitive(): Unit = {
48+
Assert.assertSame(false, classOf[AnyRef].isPrimitive())
49+
Assert.assertSame(false, classOf[String].isPrimitive())
50+
Assert.assertSame(false, classOf[CharSequence].isPrimitive())
51+
Assert.assertSame(false, classOf[java.lang.Iterable[Any]].isPrimitive())
52+
Assert.assertSame(false, classOf[Array[Int]].isPrimitive())
53+
Assert.assertSame(false, classOf[Array[String]].isPrimitive())
54+
Assert.assertSame(false, classOf[Array[CharSequence]].isPrimitive())
55+
56+
Assert.assertSame(true, classOf[Int].isPrimitive())
57+
Assert.assertSame(true, classOf[Unit].isPrimitive())
58+
}
59+
60+
def testIsInterface(): Unit = {
61+
Assert.assertSame(false, classOf[AnyRef].isInterface())
62+
Assert.assertSame(false, classOf[String].isInterface())
63+
Assert.assertSame(false, classOf[Int].isInterface())
64+
Assert.assertSame(false, classOf[Array[Int]].isInterface())
65+
Assert.assertSame(false, classOf[Array[String]].isInterface())
66+
Assert.assertSame(false, classOf[Array[CharSequence]].isInterface())
67+
68+
Assert.assertSame(true, classOf[CharSequence].isInterface())
69+
Assert.assertSame(true, classOf[java.lang.Iterable[Any]].isInterface())
70+
}
71+
72+
def testIsArray(): Unit = {
73+
Assert.assertSame(false, classOf[AnyRef].isArray())
74+
Assert.assertSame(false, classOf[String].isArray())
75+
Assert.assertSame(false, classOf[Int].isArray())
76+
Assert.assertSame(false, classOf[CharSequence].isArray())
77+
Assert.assertSame(false, classOf[java.lang.Iterable[Any]].isArray())
78+
79+
Assert.assertSame(true, classOf[Array[Int]].isArray())
80+
Assert.assertSame(true, classOf[Array[String]].isArray())
81+
Assert.assertSame(true, classOf[Array[CharSequence]].isArray())
82+
}
83+
84+
def testGetComponentType(): Unit = {
85+
Assert.assertSame(null, classOf[AnyRef].getComponentType())
86+
Assert.assertSame(null, classOf[String].getComponentType())
87+
Assert.assertSame(null, classOf[Int].getComponentType())
88+
Assert.assertSame(null, classOf[CharSequence].getComponentType())
89+
Assert.assertSame(null, classOf[java.lang.Iterable[Any]].getComponentType())
90+
91+
Assert.assertSame(classOf[Int], classOf[Array[Int]].getComponentType())
92+
Assert.assertSame(classOf[String], classOf[Array[String]].getComponentType())
93+
Assert.assertSame(classOf[AnyRef], classOf[Array[AnyRef]].getComponentType())
94+
95+
Assert.assertSame(
96+
classOf[Array[CharSequence]],
97+
classOf[Array[Array[CharSequence]]].getComponentType()
98+
)
99+
100+
Assert.assertSame(
101+
classOf[Array[Long]],
102+
classOf[Array[Array[Long]]].getComponentType()
103+
)
104+
105+
Assert.assertSame(
106+
classOf[Array[Array[java.lang.Byte]]],
107+
classOf[Array[Array[Array[java.lang.Byte]]]].getComponentType()
108+
)
109+
110+
Assert.assertSame(
111+
classOf[Array[ClassForUniqueGetComponentTypeTest]].getComponentType(),
112+
classOf[Array[ClassForUniqueGetComponentTypeTest]].getComponentType()
113+
)
114+
}
115+
116+
class ClassForUniqueGetComponentTypeTest
117+
}

Diff for: wasm/src/main/scala/Compiler.scala

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import wasm.ir2wasm._
44
import wasm.wasm4s._
55

66
import org.scalajs.ir
7-
import org.scalajs.ir.Trees._
8-
import org.scalajs.ir.Types._
7+
import org.scalajs.ir.{Names => IRNames}
98

109
import org.scalajs.linker.interface._
1110
import org.scalajs.linker.standard._
@@ -46,6 +45,7 @@ object Compiler {
4645
*/
4746
val factory = SymbolRequirement.factory("wasm")
4847
val symbolRequirements = factory.multiple(
48+
factory.instantiateClass(IRNames.ClassClass, SpecialNames.ClassCtor),
4949
factory.instantiateClass(SpecialNames.CharBoxClass, SpecialNames.CharBoxCtor),
5050
factory.instantiateClass(SpecialNames.LongBoxClass, SpecialNames.LongBoxCtor)
5151
)
@@ -70,6 +70,8 @@ object Compiler {
7070

7171
Preprocessor.preprocess(sortedClasses)(context)
7272
println("preprocessed")
73+
HelperFunctions.genGlobalHelpers()
74+
builder.genPrimitiveTypeDataGlobals()
7375
sortedClasses.foreach { clazz =>
7476
builder.transformClassDef(clazz)
7577
}

0 commit comments

Comments
 (0)