// 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;
}
//
//
- // Non-final form ImplicitStmtCtx
+ // Non-final for ImplicitStmtCtx/InferredStatementContext
@Override
public boolean isSupportedToBuildEffective() {
return isSupportedToBuildEffective;
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.
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;
}