From 6ace38eaf4ccfdada4655e37b9d3e1d0dd353039 Mon Sep 17 00:00:00 2001 From: Krzysztof Romanowski Date: Fri, 25 Mar 2022 23:06:04 +0100 Subject: [PATCH 1/2] 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. --- compiler/src/dotty/tools/dotc/transform/LazyVals.scala | 9 +++++++-- library/src/scala/runtime/LazyVals.scala | 7 +++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index e72874dfaadd..74874843b4f6 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -382,6 +382,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { val thizClass = Literal(Constant(claz.info)) val helperModule = requiredModule("scala.runtime.LazyVals") val getOffset = Select(ref(helperModule), lazyNme.RLazyVals.getOffset) + val getOffsetStatic = Select(ref(helperModule), lazyNme.RLazyVals.getOffsetStatic) var offsetSymbol: TermSymbol | Null = null var flag: Tree = EmptyTree var ord = 0 @@ -406,7 +407,8 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { val flagName = LazyBitMapName.fresh(id.toString.toTermName) val flagSymbol = newSymbol(claz, flagName, containerFlags, defn.LongType).enteredAfter(this) flag = ValDef(flagSymbol, Literal(Constant(0L))) - val offsetTree = ValDef(offsetSymbol.nn, getOffset.appliedTo(thizClass, Literal(Constant(flagName.toString)))) + val fieldTree = thizClass.select(lazyNme.RLazyVals.getDeclaredField).appliedTo(Literal(Constant(flagName.toString))) + val offsetTree = ValDef(offsetSymbol.nn, getOffsetStatic.appliedTo(fieldTree)) info.defs = offsetTree :: info.defs } @@ -416,7 +418,8 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer { val flagName = LazyBitMapName.fresh("0".toTermName) val flagSymbol = newSymbol(claz, flagName, containerFlags, defn.LongType).enteredAfter(this) flag = ValDef(flagSymbol, Literal(Constant(0L))) - val offsetTree = ValDef(offsetSymbol.nn, getOffset.appliedTo(thizClass, Literal(Constant(flagName.toString)))) + val fieldTree = thizClass.select(lazyNme.RLazyVals.getDeclaredField).appliedTo(Literal(Constant(flagName.toString))) + val offsetTree = ValDef(offsetSymbol.nn, getOffsetStatic.appliedTo(fieldTree)) appendOffsetDefs += (claz -> new OffsetInfo(List(offsetTree), ord)) } @@ -453,6 +456,8 @@ object LazyVals { val state: TermName = N.state.toTermName val cas: TermName = N.cas.toTermName val getOffset: TermName = N.getOffset.toTermName + val getOffsetStatic: TermName = "getOffsetStatic".toTermName + val getDeclaredField: TermName = "getDeclaredField".toTermName } val flag: TermName = "flag".toTermName val state: TermName = "state".toTermName diff --git a/library/src/scala/runtime/LazyVals.scala b/library/src/scala/runtime/LazyVals.scala index 85ca4f5cb3a0..f3fe52beb9ee 100644 --- a/library/src/scala/runtime/LazyVals.scala +++ b/library/src/scala/runtime/LazyVals.scala @@ -106,6 +106,13 @@ object LazyVals { r } + def getOffsetStatic(field: java.lang.reflect.Field) = + val r = unsafe.objectFieldOffset(field) + if (debug) + println(s"getOffset(${field.getDeclaringClass}, ${field.getName}) = $r") + r + + object Names { final val state = "STATE" final val cas = "CAS" From 3cd853a5f0d9590763a4c89b0831a369c0b99718 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Thu, 12 May 2022 12:22:14 +0200 Subject: [PATCH 2/2] Fix failing MiMa --- library/src/scala/runtime/LazyVals.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/src/scala/runtime/LazyVals.scala b/library/src/scala/runtime/LazyVals.scala index f3fe52beb9ee..aabbd489d589 100644 --- a/library/src/scala/runtime/LazyVals.scala +++ b/library/src/scala/runtime/LazyVals.scala @@ -1,5 +1,7 @@ package scala.runtime +import scala.annotation.since + /** * Helper methods used in thread-safe lazy vals. */ @@ -106,6 +108,7 @@ object LazyVals { r } + @since("3.2") def getOffsetStatic(field: java.lang.reflect.Field) = val r = unsafe.objectFieldOffset(field) if (debug)