Skip to content

Commit 503a099

Browse files
lavenzgfacebook-github-bot
authored andcommitted
Pass the pointer of owning object to GCPointer constructor and set method (#1502)
Summary: Pull Request resolved: #1502 Differential Revision: D62222257
1 parent 32a3f9c commit 503a099

File tree

2 files changed

+123
-4
lines changed

2 files changed

+123
-4
lines changed

include/hermes/VM/GCPointer-inline.h

+56
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,24 @@ GCPointerBase::GCPointerBase(
3232
}
3333
}
3434

35+
template <typename NeedsBarriers>
36+
GCPointerBase::GCPointerBase(
37+
PointerBase &base,
38+
GCCell *ptr,
39+
GC &gc,
40+
const GCCell *owningObj,
41+
NeedsBarriers)
42+
: CompressedPointer(CompressedPointer::encode(ptr, base)) {
43+
assert(
44+
(!ptr || gc.validPointer(ptr)) &&
45+
"Cannot construct a GCPointer from an invalid pointer");
46+
if constexpr (NeedsBarriers::value) {
47+
gc.constructorWriteBarrierForLargeObj(owningObj, this, ptr);
48+
} else {
49+
assert(!gc.needsWriteBarrier(this, ptr));
50+
}
51+
}
52+
3553
inline void GCPointerBase::set(PointerBase &base, GCCell *ptr, GC &gc) {
3654
assert(
3755
(!ptr || gc.validPointer(ptr)) &&
@@ -59,6 +77,44 @@ GCPointerBase::set(PointerBase &base, CompressedPointer ptr, GC &gc) {
5977
setNoBarrier(ptr);
6078
}
6179

80+
inline void GCPointerBase::set(
81+
PointerBase &base,
82+
GCCell *ptr,
83+
GC &gc,
84+
const GCCell *owningObj) {
85+
assert(
86+
(!ptr || gc.validPointer(ptr)) &&
87+
"Cannot set a GCPointer to an invalid pointer");
88+
// Write barrier must happen before the write.
89+
gc.writeBarrierForLargeObj(owningObj, this, ptr);
90+
setNoBarrier(CompressedPointer::encode(ptr, base));
91+
}
92+
93+
inline void GCPointerBase::setNonNull(
94+
PointerBase &base,
95+
GCCell *ptr,
96+
GC &gc,
97+
const GCCell *owningObj) {
98+
assert(
99+
gc.validPointer(ptr) && "Cannot set a GCPointer to an invalid pointer");
100+
// Write barrier must happen before the write.
101+
gc.writeBarrierForLargeObj(owningObj, this, ptr);
102+
setNoBarrier(CompressedPointer::encodeNonNull(ptr, base));
103+
}
104+
105+
inline void GCPointerBase::set(
106+
PointerBase &base,
107+
CompressedPointer ptr,
108+
GC &gc,
109+
const GCCell *owningObj) {
110+
assert(
111+
(!ptr || gc.validPointer(ptr.get(base))) &&
112+
"Cannot set a GCPointer to an invalid pointer");
113+
// Write barrier must happen before the write.
114+
gc.writeBarrierForLargeObj(owningObj, this, ptr.get(base));
115+
setNoBarrier(ptr);
116+
}
117+
62118
inline void GCPointerBase::setNull(GC &gc) {
63119
gc.snapshotWriteBarrier(this);
64120
setNoBarrier(CompressedPointer(nullptr));

include/hermes/VM/GCPointer.h

+67-4
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,46 @@ class GCPointerBase : public CompressedPointer {
2727
template <typename NeedsBarriers>
2828
inline GCPointerBase(PointerBase &base, GCCell *ptr, GC &gc, NeedsBarriers);
2929

30+
template <typename NeedsBarriers>
31+
inline GCPointerBase(
32+
PointerBase &base,
33+
GCCell *ptr,
34+
GC &gc,
35+
const GCCell *owningObj,
36+
NeedsBarriers);
37+
3038
public:
3139
// These classes are used as arguments to GCPointer constructors, to
3240
// indicate whether write barriers are necessary in initializing the
3341
// GCPointer.
3442
class NoBarriers : public std::false_type {};
3543
class YesBarriers : public std::true_type {};
3644

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

54+
/// This must be used to assign a new value to this GCPointer.
55+
/// \param ptr The memory being pointed to.
56+
/// \param base The base of ptr.
57+
/// \param gc Used for write barriers.
58+
/// \param owningObj The object that contains this GCPointer, used by the
59+
/// writer barriers.
60+
inline void
61+
set(PointerBase &base, GCCell *ptr, GC &gc, const GCCell *owningObj);
62+
inline void set(
63+
PointerBase &base,
64+
CompressedPointer ptr,
65+
GC &gc,
66+
const GCCell *owningObj);
67+
inline void
68+
setNonNull(PointerBase &base, GCCell *ptr, GC &gc, const GCCell *owningObj);
69+
4570
/// Set this pointer to null. This needs a write barrier in some types of
4671
/// garbage collectors.
4772
inline void setNull(GC &gc);
@@ -64,12 +89,26 @@ class GCPointer : public GCPointerBase {
6489
template <typename NeedsBarriers>
6590
GCPointer(PointerBase &base, T *ptr, GC &gc, NeedsBarriers needsBarriers)
6691
: GCPointerBase(base, ptr, gc, needsBarriers) {}
92+
/// Pass the owning object pointer to perform barriers when the object
93+
/// supports large allocation.
94+
template <typename NeedsBarriers>
95+
GCPointer(
96+
PointerBase &base,
97+
T *ptr,
98+
GC &gc,
99+
const GCCell *owningObj,
100+
NeedsBarriers needsBarriers)
101+
: GCPointerBase(base, ptr, gc, owningObj, needsBarriers) {}
67102

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

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

89-
/// Assign a new value to this GCPointer.
128+
/// Assign a new value to this GCPointer. This must not be used if it lives in
129+
/// an object that supports large allocation.
90130
/// \param base The base of ptr.
91131
/// \param ptr The memory being pointed to.
92132
/// \param gc Used for write barriers.
@@ -97,10 +137,33 @@ class GCPointer : public GCPointerBase {
97137
GCPointerBase::setNonNull(base, ptr, gc);
98138
}
99139

100-
/// Convenience overload of GCPointer::set for other GCPointers.
140+
/// Assign a new value to this GCPointer.
141+
/// \param ptr The memory being pointed to.
142+
/// \param gc Used for write barriers.
143+
/// \param owningObj The object that contains this GCPointer, used by the
144+
/// writer barriers.
145+
void set(PointerBase &base, T *ptr, GC &gc, const GCCell *owningObj) {
146+
GCPointerBase::set(base, ptr, gc, owningObj);
147+
}
148+
void setNonNull(PointerBase &base, T *ptr, GC &gc, const GCCell *owningObj) {
149+
GCPointerBase::setNonNull(base, ptr, gc, owningObj);
150+
}
151+
152+
/// Convenience overload of GCPointer::set for other GCPointers. This must not
153+
/// be used if it lives in an object that supports large allocation.
101154
void set(PointerBase &base, const GCPointer<T> &ptr, GC &gc) {
102155
GCPointerBase::set(base, ptr, gc);
103156
}
157+
158+
/// Convenience overload of GCPointer::set for other GCPointers. \p owningObj
159+
/// is used by the writer barriers.
160+
void set(
161+
PointerBase &base,
162+
const GCPointer<T> &ptr,
163+
GC &gc,
164+
const GCCell *owningObj) {
165+
GCPointerBase::set(base, ptr, gc, owningObj);
166+
}
104167
};
105168

106169
} // namespace vm

0 commit comments

Comments
 (0)