Commit d8fe7c98 authored by Jon Coppeard's avatar Jon Coppeard
Browse files

Bug 1735296 - Part 5: Add a result value for TraceWeakEdge that encapsulates...

Bug 1735296 - Part 5: Add a result value for TraceWeakEdge that encapsulates all relevant information r=sfink

This is intended to be a simple as possible so that compilers can optimise away
the bits that aren't used after inlining. The result value includes the edge
state before and after update and there are runtime checks that you only use
the right one, depending on whether the edge was removed or not.

The signature of TraceWeakEdge changes to allow any barriered type because in
practice we have weak edges that are no WeakHeapPtr in cases where we don't
want the read barrier (e.g. WeakMap keys).

Differential Revision: https://phabricator.services.mozilla.com/D128261
parent bb755026
Loading
Loading
Loading
Loading
+34 −6
Original line number Diff line number Diff line
@@ -224,15 +224,43 @@ inline bool TraceManuallyBarrieredWeakEdge(JSTracer* trc, T* thingp,
  return gc::TraceEdgeInternal(trc, gc::ConvertToBase(thingp), name);
}

// The result of tracing a weak edge, which can be either:
//
//  - the target is dead (and the edge has been cleared), or
//  - the target is alive (and the edge may have been updated)
//
// This includes the initial and final values of the edge to allow cleanup if
// the target is dead or access to the referent if it is alive.
template <typename T>
inline bool TraceWeakEdge(JSTracer* trc, WeakHeapPtr<T>* thingp,
                          const char* name) {
  if (!InternalBarrierMethods<T>::isMarkable(thingp->unbarrieredGet())) {
    return true;
struct TraceWeakResult {
  const bool live_;
  const T initial_;
  const T final_;

  bool isLive() const { return live_; }
  bool isDead() const { return !live_; }

  MOZ_IMPLICIT operator bool() const { return isLive(); }

  T initialTarget() const {
    MOZ_ASSERT(isDead());
    return initial_;
  }

  return gc::TraceEdgeInternal(
      trc, gc::ConvertToBase(thingp->unbarrieredAddress()), name);
  T finalTarget() const {
    MOZ_ASSERT(isLive());
    return final_;
  }
};

template <typename T>
inline TraceWeakResult<T> TraceWeakEdge(JSTracer* trc, BarrieredBase<T>* thingp,
                                        const char* name) {
  T* addr = thingp->unbarrieredAddress();
  T initial = *addr;
  bool live = !InternalBarrierMethods<T>::isMarkable(initial) ||
              gc::TraceEdgeInternal(trc, gc::ConvertToBase(addr), name);
  return TraceWeakResult<T>{live, initial, *addr};
}

// Trace all edges contained in the given array.