8000 SD-194 Tweak module initialization to comply with JVM spec · retronym/scala@0ef3d67 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0ef3d67

Browse files
committed
SD-194 Tweak module initialization to comply with JVM spec
Dmitry learned that we've been relying on a bug in the verifier that will be fixed in JDK 9 under the new classfile format. Assignment to a static final must occur lexically within the <clinit>. We were performing this assignment from the constructor of the module class. I'd like to move the assignment to <clinit> but that would change behaviour of "benign" cyclic references between modules. Example: ``` package p1; class CC { def foo = O.bar}; object O {new CC().foo; def bar = println(1)}; // Exiting paste mode, now interpreting. scala> p1.O 1 ``` We currently assign the MODULE$ field after the super class constructors are finished, but before the rest of the module constructor is called. ``` private p1.O$(); Code: 0: aload_0 1: invokespecial #30 // Method java/lang/Object."<init>":()V 4: aload_0 5: putstatic #32 // Field MODULE$:Lp1/O$; 8: new #34 // class p1/CC 11: dup 12: invokespecial #35 // Method p1/CC."<init>":()V 15: invokevirtual #38 // Method p1/CC.foo:()V 18: return ``` This commit removes the ACC_FINAL bit from the field. It actually wasn't behaving as final at all, precisely the issue that the stricter verifier now alerts us to. ``` scala> :paste -raw // Entering paste mode (ctrl-D to finish) package p1; object O // Exiting paste mode, now interpreting. scala> val O1 = p1.O O1: p1.O.type = p1.O$@ee7d9f1 scala> scala.reflect.ensureAccessible(p1.O.getClass.getDeclaredConstructor()).newInstance() res0: p1.O.type = p1.O$@64cee07 scala> O1 eq p1.O res1: Boolean = false ``` Fixes scala/scala-dev#SD-194
1 parent 2b172be commit 0ef3d67

File tree

2 files changed

+19
-12
lines changed

2 files changed

+19
-12
lines changed

src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,15 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
189189
* can-multi-thread
190190
*/
191191
private def addModuleInstanceField() {
192+
// TODO confirm whether we really don't want ACC_SYNTHETIC nor ACC_DEPRECATED
193+
// SD-194 This can't be FINAL on JVM 1.9+ because we assign it from within the
194+
// instance constructor, not from <clinit> directly. Assignment from <clinit>,
195+
// after the constructor has completely finished, seems like the principled
196+
// thing to do, but it would change behaviour when "benign" cyclic references
197+
// between modules exist.
198+
val mods = GenBCode.PublicStatic
192199
val fv =
193-
cnode.visitField(GenBCode.PublicStaticFinal, // TODO confirm whether we really don't want ACC_SYNTHETIC nor ACC_DEPRECATED
200+
cnode.visitField(mods,
194201
strMODULE_INSTANCE_FIELD,
195202
thisBType.descriptor,
196203
null, // no java-generic-signature

0 commit comments

Comments
 (0)
0