Skip to content

Commit c5725e7

Browse files
committed
Make lazy vals and object native image friendly
Currently, creating a graal native image from scala 3 code is really cubersome, custom configuration needs to be provided for each object and lazy val. It is caused by reflection in LazyVals object. This PR inlines reflection within each class and in this form Graal is able to inline such calls without any additional config.
1 parent 6f3fe05 commit c5725e7

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

compiler/src/dotty/tools/dotc/transform/LazyVals.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
382382
val thizClass = Literal(Constant(claz.info))
383383
val helperModule = requiredModule("scala.runtime.LazyVals")
384384
val getOffset = Select(ref(helperModule), lazyNme.RLazyVals.getOffset)
385+
val getOffsetStatic = Select(ref(helperModule), lazyNme.RLazyVals.getOffsetStatic)
385386
var offsetSymbol: TermSymbol | Null = null
386387
var flag: Tree = EmptyTree
387388
var ord = 0
@@ -406,7 +407,8 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
406407
val flagName = LazyBitMapName.fresh(id.toString.toTermName)
407408
val flagSymbol = newSymbol(claz, flagName, containerFlags, defn.LongType).enteredAfter(this)
408409
flag = ValDef(flagSymbol, Literal(Constant(0L)))
409-
val offsetTree = ValDef(offsetSymbol.nn, getOffset.appliedTo(thizClass, Literal(Constant(flagName.toString))))
410+
val fieldTree = thizClass.select(lazyNme.RLazyVals.getDeclaredField).appliedTo(Literal(Constant(flagName.toString)))
411+
val offsetTree = ValDef(offsetSymbol.nn, getOffsetStatic.appliedTo(fieldTree))
410412
info.defs = offsetTree :: info.defs
411413
}
412414

@@ -416,7 +418,8 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
416418
val flagName = LazyBitMapName.fresh("0".toTermName)
417419
val flagSymbol = newSymbol(claz, flagName, containerFlags, defn.LongType).enteredAfter(this)
418420
flag = ValDef(flagSymbol, Literal(Constant(0L)))
419-
val offsetTree = ValDef(offsetSymbol.nn, getOffset.appliedTo(thizClass, Literal(Constant(flagName.toString))))
421+
val fieldTree = thizClass.select(lazyNme.RLazyVals.getDeclaredField).appliedTo(Literal(Constant(flagName.toString)))
422+
val offsetTree = ValDef(offsetSymbol.nn, getOffsetStatic.appliedTo(fieldTree))
420423
appendOffsetDefs += (claz -> new OffsetInfo(List(offsetTree), ord))
421424
}
422425

@@ -453,6 +456,8 @@ object LazyVals {
453456
val state: TermName = N.state.toTermName
454457
val cas: TermName = N.cas.toTermName
455458
val getOffset: TermName = N.getOffset.toTermName
459+
val getOffsetStatic: TermName = "getOffsetStatic".toTermName
460+
val getDeclaredField: TermName = "getDeclaredField".toTermName
456461
}
457462
val flag: TermName = "flag".toTermName
458463
val state: TermName = "state".toTermName

library/src/scala/runtime/LazyVals.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ object LazyVals {
106106
r
107107
}
108108

109+
def getOffsetStatic(field: java.lang.reflect.Field) =
110+
val r = unsafe.objectFieldOffset(field)
111+
if (debug)
112+
println(s"getOffset(${field.getDeclaringClass}, ${field.getName}) = $r")
113+
r
114+
115+
109116
object Names {
110117
final val state = "STATE"
111118
final val cas = "CAS"

0 commit comments

Comments
 (0)