summaryrefslogtreecommitdiffstats
path: root/js/src/gc/StoreBuffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/gc/StoreBuffer.h')
-rw-r--r--js/src/gc/StoreBuffer.h54
1 files changed, 35 insertions, 19 deletions
diff --git a/js/src/gc/StoreBuffer.h b/js/src/gc/StoreBuffer.h
index 2e117f02c8..0b1ca8af9b 100644
--- a/js/src/gc/StoreBuffer.h
+++ b/js/src/gc/StoreBuffer.h
@@ -169,8 +169,7 @@ class StoreBuffer {
struct WholeCellBuffer {
UniquePtr<LifoAlloc> storage_;
- ArenaCellSet* stringHead_ = nullptr;
- ArenaCellSet* nonStringHead_ = nullptr;
+ ArenaCellSet* head_ = nullptr;
const Cell* last_ = nullptr;
WholeCellBuffer() = default;
@@ -180,11 +179,9 @@ class StoreBuffer {
WholeCellBuffer(WholeCellBuffer&& other)
: storage_(std::move(other.storage_)),
- stringHead_(other.stringHead_),
- nonStringHead_(other.nonStringHead_),
+ head_(other.head_),
last_(other.last_) {
- other.stringHead_ = nullptr;
- other.nonStringHead_ = nullptr;
+ other.head_ = nullptr;
other.last_ = nullptr;
}
WholeCellBuffer& operator=(WholeCellBuffer&& other) {
@@ -214,13 +211,20 @@ class StoreBuffer {
}
bool isEmpty() const {
- MOZ_ASSERT_IF(!stringHead_ && !nonStringHead_,
- !storage_ || storage_->isEmpty());
- return !stringHead_ && !nonStringHead_;
+ MOZ_ASSERT_IF(!head_, !storage_ || storage_->isEmpty());
+ return !head_;
}
const Cell** lastBufferedPtr() { return &last_; }
+ CellSweepSet releaseCellSweepSet() {
+ CellSweepSet set;
+ std::swap(storage_, set.storage_);
+ std::swap(head_, set.head_);
+ last_ = nullptr;
+ return set;
+ }
+
private:
ArenaCellSet* allocateCellSet(Arena* arena);
};
@@ -339,9 +343,10 @@ class StoreBuffer {
bool operator==(const ValueEdge& other) const { return edge == other.edge; }
bool operator!=(const ValueEdge& other) const { return edge != other.edge; }
+ bool isGCThing() const { return edge->isGCThing(); }
+
Cell* deref() const {
- return edge->isGCThing() ? static_cast<Cell*>(edge->toGCThing())
- : nullptr;
+ return isGCThing() ? static_cast<Cell*>(edge->toGCThing()) : nullptr;
}
bool maybeInRememberedSet(const Nursery& nursery) const {
@@ -449,10 +454,10 @@ class StoreBuffer {
return edge != other.edge;
}
+ bool isGCThing() const { return edge->isGCThing(); }
+
Cell* deref() const {
- return edge->isGCThing() ? static_cast<Cell*>(edge->toGCThing())
- : nullptr;
- return nullptr;
+ return isGCThing() ? static_cast<Cell*>(edge->toGCThing()) : nullptr;
}
bool maybeInRememberedSet(const Nursery& nursery) const {
@@ -525,10 +530,6 @@ class StoreBuffer {
#endif
public:
-#ifdef DEBUG
- bool markingNondeduplicatable;
-#endif
-
explicit StoreBuffer(JSRuntime* rt);
StoreBuffer(const StoreBuffer& other) = delete;
@@ -629,6 +630,10 @@ class StoreBuffer {
}
void traceGenericEntries(JSTracer* trc) { bufferGeneric.trace(trc, this); }
+ gc::CellSweepSet releaseCellSweepSet() {
+ return bufferWholeCell.releaseCellSweepSet();
+ }
+
/* For use by our owned buffers and for testing. */
void setAboutToOverflow(JS::GCReason);
@@ -639,6 +644,7 @@ class StoreBuffer {
};
// A set of cells in an arena used to implement the whole cell store buffer.
+// Also used to store a set of cells that need to be swept.
class ArenaCellSet {
friend class StoreBuffer;
@@ -693,7 +699,17 @@ class ArenaCellSet {
WordT getWord(size_t wordIndex) const { return bits.getWord(wordIndex); }
- void trace(TenuringTracer& mover);
+ void setWord(size_t wordIndex, WordT value) {
+ bits.setWord(wordIndex, value);
+ }
+
+ // Returns the list of ArenaCellSets that need to be swept.
+ ArenaCellSet* trace(TenuringTracer& mover);
+
+ // At the end of a minor GC, sweep through all tenured dependent strings that
+ // may point to nursery-allocated chars to update their pointers in case the
+ // base string moved its chars.
+ void sweepDependentStrings();
// Sentinel object used for all empty sets.
//