Skip to content

Commit

Permalink
Pass the pointer of owning object to GCPointer constructor and set me…
Browse files Browse the repository at this point in the history
…thod (facebook#1502)

Summary: Pull Request resolved: facebook#1502

Differential Revision: D62222257
  • Loading branch information
lavenzg authored and facebook-github-bot committed Dec 10, 2024
1 parent 60cc535 commit 270b69b
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 4 deletions.
56 changes: 56 additions & 0 deletions include/hermes/VM/GCPointer-inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,24 @@ GCPointerBase::GCPointerBase(
}
}

template <typename NeedsBarriers>
GCPointerBase::GCPointerBase(
PointerBase &base,
GCCell *ptr,
GC &gc,
const GCCell *owningObj,
NeedsBarriers)
: CompressedPointer(CompressedPointer::encode(ptr, base)) {
assert(
(!ptr || gc.validPointer(ptr)) &&
"Cannot construct a GCPointer from an invalid pointer");
if constexpr (NeedsBarriers::value) {
gc.constructorWriteBarrierForLargeObj(owningObj, this, ptr);
} else {
assert(!gc.needsWriteBarrier(this, ptr));
}
}

inline void GCPointerBase::set(PointerBase &base, GCCell *ptr, GC &gc) {
assert(
(!ptr || gc.validPointer(ptr)) &&
Expand Down Expand Up @@ -59,6 +77,44 @@ GCPointerBase::set(PointerBase &base, CompressedPointer ptr, GC &gc) {
setNoBarrier(ptr);
}

inline void GCPointerBase::setInLargeObj(
PointerBase &base,
GCCell *ptr,
GC &gc,
const GCCell *owningObj) {
assert(
(!ptr || gc.validPointer(ptr)) &&
"Cannot set a GCPointer to an invalid pointer");
// Write barrier must happen before the write.
gc.writeBarrierForLargeObj(owningObj, this, ptr);
setNoBarrier(CompressedPointer::encode(ptr, base));
}

inline void GCPointerBase::setNonNullInLargeObj(
PointerBase &base,
GCCell *ptr,
GC &gc,
const GCCell *owningObj) {
assert(
gc.validPointer(ptr) && "Cannot set a GCPointer to an invalid pointer");
// Write barrier must happen before the write.
gc.writeBarrierForLargeObj(owningObj, this, ptr);
setNoBarrier(CompressedPointer::encodeNonNull(ptr, base));
}

inline void GCPointerBase::setInLargeObj(
PointerBase &base,
CompressedPointer ptr,
GC &gc,
const GCCell *owningObj) {
assert(
(!ptr || gc.validPointer(ptr.get(base))) &&
"Cannot set a GCPointer to an invalid pointer");
// Write barrier must happen before the write.
gc.writeBarrierForLargeObj(owningObj, this, ptr.get(base));
setNoBarrier(ptr);
}

inline void GCPointerBase::setNull(GC &gc) {
gc.snapshotWriteBarrier(this);
setNoBarrier(CompressedPointer(nullptr));
Expand Down
85 changes: 81 additions & 4 deletions include/hermes/VM/GCPointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,53 @@ class GCPointerBase : public CompressedPointer {
template <typename NeedsBarriers>
inline GCPointerBase(PointerBase &base, GCCell *ptr, GC &gc, NeedsBarriers);

template <typename NeedsBarriers>
inline GCPointerBase(
PointerBase &base,
GCCell *ptr,
GC &gc,
const GCCell *owningObj,
NeedsBarriers);

public:
// These classes are used as arguments to GCPointer constructors, to
// indicate whether write barriers are necessary in initializing the
// GCPointer.
class NoBarriers : public std::false_type {};
class YesBarriers : public std::true_type {};

/// This must be used to assign a new value to this GCPointer.
/// This must be used to assign a new value to this GCPointer. This must not
/// be used if it lives in an object that supports large allocation.
/// \param ptr The memory being pointed to.
/// \param base The base of ptr.
/// \param gc Used for write barriers.
inline void set(PointerBase &base, GCCell *ptr, GC &gc);
inline void set(PointerBase &base, CompressedPointer ptr, GC &gc);
inline void setNonNull(PointerBase &base, GCCell *ptr, GC &gc);

/// This must be used to assign a new value to this GCPointer, which lives in
/// an object of kind that supports large allocation.
/// \param ptr The memory being pointed to.
/// \param base The base of ptr.
/// \param gc Used for write barriers.
/// \param owningObj The object that contains this GCPointer, used by the
/// writer barriers.
inline void setInLargeObj(
PointerBase &base,
GCCell *ptr,
GC &gc,
const GCCell *owningObj);
inline void setInLargeObj(
PointerBase &base,
CompressedPointer ptr,
GC &gc,
const GCCell *owningObj);
inline void setNonNullInLargeObj(
PointerBase &base,
GCCell *ptr,
GC &gc,
const GCCell *owningObj);

/// Set this pointer to null. This needs a write barrier in some types of
/// garbage collectors.
inline void setNull(GC &gc);
Expand All @@ -64,12 +96,26 @@ class GCPointer : public GCPointerBase {
template <typename NeedsBarriers>
GCPointer(PointerBase &base, T *ptr, GC &gc, NeedsBarriers needsBarriers)
: GCPointerBase(base, ptr, gc, needsBarriers) {}
/// Pass the owning object pointer to perform barriers when the object
/// supports large allocation.
template <typename NeedsBarriers>
GCPointer(
PointerBase &base,
T *ptr,
GC &gc,
const GCCell *owningObj,
NeedsBarriers needsBarriers)
: GCPointerBase(base, ptr, gc, owningObj, needsBarriers) {}

/// Same as the constructor above, with the default for
/// NeedsBarriers as "YesBarriers". (We can't use default template
/// arguments with the idiom used above.)
inline GCPointer(PointerBase &base, T *ptr, GC &gc)
GCPointer(PointerBase &base, T *ptr, GC &gc)
: GCPointer<T>(base, ptr, gc, YesBarriers()) {}
/// Pass the owning object pointer to perform barriers when the object
/// supports large allocation.
GCPointer(PointerBase &base, T *ptr, GC &gc, const GCCell *owningObj)
: GCPointer<T>(base, ptr, gc, owningObj, YesBarriers()) {}

/// We are not allowed to copy-construct or assign GCPointers.
GCPointer(const GCPointerBase &) = delete;
Expand All @@ -86,7 +132,8 @@ class GCPointer : public GCPointerBase {
return vmcast<T>(GCPointerBase::getNonNull(base));
}

/// Assign a new value to this GCPointer.
/// Assign a new value to this GCPointer. This must not be used if it lives in
/// an object that supports large allocation.
/// \param base The base of ptr.
/// \param ptr The memory being pointed to.
/// \param gc Used for write barriers.
Expand All @@ -97,10 +144,40 @@ class GCPointer : public GCPointerBase {
GCPointerBase::setNonNull(base, ptr, gc);
}

/// Convenience overload of GCPointer::set for other GCPointers.
/// Assign a new value to this GCPointer, which lives in an object of kind
/// that supports large allocation.
/// \param base The base of ptr.
/// \param ptr The memory being pointed to.
/// \param gc Used for write barriers.
/// \param owningObj The object that contains this GCPointer, used by the
/// writer barriers.
void
setInLargeObj(PointerBase &base, T *ptr, GC &gc, const GCCell *owningObj) {
GCPointerBase::set(base, ptr, gc, owningObj);
}
void setNonNullInLargeObj(
PointerBase &base,
T *ptr,
GC &gc,
const GCCell *owningObj) {
GCPointerBase::setNonNull(base, ptr, gc, owningObj);
}

/// Convenience overload of GCPointer::set for other GCPointers. This must not
/// be used if it lives in an object that supports large allocation.
void set(PointerBase &base, const GCPointer<T> &ptr, GC &gc) {
GCPointerBase::set(base, ptr, gc);
}

/// Convenience overload of GCPointer::set for other GCPointers. \p owningObj
/// is used by the writer barriers.
void setInLargeObj(
PointerBase &base,
const GCPointer<T> &ptr,
GC &gc,
const GCCell *owningObj) {
GCPointerBase::set(base, ptr, gc, owningObj);
}
};

} // namespace vm
Expand Down

0 comments on commit 270b69b

Please sign in to comment.