Skip to content

Commit 58acd20

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

File tree

2 files changed

+137
-4
lines changed

2 files changed

+137
-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::setInLargeObj(
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::setNonNullInLargeObj(
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::setInLargeObj(
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

+81-4
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,53 @@ 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, which lives in
55+
/// an object of kind that supports large allocation.
56+
/// \param ptr The memory being pointed to.
57+
/// \param base The base of ptr.
58+
/// \param gc Used for write barriers.
59+
/// \param owningObj The object that contains this GCPointer, used by the
60+
/// writer barriers.
61+
inline void setInLargeObj(
62+
PointerBase &base,
63+
GCCell *ptr,
64+
GC &gc,
65+
const GCCell *owningObj);
66+
inline void setInLargeObj(
67+
PointerBase &base,
68+
CompressedPointer ptr,
69+
GC &gc,
70+
const GCCell *owningObj);
71+
inline void setNonNullInLargeObj(
72+
PointerBase &base,
73+
GCCell *ptr,
74+
GC &gc,
75+
const GCCell *owningObj);
76+
4577
/// Set this pointer to null. This needs a write barrier in some types of
4678
/// garbage collectors.
4779
inline void setNull(GC &gc);
@@ -64,12 +96,26 @@ class GCPointer : public GCPointerBase {
6496
template <typename NeedsBarriers>
6597
GCPointer(PointerBase &base, T *ptr, GC &gc, NeedsBarriers needsBarriers)
6698
: GCPointerBase(base, ptr, gc, needsBarriers) {}
99+
/// Pass the owning object pointer to perform barriers when the object
100+
/// supports large allocation.
101+
template <typename NeedsBarriers>
102+
GCPointer(
103+
PointerBase &base,
104+
T *ptr,
105+
GC &gc,
106+
const GCCell *owningObj,
107+
NeedsBarriers needsBarriers)
108+
: GCPointerBase(base, ptr, gc, owningObj, needsBarriers) {}
67109

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

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

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

100-
/// Convenience overload of GCPointer::set for other GCPointers.
147+
/// Assign a new value to this GCPointer, which lives in an object of kind
148+
/// that supports large allocation.
149+
/// \param base The base of ptr.
150+
/// \param ptr The memory being pointed to.
151+
/// \param gc Used for write barriers.
152+
/// \param owningObj The object that contains this GCPointer, used by the
153+
/// writer barriers.
154+
void
155+
setInLargeObj(PointerBase &base, T *ptr, GC &gc, const GCCell *owningObj) {
156+
GCPointerBase::set(base, ptr, gc, owningObj);
157+
}
158+
void setNonNullInLargeObj(
159+
PointerBase &base,
160+
T *ptr,
161+
GC &gc,
162+
const GCCell *owningObj) {
163+
GCPointerBase::setNonNull(base, ptr, gc, owningObj);
164+
}
165+
166+
/// Convenience overload of GCPointer::set for other GCPointers. This must not
167+
/// be used if it lives in an object that supports large allocation.
101168
void set(PointerBase &base, const GCPointer<T> &ptr, GC &gc) {
102169
GCPointerBase::set(base, ptr, gc);
103170
}
171+
172+
/// Convenience overload of GCPointer::set for other GCPointers. \p owningObj
173+
/// is used by the writer barriers.
174+
void setInLargeObj(
175+
PointerBase &base,
176+
const GCPointer<T> &ptr,
177+
GC &gc,
178+
const GCCell *owningObj) {
179+
GCPointerBase::set(base, ptr, gc, owningObj);
180+
}
104181
};
105182

106183
} // namespace vm

0 commit comments

Comments
 (0)