Fix ReactorStmtCtx.calculateParentRefcount()
[yangtools.git] / parser / yang-parser-reactor / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / ReactorStmtCtx.java
index a00b5446e56db4d2fbfd566267cc50fec0fd18af..edade5f26878f6e34208206ff1efb8764a114ee4 100644 (file)
@@ -156,25 +156,18 @@ abstract class ReactorStmtCtx<A, D extends DeclaredStatement<A>, E extends Effec
     // hence improve memory layout.
     private byte flags;
 
-    // Flag for use by AbstractResumedStatement, ReplicaStatementContext and InferredStatementContext. Each of them
-    // uses it to indicated a different condition. This is hiding in the alignment shadow created by
-    // 'isSupportedToBuildEffective'.
-    // FIXME: move this out once we have JDK15+
-    private boolean boolFlag;
-
     ReactorStmtCtx() {
         // Empty on purpose
     }
 
     ReactorStmtCtx(final ReactorStmtCtx<A, D, E> original) {
         isSupportedToBuildEffective = original.isSupportedToBuildEffective;
-        boolFlag = original.boolFlag;
         flags = original.flags;
     }
 
     // Used by ReplicaStatementContext only
     ReactorStmtCtx(final ReactorStmtCtx<A, D, E> original, final Void dummy) {
-        boolFlag = isSupportedToBuildEffective = original.isSupportedToBuildEffective;
+        isSupportedToBuildEffective = original.isSupportedToBuildEffective;
         flags = original.flags;
     }
 
@@ -465,7 +458,7 @@ abstract class ReactorStmtCtx<A, D extends DeclaredStatement<A>, E extends Effec
     //
     //
 
-    // Non-final form ImplicitStmtCtx
+    // Non-final for ImplicitStmtCtx/InferredStatementContext
     @Override
     public boolean isSupportedToBuildEffective() {
         return isSupportedToBuildEffective;
@@ -587,36 +580,6 @@ abstract class ReactorStmtCtx<A, D extends DeclaredStatement<A>, E extends Effec
         return false;
     }
 
-    // These two exist only due to memory optimization, should live in AbstractResumedStatement.
-    final boolean fullyDefined() {
-        return boolFlag;
-    }
-
-    final void setFullyDefined() {
-        boolFlag = true;
-    }
-
-    // This exists only due to memory optimization, should live in ReplicaStatementContext. In this context the flag
-    // indicates the need to drop source's reference count when we are being swept.
-    final boolean haveSourceReference() {
-        return boolFlag;
-    }
-
-    // These three exist due to memory optimization, should live in InferredStatementContext. In this context the flag
-    // indicates whether or not this statement's substatement file was modified, i.e. it is not quite the same as the
-    // prototype's file.
-    final boolean isModified() {
-        return boolFlag;
-    }
-
-    final void setModified() {
-        boolFlag = true;
-    }
-
-    final void setUnmodified() {
-        boolFlag = false;
-    }
-
     // These two exist only for StatementContextBase. Since we are squeezed for size, with only a single bit available
     // in flags, we default to 'false' and only set the flag to true when we are absolutely sure -- and all other cases
     // err on the side of caution by taking the time to evaluate each substatement separately.
@@ -874,26 +837,26 @@ abstract class ReactorStmtCtx<A, D extends DeclaredStatement<A>, E extends Effec
 
     private byte calculateParentRefcount() {
         final ReactorStmtCtx<?, ?, ?> parent = getParentContext();
-        if (parent == null) {
-            return PARENTREF_ABSENT;
-        }
+        return parent == null ? PARENTREF_ABSENT : parent.refcountForChild();
+    }
 
+    private byte refcountForChild() {
         // A slight wrinkle here is that our machinery handles only PRESENT -> ABSENT invalidation and we can reach here
         // while inference is still ongoing and hence we may not have a complete picture about existing references. We
         // could therefore end up caching an ABSENT result and then that information becoming stale as a new reference
         // is introduced.
-        if (parent.executionOrder() < ExecutionOrder.EFFECTIVE_MODEL) {
+        if (executionOrder() < ExecutionOrder.EFFECTIVE_MODEL) {
             return PARENTREF_UNKNOWN;
         }
 
         // There are three possibilities:
-        // - REFCOUNT_NONE, in which case we need to search next parent
+        // - REFCOUNT_NONE, in which case we need to check if this statement or its parents are holding a reference
         // - negative (< REFCOUNT_NONE), meaning parent is in some stage of sweeping, hence it does not have
         //   a reference to us
         // - positive (> REFCOUNT_NONE), meaning parent has an explicit refcount which is holding us down
-        final int refs = parent.refcount;
+        final int refs = refcount;
         if (refs == REFCOUNT_NONE) {
-            return parent.parentRefcount();
+            return noImplictRef() && noParentRef() ? PARENTREF_ABSENT : PARENTREF_PRESENT;
         }
         return refs < REFCOUNT_NONE ? PARENTREF_ABSENT : PARENTREF_PRESENT;
     }