Do not instantiate transient replicas 60/95060/3
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 7 Feb 2021 12:23:26 +0000 (13:23 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Sun, 7 Feb 2021 14:42:24 +0000 (15:42 +0100)
Refactor ReactorStmtCtx.haveRef() into an accurate noRefs(), taking
parents into account. If we do not have such a reference, use a new
substatement sentinel instead of a full list.

JIRA: YANGTOOLS-1223
Change-Id: I4ed132d36b1006bfe3ee650cbef6efb4c88cb8d2
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.java
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ReactorStmtCtx.java

index 7cc1efd10b8a8fc2ae2ec2b5d2298e2e2ee14625..a3d5e9d4592a7016f03c23818d8925f07467db70 100644 (file)
@@ -81,8 +81,9 @@ final class InferredStatementContext<A, D extends DeclaredStatement<A>, E extend
 
     private static final Logger LOG = LoggerFactory.getLogger(InferredStatementContext.class);
 
-    // Sentinel object for 'substatements'
-    private static final Object SWEPT_SUBSTATEMENTS = new Object();
+    // Sentinel objects for 'substatements', String is a good enough type
+    private static final @NonNull String REUSED_SUBSTATEMENTS = "reused";
+    private static final @NonNull String SWEPT_SUBSTATEMENTS = "swept";
 
     private final @NonNull StatementContextBase<A, D, E> prototype;
     private final @NonNull StatementContextBase<?, ?, ?> parent;
@@ -212,6 +213,7 @@ final class InferredStatementContext<A, D extends DeclaredStatement<A>, E extend
     E createEffective(final StatementFactory<A, D, E> factory) {
         // If we have not materialized we do not have a difference in effective substatements, hence we can forward
         // towards the source of the statement.
+        accessSubstatements();
         return substatements == null ? tryToReusePrototype(factory) : super.createEffective(factory);
     }
 
@@ -245,9 +247,9 @@ final class InferredStatementContext<A, D extends DeclaredStatement<A>, E extend
 
         if (allReused(declCopy) && allReused(effCopy)) {
             LOG.debug("Reusing after substatement check: {}", origEffective);
-            // FIXME: can we skip this if !haveRef()?
-            substatements = reusePrototypeReplicas(Streams.concat(declCopy.stream(), effCopy.stream())
-                .map(copy -> copy.toReusedChild(this)));
+            substatements = noRefs() ? REUSED_SUBSTATEMENTS
+                : reusePrototypeReplicas(Streams.concat(declCopy.stream(), effCopy.stream())
+                    .map(copy -> copy.toReusedChild(this)));
             prototype.decRef();
             return origEffective;
         }
@@ -269,8 +271,7 @@ final class InferredStatementContext<A, D extends DeclaredStatement<A>, E extend
     private @NonNull E tryToReuseSubstatements(final StatementFactory<A, D, E> factory, final @NonNull E original) {
         if (allSubstatementsContextIndependent()) {
             LOG.debug("Reusing substatements of: {}", prototype);
-            // FIXME: can we skip this if !haveRef()?
-            substatements = reusePrototypeReplicas();
+            substatements = noRefs() ? REUSED_SUBSTATEMENTS : reusePrototypeReplicas();
             prototype.decRef();
             return factory.copyEffective(this, original);
         }
@@ -461,7 +462,9 @@ final class InferredStatementContext<A, D extends DeclaredStatement<A>, E extend
     }
 
     private void accessSubstatements() {
-        verify(substatements != SWEPT_SUBSTATEMENTS, "Attempted to access substatements of %s", this);
+        if (substatements instanceof String) {
+            throw new VerifyException("Access to " + substatements + " substatements of " + this);
+        }
     }
 
     @Override
@@ -477,7 +480,7 @@ final class InferredStatementContext<A, D extends DeclaredStatement<A>, E extend
         final Object local = substatements;
         substatements = SWEPT_SUBSTATEMENTS;
         int count = 0;
-        if (local != null) {
+        if (local instanceof List) {
             final List<ReactorStmtCtx<?, ?, ?>> list = castEffective(local);
             sweep(list);
             count = countUnswept(list);
index 2237fa03ef762bb4c781490a722609afcd886781..7b9afcb96f4e886e4e5f79f22b73bb654108d165 100644 (file)
@@ -693,12 +693,13 @@ abstract class ReactorStmtCtx<A, D extends DeclaredStatement<A>, E extends Effec
     }
 
     /**
-     * Return {@code true} if this context has an outstanding reference.
+     * Return {@code true} if this context has no outstanding references.
      *
-     * @return True if this context has an outstanding reference.
+     * @return True if this context has no outstanding references.
      */
-    final boolean haveRef() {
-        return refcount > REFCOUNT_NONE;
+    final boolean noRefs() {
+        final int local = refcount;
+        return local < REFCOUNT_NONE || local == REFCOUNT_NONE && noParentRef();
     }
 
     private void lastDecRef() {