Skip to content

Commit cfceeda

Browse files
neildharfacebook-github-bot
authored andcommitted
Avoid passing GCHermesValue& around in JSObject
Summary: Instead of passing around references to GCHermesValue, accept and return HermesValues from get/set functions in JSObject. This reduces the possibility of accidentally holding dangling references into a relocated JSObject, which is going to be more of a risk with HV32 (since many more places will be able to allocate). This change also lets us remove references from the API for ArrayStorage. Reviewed By: avp Differential Revision: D26998350 fbshipit-source-id: defa243c3784c8013eaa3109e84eb5219b06c981
1 parent 64ef4c4 commit cfceeda

3 files changed

Lines changed: 53 additions & 32 deletions

File tree

include/hermes/VM/JSArray.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ class JSArray final : public ArrayImpl {
304304
}
305305

306306
static uint32_t getLength(const JSArray *self) {
307-
return directSlotRef(self, lengthPropIndex()).getNumber();
307+
return getDirectSlotValue(self, lengthPropIndex()).getNumber();
308308
}
309309

310310
/// Create an instance of Array, with [[Prototype]] initialized with
@@ -391,9 +391,11 @@ class JSArray final : public ArrayImpl {
391391
private:
392392
/// A helper to update the named '.length' property.
393393
static void putLength(JSArray *self, Runtime *runtime, uint32_t newLength) {
394-
directSlotRef(self, lengthPropIndex())
395-
.setNonPtr(
396-
HermesValue::encodeNumberValue(newLength), &runtime->getHeap());
394+
setDirectSlotValueNonPtr(
395+
self,
396+
lengthPropIndex(),
397+
HermesValue::encodeNumberValue(newLength),
398+
&runtime->getHeap());
397399
}
398400

399401
/// Update the JavaScript '.length' property, which also resizes the array.

include/hermes/VM/JSObject.h

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -512,21 +512,21 @@ class JSObject : public GCCell {
512512
JSObject *parent,
513513
PropOpFlags opFlags = PropOpFlags());
514514

515-
/// Return a reference to an internal property slot.
516-
static GCHermesValue &
517-
internalPropertyRef(JSObject *self, PointerBase *base, SlotIndex index) {
515+
/// Return the value of an internal property slot.
516+
static HermesValue
517+
internalProperty(JSObject *self, PointerBase *base, SlotIndex index) {
518518
assert(
519519
HiddenClass::debugIsPropertyDefined(
520520
self->clazz_.get(base),
521521
base,
522522
InternalProperty::getSymbolID(index)) &&
523523
"internal slot must be reserved");
524-
return namedSlotRef<PropStorage::Inline::Yes>(self, base, index);
524+
return getNamedSlotValue<PropStorage::Inline::Yes>(self, base, index);
525525
}
526526

527527
static HermesValue
528528
getInternalProperty(JSObject *self, PointerBase *base, SlotIndex index) {
529-
return internalPropertyRef(self, base, index);
529+
return internalProperty(self, base, index);
530530
}
531531

532532
static void setInternalProperty(
@@ -595,29 +595,31 @@ class JSObject : public GCCell {
595595
OwnKeysFlags().plusIncludeSymbols().plusIncludeNonEnumerable());
596596
}
597597

598-
/// Return a reference to a direct property storage space by \p index.
598+
/// Load a value from the direct property storage space by \p index.
599599
/// \pre index < DIRECT_PROPERTY_SLOTS.
600-
static GCHermesValue &directSlotRef(JSObject *self, SlotIndex index);
601-
static const GCHermesValue &directSlotRef(
600+
inline static HermesValue getDirectSlotValue(
602601
const JSObject *self,
603602
SlotIndex index);
604603

605-
/// Return a reference to a slot in the "named value" storage space by
606-
/// \p index.
607-
/// \pre inl == PropStorage::Inline::Yes -> index <
608-
/// PropStorage::kValueToSegmentThreshold.
609-
template <PropStorage::Inline inl = PropStorage::Inline::No>
610-
static GCHermesValue &
611-
namedSlotRef(JSObject *self, PointerBase *runtime, SlotIndex index);
604+
/// Store a value to the direct property storage space by \p index.
605+
/// \pre index < DIRECT_PROPERTY_SLOTS.
606+
inline static void setDirectSlotValue(
607+
JSObject *self,
608+
SlotIndex index,
609+
HermesValue value,
610+
GC *gc);
611+
inline static void setDirectSlotValueNonPtr(
612+
JSObject *self,
613+
SlotIndex index,
614+
HermesValue value,
615+
GC *gc);
612616

613617
/// Load a value from the "named value" storage space by \p index.
614618
/// \pre inl == PropStorage::Inline::Yes -> index <
615619
/// PropStorage::kValueToSegmentThreshold.
616620
template <PropStorage::Inline inl = PropStorage::Inline::No>
617-
static HermesValue
618-
getNamedSlotValue(JSObject *self, PointerBase *runtime, SlotIndex index) {
619-
return namedSlotRef<inl>(self, runtime, index);
620-
}
621+
inline static HermesValue
622+
getNamedSlotValue(JSObject *self, PointerBase *runtime, SlotIndex index);
621623

622624
/// Load a value from the "named value" storage space by the slot described by
623625
/// the property descriptor \p desc.
@@ -1591,21 +1593,38 @@ inline T *JSObject::initDirectPropStorage(Runtime *runtime, T *self) {
15911593
return self;
15921594
}
15931595

1594-
inline GCHermesValue &JSObject::directSlotRef(JSObject *self, SlotIndex index) {
1596+
inline HermesValue JSObject::getDirectSlotValue(
1597+
const JSObject *self,
1598+
SlotIndex index) {
15951599
assert(index < DIRECT_PROPERTY_SLOTS && "Must be a direct property");
15961600
return self->directProps()[index];
15971601
}
15981602

1599-
inline const GCHermesValue &JSObject::directSlotRef(
1600-
const JSObject *self,
1601-
SlotIndex index) {
1603+
inline void JSObject::setDirectSlotValue(
1604+
JSObject *self,
1605+
SlotIndex index,
1606+
HermesValue value,
1607+
GC *gc) {
16021608
assert(index < DIRECT_PROPERTY_SLOTS && "Must be a direct property");
1603-
return self->directProps()[index];
1609+
self->directProps()[index].set(value, gc);
1610+
}
1611+
1612+
inline void JSObject::setDirectSlotValueNonPtr(
1613+
JSObject *self,
1614+
SlotIndex index,
1615+
HermesValue value,
1616+
GC *gc) {
1617+
assert(index < DIRECT_PROPERTY_SLOTS && "Must be a direct property");
1618+
self->directProps()[index].setNonPtr(value, gc);
16041619
}
16051620

16061621
template <PropStorage::Inline inl>
1607-
inline GCHermesValue &
1608-
JSObject::namedSlotRef(JSObject *self, PointerBase *runtime, SlotIndex index) {
1622+
inline HermesValue JSObject::getNamedSlotValue(
1623+
JSObject *self,
1624+
PointerBase *runtime,
1625+
SlotIndex index) {
1626+
assert(!self->flags_.proxyObject && "getNamedSlotValue called on a Proxy");
1627+
16091628
if (LLVM_LIKELY(index < DIRECT_PROPERTY_SLOTS))
16101629
return self->directProps()[index];
16111630

lib/VM/JSObject.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2410,8 +2410,8 @@ void JSObject::_snapshotAddEdgesImpl(GCCell *cell, GC *gc, HeapSnapshot &snap) {
24102410
return;
24112411
}
24122412
// Else, it's a user-visible property.
2413-
GCHermesValue &prop =
2414-
namedSlotRef(self, gc->getPointerBase(), desc.slot);
2413+
HermesValue prop =
2414+
getNamedSlotValue(self, gc->getPointerBase(), desc.slot);
24152415
const llvh::Optional<HeapSnapshot::NodeID> idForProp =
24162416
gc->getSnapshotID(prop);
24172417
if (!idForProp) {

0 commit comments

Comments
 (0)