@@ -10,7 +10,7 @@ import Symbols._
1010import Decorators ._
1111import NameKinds ._
1212import Types ._
13- import Flags .FlagSet
13+ import Flags ._
1414import StdNames .nme
1515import dotty .tools .dotc .transform .MegaPhase ._
1616import dotty .tools .dotc .ast .tpd
@@ -275,34 +275,31 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
275275 /** Create a threadsafe lazy accessor equivalent to such code
276276 * ```
277277 * def methodSymbol(): Int = {
278- * val result: Int = 0
279- * val retry: Boolean = true
280- * var flag: Long = 0L
281- * while retry do {
282- * flag = dotty.runtime.LazyVals.get(this, $claz.$OFFSET)
283- * dotty.runtime.LazyVals.STATE(flag, 0) match {
284- * case 0 =>
285- * if dotty.runtime.LazyVals.CAS(this, $claz.$OFFSET, flag, 1, $ord) {
286- * try {result = rhs} catch {
287- * case x: Throwable =>
288- * dotty.runtime.LazyVals.setFlag(this, $claz.$OFFSET, 0, $ord)
289- * throw x
290- * }
291- * $target = result
292- * dotty.runtime.LazyVals.setFlag(this, $claz.$OFFSET, 3, $ord)
293- * retry = false
294- * }
295- * case 1 =>
296- * dotty.runtime.LazyVals.wait4Notification(this, $claz.$OFFSET, flag, $ord)
297- * case 2 =>
298- * dotty.runtime.LazyVals.wait4Notification(this, $claz.$OFFSET, flag, $ord)
299- * case 3 =>
300- * retry = false
301- * result = $target
278+ * while (true) {
279+ * val flag = LazyVals.get(this, bitmap_offset)
280+ * val state = LazyVals.STATE(flag, <field-id>)
281+ *
282+ * if (state == <state-3>) {
283+ * return value_0
284+ * } else if (state == <state-0>) {
285+ * if (LazyVals.CAS(this, bitmap_offset, flag, <state-1>, <field-id>)) {
286+ * try {
287+ * val result = <RHS>
288+ * value_0 = result
289+ * nullable = null
290+ * LazyVals.setFlag(this, bitmap_offset, <state-3>, <field-id>)
291+ * return result
292+ * }
293+ * catch {
294+ * case ex =>
295+ * LazyVals.setFlag(this, bitmap_offset, <state-0>, <field-id>)
296+ * throw ex
297+ * }
302298 * }
299+ * } else /* if (state == <state-1> || state == <state-2>) */ {
300+ * LazyVals.wait4Notification(this, bitmap_offset, flag, <field-id>)
303301 * }
304- * nullable = null
305- * result
302+ * }
306303 * }
307304 * ```
308305 */
@@ -321,69 +318,59 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
321318 nullables : List [Symbol ])(implicit ctx : Context ): DefDef = {
322319 val initState = Literal (Constant (0 ))
323320 val computeState = Literal (Constant (1 ))
324- val notifyState = Literal (Constant (2 ))
325321 val computedState = Literal (Constant (3 ))
326- val flagSymbol = ctx.newSymbol(methodSymbol, lazyNme.flag, containerFlags, defn.LongType )
327- val flagDef = ValDef (flagSymbol, Literal (Constant (0L )))
328322
329323 val thiz = This (claz)(ctx.fresh.setOwner(claz))
324+ val fieldId = Literal (Constant (ord))
330325
331- val resultSymbol = ctx.newSymbol(methodSymbol, lazyNme.result, containerFlags, tp)
332- val resultDef = ValDef (resultSymbol, defaultValue(tp))
333-
334- val retrySymbol = ctx.newSymbol(methodSymbol, lazyNme.retry, containerFlags, defn.BooleanType )
335- val retryDef = ValDef (retrySymbol, Literal (Constant (true )))
326+ val flagSymbol = ctx.newSymbol(methodSymbol, lazyNme.flag, Synthetic , defn.LongType )
327+ val flagDef = ValDef (flagSymbol, getFlag.appliedTo(thiz, offset))
328+ val flagRef = ref(flagSymbol)
336329
337- val whileCond = ref(retrySymbol)
330+ val stateSymbol = ctx.newSymbol(methodSymbol, lazyNme.state, Synthetic , defn.LongType )
331+ val stateDef = ValDef (stateSymbol, stateMask.appliedTo(ref(flagSymbol), Literal (Constant (ord))))
332+ val stateRef = ref(stateSymbol)
338333
339334 val compute = {
340- val handlerSymbol = ctx.newSymbol(methodSymbol, nme.ANON_FUN , Flags .Synthetic ,
341- MethodType (List (nme.x_1), List (defn.ThrowableType ), defn.IntType ))
342- val caseSymbol = ctx.newSymbol(methodSymbol, nme.DEFAULT_EXCEPTION_NAME , Flags .Synthetic , defn.ThrowableType )
343- val triggerRetry = setFlagState.appliedTo(thiz, offset, initState, Literal (Constant (ord)))
344- val complete = setFlagState.appliedTo(thiz, offset, computedState, Literal (Constant (ord)))
345-
346- val handler = CaseDef (Bind (caseSymbol, ref(caseSymbol)), EmptyTree ,
347- Block (List (triggerRetry), Throw (ref(caseSymbol))
348- ))
349-
350- val compute = ref(resultSymbol).becomes(rhs)
351- val tr = Try (compute, List (handler), EmptyTree )
352- val assign = ref(target).becomes(ref(resultSymbol))
353- val noRetry = ref(retrySymbol).becomes(Literal (Constant (false )))
354- val body = If (casFlag.appliedTo(thiz, offset, ref(flagSymbol), computeState, Literal (Constant (ord))),
355- Block (tr :: assign :: complete :: noRetry :: Nil , Literal (Constant (()))),
356- Literal (Constant (())))
357-
358- CaseDef (initState, EmptyTree , body)
359- }
360-
361- val waitFirst = {
362- val wait = waitOnLock.appliedTo(thiz, offset, ref(flagSymbol), Literal (Constant (ord)))
363- CaseDef (computeState, EmptyTree , wait)
335+ val resultSymbol = ctx.newSymbol(methodSymbol, lazyNme.result, Synthetic , tp)
336+ val resultRef = ref(resultSymbol)
337+ val stats = (
338+ ValDef (resultSymbol, rhs) ::
339+ ref(target).becomes(resultRef) ::
340+ (nullOut(nullableFor(methodSymbol)) :+
341+ setFlagState.appliedTo(thiz, offset, computedState, fieldId))
342+ )
343+ Block (stats, Return (resultRef, methodSymbol))
364344 }
365345
366- val waitSecond = {
367- val wait = waitOnLock.appliedTo(thiz, offset, ref(flagSymbol), Literal (Constant (ord)))
368- CaseDef (notifyState, EmptyTree , wait)
369- }
370-
371- val computed = {
372- val noRetry = ref(retrySymbol).becomes(Literal (Constant (false )))
373- val result = ref(resultSymbol).becomes(ref(target))
374- val body = Block (noRetry :: result :: Nil , Literal (Constant (())))
375- CaseDef (computedState, EmptyTree , body)
346+ val retryCase = {
347+ val caseSymbol = ctx.newSymbol(methodSymbol, nme.DEFAULT_EXCEPTION_NAME , Flags .Synthetic , defn.ThrowableType )
348+ val triggerRetry = setFlagState.appliedTo(thiz, offset, initState, fieldId)
349+ CaseDef (
350+ Bind (caseSymbol, ref(caseSymbol)),
351+ EmptyTree ,
352+ Block (List (triggerRetry), Throw (ref(caseSymbol)))
353+ )
376354 }
377355
378- val default = CaseDef (Underscore (defn.LongType ), EmptyTree , Literal (Constant (())))
356+ val initialize = If (
357+ casFlag.appliedTo(thiz, offset, flagRef, computeState, fieldId),
358+ Try (compute, List (retryCase), EmptyTree ),
359+ unitLiteral
360+ )
379361
380- val cases = Match (stateMask.appliedTo(ref(flagSymbol), Literal (Constant (ord))),
381- List (compute, waitFirst, waitSecond, computed, default)) // todo: annotate with @switch
362+ val condition = If (
363+ stateRef.equal(computedState),
364+ Return (ref(target), methodSymbol),
365+ If (
366+ stateRef.equal(initState),
367+ initialize,
368+ waitOnLock.appliedTo(thiz, offset, flagRef, fieldId)
369+ )
370+ )
382371
383- val whileBody = Block (ref(flagSymbol).becomes(getFlag.appliedTo(thiz, offset)) :: Nil , cases)
384- val cycle = WhileDo (whileCond, whileBody)
385- val setNullables = nullOut(nullables)
386- DefDef (methodSymbol, Block (resultDef :: retryDef :: flagDef :: cycle :: setNullables, ref(resultSymbol)))
372+ val loop = WhileDo (EmptyTree , Block (List (flagDef, stateDef), condition))
373+ DefDef (methodSymbol, loop)
387374 }
388375
389376 def transformMemberDefVolatile (x : ValOrDefDef )(implicit ctx : Context ): Thicket = {
@@ -465,6 +452,7 @@ object LazyVals {
465452 val getOffset : TermName = N .getOffset.toTermName
466453 }
467454 val flag : TermName = " flag" .toTermName
455+ val state : TermName = " state" .toTermName
468456 val result : TermName = " result" .toTermName
469457 val value : TermName = " value" .toTermName
470458 val initialized : TermName = " initialized" .toTermName
0 commit comments