Skip to content

Commit

Permalink
Add SegmentedArraySmall
Browse files Browse the repository at this point in the history
Summary: Add a specialisation of `SegmentedArrayBase` for `HermesValue32`.

Reviewed By: jpporto

Differential Revision: D27865222

fbshipit-source-id: 108b10625e77d1a5c722232c1759938450e25300
  • Loading branch information
neildhar authored and facebook-github-bot committed Apr 8, 2022
1 parent b4ac709 commit df635b4
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 8 deletions.
2 changes: 2 additions & 0 deletions include/hermes/VM/CellKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ CELL_KIND(HiddenClass)
CELL_KIND(ArrayStorage)
CELL_KIND(ArrayStorageSmall)
CELL_KIND(SegmentedArray)
CELL_KIND(SegmentedArraySmall)
CELL_KIND(Segment)
CELL_KIND(SegmentSmall)
CELL_KIND(PropertyAccessor)
CELL_KIND(Environment)
CELL_KIND(HashMapEntry)
Expand Down
6 changes: 6 additions & 0 deletions include/hermes/VM/HermesValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,10 +482,16 @@ class HermesValue {
GCCell *getPointer(PointerBase &) const {
return static_cast<GCCell *>(getPointer());
}
GCCell *getObject(PointerBase &) const {
return static_cast<GCCell *>(getObject());
}

static HermesValue encodeHermesValue(HermesValue hv, Runtime &) {
return hv;
}
static HermesValue encodeObjectValue(GCCell *obj, Runtime &) {
return encodeObjectValue(obj);
}

/// }

Expand Down
35 changes: 30 additions & 5 deletions include/hermes/VM/SegmentedArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "hermes/VM/CellKind.h"
#include "hermes/VM/Runtime.h"
#include "hermes/VM/SmallHermesValue-inline.h"

#include "llvh/Support/TrailingObjects.h"

Expand Down Expand Up @@ -59,8 +60,12 @@ class SegmentedArrayBase final : public VariableSizeRuntimeCell,

static constexpr CellKind getCellKind() {
static_assert(
std::is_same<HVType, HermesValue>::value, "Illegal HVType.");
return CellKind::SegmentKind;
std::is_same<HVType, HermesValue>::value ||
std::is_same<HVType, SmallHermesValue>::value,
"Illegal HVType.");
return std::is_same<HVType, HermesValue>::value
? CellKind::SegmentKind
: CellKind::SegmentSmallKind;
}
static bool classof(const GCCell *cell) {
return cell->getKind() == getCellKind();
Expand Down Expand Up @@ -91,6 +96,9 @@ class SegmentedArrayBase final : public VariableSizeRuntimeCell,
void setLength(Runtime &runtime, uint32_t newLength);

friend void SegmentBuildMeta(const GCCell *cell, Metadata::Builder &mb);
friend void SegmentSmallBuildMeta(
const GCCell *cell,
Metadata::Builder &mb);

private:
static const VTable vt;
Expand Down Expand Up @@ -356,8 +364,13 @@ class SegmentedArrayBase final : public VariableSizeRuntimeCell,
}

static constexpr CellKind getCellKind() {
static_assert(std::is_same<HVType, HermesValue>::value, "Illegal HVType.");
return CellKind::SegmentedArrayKind;
static_assert(
std::is_same<HVType, HermesValue>::value ||
std::is_same<HVType, SmallHermesValue>::value,
"Illegal HVType.");
return std::is_same<HVType, HermesValue>::value
? CellKind::SegmentedArrayKind
: CellKind::SegmentedArraySmallKind;
}
static bool classof(const GCCell *cell) {
return cell->getKind() == getCellKind();
Expand All @@ -372,6 +385,10 @@ class SegmentedArrayBase final : public VariableSizeRuntimeCell,
friend void SegmentedArrayBuildMeta(
const GCCell *cell,
Metadata::Builder &mb);
friend void SegmentSmallBuildMeta(const GCCell *cell, Metadata::Builder &mb);
friend void SegmentedArraySmallBuildMeta(
const GCCell *cell,
Metadata::Builder &mb);

private:
/// Throws a RangeError with a descriptive message describing the attempted
Expand Down Expand Up @@ -467,7 +484,8 @@ class SegmentedArrayBase final : public VariableSizeRuntimeCell,
assert(
segment < numUsedSegments() &&
"Trying to get a segment that does not exist");
return vmcast<Segment>(*segmentAtPossiblyUnallocated(segment));
return vmcast<Segment>(
segmentAtPossiblyUnallocated(segment)->getObject(base));
}

