@@ -229,6 +229,7 @@ js::Nursery::Nursery(GCRuntime* gc)
229
229
reportPretenuring_(false ),
230
230
reportPretenuringThreshold_(0 ),
231
231
minorGCTriggerReason_(JS::GCReason::NO_REASON),
232
+ prevPosition_(0 ),
232
233
hasRecentGrowthData(false ),
233
234
smoothedTargetSize(0.0 ) {
234
235
const char * env = getenv (" MOZ_NURSERY_STRINGS" );
@@ -539,8 +540,8 @@ inline void* js::Nursery::allocate(size_t size) {
539
540
MOZ_ASSERT (CurrentThreadCanAccessRuntime (runtime ()));
540
541
MOZ_ASSERT_IF (currentChunk_ == currentStartChunk_,
541
542
position () >= currentStartPosition_);
542
- MOZ_ASSERT (position () % CellAlignBytes == 0 );
543
543
MOZ_ASSERT (size % CellAlignBytes == 0 );
544
+ MOZ_ASSERT (position () % CellAlignBytes == 0 );
544
545
545
546
if (MOZ_UNLIKELY (currentEnd () < position () + size)) {
546
547
return moveToNextChunkAndAllocate (size);
@@ -556,6 +557,12 @@ inline void* js::Nursery::allocate(size_t size) {
556
557
}
557
558
558
559
void * Nursery::moveToNextChunkAndAllocate (size_t size) {
560
+ if (minorGCRequested ()) {
561
+ // If a minor GC was requested then fail the allocation. The collection is
562
+ // then run in GCRuntime::tryNewNurseryCell.
563
+ return nullptr ;
564
+ }
565
+
559
566
MOZ_ASSERT (currentEnd () < position () + size);
560
567
561
568
unsigned chunkno = currentChunk_ + 1 ;
@@ -1124,6 +1131,15 @@ void js::Nursery::collect(JS::GCOptions options, JS::GCReason reason) {
1124
1131
JSRuntime* rt = runtime ();
1125
1132
MOZ_ASSERT (!rt->mainContextFromOwnThread ()->suppressGC );
1126
1133
1134
+ if (minorGCRequested ()) {
1135
+ MOZ_ASSERT (position_ == chunk (currentChunk_).end ());
1136
+ position_ = prevPosition_;
1137
+ prevPosition_ = 0 ;
1138
+ minorGCTriggerReason_ = JS::GCReason::NO_REASON;
1139
+ rt->mainContextFromOwnThread ()->clearPendingInterrupt (
1140
+ InterruptReason::MinorGC);
1141
+ }
1142
+
1127
1143
if (!isEnabled () || isEmpty ()) {
1128
1144
// Our barriers are not always exact, and there may be entries in the
1129
1145
// storebuffer even when the nursery is disabled or empty. It's not safe
@@ -1584,6 +1600,25 @@ bool js::Nursery::registerMallocedBuffer(void* buffer, size_t nbytes) {
1584
1600
return true ;
1585
1601
}
1586
1602
1603
+ void Nursery::requestMinorGC (JS::GCReason reason) {
1604
+ MOZ_ASSERT (reason != JS::GCReason::NO_REASON);
1605
+ MOZ_ASSERT (CurrentThreadCanAccessRuntime (runtime ()));
1606
+ MOZ_ASSERT (isEnabled ());
1607
+
1608
+ if (minorGCRequested ()) {
1609
+ return ;
1610
+ }
1611
+
1612
+ // Set position to end of chunk to block further allocation.
1613
+ MOZ_ASSERT (prevPosition_ == 0 );
1614
+ prevPosition_ = position_;
1615
+ position_ = chunk (currentChunk_).end ();
1616
+
1617
+ minorGCTriggerReason_ = reason;
1618
+ runtime ()->mainContextFromOwnThread ()->requestInterrupt (
1619
+ InterruptReason::MinorGC);
1620
+ }
1621
+
1587
1622
size_t Nursery::sizeOfMallocedBuffers (
1588
1623
mozilla::MallocSizeOf mallocSizeOf) const {
1589
1624
size_t total = 0 ;
0 commit comments