* Ensure phantomly reachable objects are enqueued only * the first time they become phantomly reachable.
* Ensure phantomly reachable objects are enqueued only the first time * they become phantomly reachable.
  public static Address processReference(Address reference,                                         int semantics) throws InlinePragma {    if (Assert.VERIFY_ASSERTIONS) Assert._assert(!reference.isZero());        TraceLocal trace = ActivePlan.collector().getCurrentTrace();        if (TRACE) {      Log.write("+++ old reference: "); Log.writeln(reference);    }    Address newReference;    /*     * If the reference is dead, we're done with it. Let it (and     * possibly its referent) be garbage-collected.     */    if (ReferenceGlue.REFERENCES_ARE_OBJECTS &&         !trace.isReferentLive(reference.toObjectReference())) {      newReference = Address.zero();    } else {      /* Otherwise... */      if (ReferenceGlue.REFERENCES_ARE_OBJECTS)        newReference = trace.getForwardedReference(reference.toObjectReference()).toAddress();      else        newReference = reference;      ObjectReference oldReferent = ReferenceGlue.getReferent(reference);      if (TRACE_DETAIL) {        Log.write("    new reference: "); Log.writeln(newReference);        Log.write(" old referent: "); Log.writeln(oldReferent);      }      /*       * If the application has cleared the referent the Java spec says       * this does not cause the Reference object to be enqueued. We       * simply allow the Reference object to fall out of our       * waiting list.       */      if (oldReferent.isNull()) {        newReference = Address.zero();      } else {        boolean enqueue = false;        if (semantics == PHANTOM_SEMANTICS && !trace.isLive(oldReferent)) {            /*             * Keep phantomly reachable objects from being collected             * until they are completely unreachable.             */            if (TRACE_DETAIL) {              Log.write("    resurrecting: "); Log.writeln(oldReferent);            }            trace.retainReferent(oldReferent);            enqueue = true;        } else if (semantics == SOFT_SEMANTICS && !clearSoftReferences) {          /*           * Unless we've completely run out of memory, we keep           * softly reachable objects alive.           */          if (TRACE_DETAIL) {            Log.write("    resurrecting: "); Log.writeln(oldReferent);          }          trace.retainReferent(oldReferent);        }                  if (trace.isLive(oldReferent)) {          /*           * Referent is still reachable in a way that is as strong as           * or stronger than the current reference level.           */          ObjectReference newReferent = trace.getForwardedReferent(oldReferent);          if (TRACE) {            Log.write(" new referent: "); Log.writeln(newReferent);          }                      /*           * The reference object stays on the waiting list, and the           * referent is untouched. The only thing we must do is           * ensure that the former addresses are updated with the           * new forwarding addresses in case the collector is a           * copying collector.           */                    /* Update the referent */          ReferenceGlue.setReferent(newReference, newReferent);        }        else {          /* Referent is unreachable. */                      if (TRACE) {            Log.write(" UNREACHABLE:  "); Log.writeln(oldReferent);          }          /*           * Weak and soft references always clear the referent           * before enqueueing. We don't actually call           * Reference.clear() as the user could have overridden the           * implementation and we don't want any side-effects to           * occur.           */          if (semantics != PHANTOM_SEMANTICS) {            if (TRACE_DETAIL) {              Log.write(" clearing: "); Log.writeln(oldReferent);            }            ReferenceGlue.setReferent(newReference, ObjectReference.nullReference());          }          enqueue = true;        }        if (enqueue) {          /*           * Ensure phantomly reachable objects are enqueued only           * the first time they become phantomly reachable.           */          ReferenceGlue.enqueueReference(newReference,                                         semantics == PHANTOM_SEMANTICS);                    }      }    }    return newReference;  }