/// Same as \c segmentAt, except for any segment, including ones between
Expand Down Expand Up @@ -611,14 +629,21 @@ SegmentedArrayBase<HVType>::maxNumSegmentsWithoutOverflow() {
}

using SegmentedArray = SegmentedArrayBase<HermesValue>;
using SegmentedArraySmall = SegmentedArrayBase<SmallHermesValue>;

template <>
struct IsGCObject<SegmentedArray::Segment> : public std::true_type {};
template <>
struct IsGCObject<SegmentedArraySmall::Segment> : public std::true_type {};

static_assert(
SegmentedArray::allocationSizeForCapacity(SegmentedArray::maxElements()) <=
GC::maxAllocationSize(),
"maxElements() is too big");
static_assert(
SegmentedArraySmall::allocationSizeForCapacity(
SegmentedArraySmall::maxElements()) <= GC::maxAllocationSize(),
"maxElements() is too big");

} // namespace vm
} // namespace hermes
Expand Down
23 changes: 20 additions & 3 deletions lib/VM/SegmentedArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ void SegmentBuildMeta(const GCCell *cell, Metadata::Builder &mb) {
mb.setVTable(&SegmentedArray::Segment::vt);
mb.addArray("data", self->data_, &self->length_, sizeof(GCHermesValue));
}
void SegmentSmallBuildMeta(const GCCell *cell, Metadata::Builder &mb) {
const auto *self = static_cast<const SegmentedArraySmall::Segment *>(cell);
mb.setVTable(&SegmentedArraySmall::Segment::vt);
mb.addArray("data", self->data_, &self->length_, sizeof(GCSmallHermesValue));
}

template <typename HVType>
PseudoHandle<typename SegmentedArrayBase<HVType>::Segment>
Expand Down Expand Up @@ -89,6 +94,16 @@ void SegmentedArrayBuildMeta(const GCCell *cell, Metadata::Builder &mb) {
sizeof(GCHermesValue));
}

void SegmentedArraySmallBuildMeta(const GCCell *cell, Metadata::Builder &mb) {
const auto *self = static_cast<const SegmentedArraySmall *>(cell);
mb.setVTable(&SegmentedArraySmall::vt);
mb.addArray(
"slots",
self->inlineStorage(),
&self->numSlotsUsed_,
sizeof(GCSmallHermesValue));
}

template <typename HVType>
CallResult<PseudoHandle<SegmentedArrayBase<HVType>>>
SegmentedArrayBase<HVType>::create(Runtime &runtime, size_type capacity) {
Expand All @@ -115,8 +130,9 @@ CallResult<PseudoHandle<SegmentedArrayBase<HVType>>> SegmentedArrayBase<
// will be allocated.
const auto allocSize = allocationSizeForCapacity(capacity);
return createPseudoHandle(
runtime.makeAVariable<SegmentedArray, HasFinalizer::No, LongLived::Yes>(
allocSize));
runtime
.makeAVariable<SegmentedArrayBase, HasFinalizer::No, LongLived::Yes>(
allocSize));
}

template <typename HVType>
Expand Down Expand Up @@ -243,7 +259,7 @@ void SegmentedArrayBase<HVType>::allocateSegment(
"Allocating into a non-empty segment");
PseudoHandle<Segment> c = Segment::create(runtime);
self->segmentAtPossiblyUnallocated(segment)->set(
c.getHermesValue(), runtime.getHeap());
HVType::encodeObjectValue(c.get(), runtime), runtime.getHeap());
}

template <typename HVType>
Expand Down Expand Up @@ -510,6 +526,7 @@ gcheapsize_t SegmentedArrayBase<HVType>::_trimSizeCallback(const GCCell *cell) {
}

template class SegmentedArrayBase<HermesValue>;
template class SegmentedArrayBase<SmallHermesValue>;

} // namespace vm
} // namespace hermes

0 comments on commit df635b4

Please sign in to comment.