From a5bb6e00f051bf93fe7df4a02583eba478fa5ca1 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 13 Sep 2016 22:45:10 +1000 Subject: SD-225 Use a "lzycompute" method for module initialization The monitors and module instantation were inliuned into the module accessor method in b2e0911. However, this seems to have had a detrimental impact on performance. This might be because the module accessors are now above the "always inline" HotSpot threshold of 35 bytes, or perhaps because they contain monitor-entry/exit and exception handlers. This commit returns to the the 2.11.8 appraoch of factoring the the second check of the doublecheck locking into a method. I've done this by declaring a nested method within the accessor; this will be lifted out to the class level by lambdalift. This represents a slight deviation from the implementation strategy used for lazy accessors, which create a symbol for the slowpath method in the info transform and generate the corresponding DefDef as a class member. I don't believe this deviation is particular worrisome, though. I have bootstrapped the compiler through this commit and found that the drastic regression in compiling the shapeless test suite is solved. --- src/compiler/scala/tools/nsc/transform/Fields.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/compiler/scala/tools/nsc/transform') diff --git a/src/compiler/scala/tools/nsc/transform/Fields.scala b/src/compiler/scala/tools/nsc/transform/Fields.scala index a383b65192..45741eb391 100644 --- a/src/compiler/scala/tools/nsc/transform/Fields.scala +++ b/src/compiler/scala/tools/nsc/transform/Fields.scala @@ -22,7 +22,7 @@ import symtab.Flags._ * in the first (closest in the subclassing lattice) subclass (not a trait) of a trait. * * For lazy vals and modules, we emit accessors that using double-checked locking (DCL) to balance thread safety - * and performance. A lazy val gets a compute method for the DCL's slow path, for a module it's all done in the accessor. + * and performance. For both lazy vals and modules, the a compute method contains the DCL's slow path. * * Local lazy vals do not receive bitmaps, but use a Lazy*Holder that has the volatile init bit and the computed value. * See `mkLazyLocalDef`. @@ -236,7 +236,9 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor * * TODO: optimize using local variable? */ - Block(If(needsInit, gen.mkSynchronized(monitorHolder)(If(needsInit, init, EmptyTree)), EmptyTree) :: Nil, moduleVarRef) + val computeName = nme.newLazyValSlowComputeName(module.name) + val computeMethod = DefDef(NoMods, computeName, Nil, ListOfNil, TypeTree(UnitTpe), gen.mkSynchronized(monitorHolder)(If(needsInit, init, EmptyTree))) + Block(computeMethod :: If(needsInit, Apply(Ident(computeName), Nil), EmptyTree) :: Nil, moduleVarRef) } // NoSymbol for lazy accessor sym with unit result type -- cgit v1.2.3