Skip to content

Commit a48ea29

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 0725239 commit a48ea29

File tree

2 files changed

+132
-4
lines changed

2 files changed

+132
-4
lines changed

include/hermes/VM/GCPointer-inline.h

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

35+
GCPointerBase::GCPointerBase(
36+
PointerBase &base,
37+
GCCell *ptr,
38+
GC &gc,
39+
const GCCell *owningObj)
40+
: CompressedPointer(CompressedPointer::encode(ptr, base)) {
41+
assert(
42+
(!ptr || gc.validPointer(ptr)) &&
43+
"Cannot construct a GCPointer from an invalid pointer");
44+
// Constructing a GCPointer on an object that supports large allocation always
45+
// needs to perform write barrier. We may revisit this decision if we see a
46+
// case that needs optimization.
47+
gc.constructorWriteBarrierForLargeObj(owningObj, this, ptr);
48+
}
49+
3550
inline void GCPointerBase::set(PointerBase &base, GCCell *ptr, GC &gc) {
3651
assert(
3752
(!ptr || gc.validPointer(ptr)) &&
@@ -59,6 +74,44 @@ GCPointerBase::set(PointerBase &base, CompressedPointer ptr, GC &gc) {
5974
setNoBarrier(ptr);
6075
}
6176

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

include/hermes/VM/GCPointer.h

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

30+
inline GCPointerBase(
31+
PointerBase &base,
32+
GCCell *ptr,
33+
GC &gc,
34+
const GCCell *owningObj);
35+
3036
public:
3137
// These classes are used as arguments to GCPointer constructors, to
3238
// indicate whether write barriers are necessary in initializing the
3339
// GCPointer.
3440
class NoBarriers : public std::false_type {};
3541
class YesBarriers : public std::true_type {};
3642

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

52+
/// This must be used to assign a new value to this GCPointer, which lives in
53+
/// an object of kind that supports large allocation.
54+
/// \param ptr The memory being pointed to.
55+
/// \param base The base of ptr.
56+
/// \param gc Used for write barriers.
57+
/// \param owningObj The object that contains this GCPointer, used by the
58+
/// writer barriers.
59+
inline void setInLargeObj(
60+
PointerBase &base,
61+
GCCell *ptr,
62+
GC &gc,
63+
const GCCell *owningObj);
64+
inline void setInLargeObj(
65+
PointerBase &base,
66+
CompressedPointer ptr,
67+
GC &gc,
68+
const GCCell *owningObj);
69+
inline void setNonNullInLargeObj(
70+
PointerBase &base,
71+
GCCell *ptr,
72+
GC &gc,
73+
const GCCell *owningObj);
74+
4575
/// Set this pointer to null. This needs a write barrier in some types of
4676
/// garbage collectors.
4777
inline void setNull(GC &gc);
@@ -64,12 +94,26 @@ class GCPointer : public GCPointerBase {
6494
template <typename NeedsBarriers>
6595
GCPointer(PointerBase &base, T *ptr, GC &gc, NeedsBarriers needsBarriers)
6696
: GCPointerBase(base, ptr, gc, needsBarriers) {}
97+
/// Pass the owning object pointer to perform barriers when the object
98+
/// supports large allocation.
99+
template <typename NeedsBarriers>
100+
GCPointer(
101+
PointerBase &base,
102+
T *ptr,
103+
GC &gc,
104+
const GCCell *owningObj,
105+
NeedsBarriers needsBarriers)
106+
: GCPointerBase(base, ptr, gc, owningObj, needsBarriers) {}
67107

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

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

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

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

106181
} // namespace vm

0 commit comments

Comments
 (0)