Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "gc/StoreBuffer-inl.h"
8 :
9 : #include "mozilla/Assertions.h"
10 :
11 : #include "jscompartment.h"
12 :
13 : #include "gc/Statistics.h"
14 : #include "vm/ArgumentsObject.h"
15 : #include "vm/Runtime.h"
16 :
17 : #include "jsgcinlines.h"
18 :
19 : using namespace js;
20 : using namespace js::gc;
21 :
22 : void
23 21 : StoreBuffer::GenericBuffer::trace(StoreBuffer* owner, JSTracer* trc)
24 : {
25 42 : mozilla::ReentrancyGuard g(*owner);
26 21 : MOZ_ASSERT(owner->isEnabled());
27 21 : if (!storage_)
28 0 : return;
29 :
30 3229 : for (LifoAlloc::Enum e(*storage_); !e.empty();) {
31 3208 : unsigned size = *e.get<unsigned>();
32 3208 : e.popFront<unsigned>();
33 3208 : BufferableRef* edge = e.get<BufferableRef>(size);
34 3208 : edge->trace(trc);
35 3208 : e.popFront(size);
36 : }
37 : }
38 :
39 : bool
40 7 : StoreBuffer::enable()
41 : {
42 7 : if (enabled_)
43 0 : return true;
44 :
45 21 : if (!bufferVal.init() ||
46 14 : !bufferCell.init() ||
47 21 : !bufferSlot.init() ||
48 7 : !bufferGeneric.init())
49 : {
50 0 : return false;
51 : }
52 :
53 7 : enabled_ = true;
54 7 : return true;
55 : }
56 :
57 : void
58 3 : StoreBuffer::disable()
59 : {
60 3 : if (!enabled_)
61 0 : return;
62 :
63 3 : aboutToOverflow_ = false;
64 :
65 3 : enabled_ = false;
66 : }
67 :
68 : void
69 24 : StoreBuffer::clear()
70 : {
71 24 : if (!enabled_)
72 0 : return;
73 :
74 24 : aboutToOverflow_ = false;
75 24 : cancelIonCompilations_ = false;
76 :
77 24 : bufferVal.clear();
78 24 : bufferCell.clear();
79 24 : bufferSlot.clear();
80 24 : bufferGeneric.clear();
81 :
82 24 : for (ArenaCellSet* set = bufferWholeCell; set; set = set->next)
83 0 : set->arena->bufferedCells() = nullptr;
84 24 : bufferWholeCell = nullptr;
85 : }
86 :
87 : void
88 18 : StoreBuffer::setAboutToOverflow()
89 : {
90 18 : if (!aboutToOverflow_) {
91 18 : aboutToOverflow_ = true;
92 18 : runtime_->gc.stats().count(gcstats::STAT_STOREBUFFER_OVERFLOW);
93 : }
94 18 : nursery_.requestMinorGC(JS::gcreason::FULL_STORE_BUFFER);
95 18 : }
96 :
97 : void
98 0 : StoreBuffer::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::GCSizes
99 : *sizes)
100 : {
101 0 : sizes->storeBufferVals += bufferVal.sizeOfExcludingThis(mallocSizeOf);
102 0 : sizes->storeBufferCells += bufferCell.sizeOfExcludingThis(mallocSizeOf);
103 0 : sizes->storeBufferSlots += bufferSlot.sizeOfExcludingThis(mallocSizeOf);
104 0 : sizes->storeBufferGenerics += bufferGeneric.sizeOfExcludingThis(mallocSizeOf);
105 :
106 0 : for (ArenaCellSet* set = bufferWholeCell; set; set = set->next)
107 0 : sizes->storeBufferWholeCells += sizeof(ArenaCellSet);
108 0 : }
109 :
110 : void
111 66 : StoreBuffer::addToWholeCellBuffer(ArenaCellSet* set)
112 : {
113 66 : set->next = bufferWholeCell;
114 66 : bufferWholeCell = set;
115 66 : }
116 :
117 3 : ArenaCellSet ArenaCellSet::Empty(nullptr);
118 :
119 69 : ArenaCellSet::ArenaCellSet(Arena* arena)
120 69 : : arena(arena), next(nullptr)
121 : {
122 69 : bits.clear(false);
123 69 : }
124 :
125 : ArenaCellSet*
126 66 : js::gc::AllocateWholeCellSet(Arena* arena)
127 : {
128 66 : Zone* zone = arena->zone;
129 66 : if (!zone->group()->nursery().isEnabled())
130 0 : return nullptr;
131 :
132 132 : AutoEnterOOMUnsafeRegion oomUnsafe;
133 66 : Nursery& nursery = zone->group()->nursery();
134 66 : void* data = nursery.allocateBuffer(zone, sizeof(ArenaCellSet));
135 66 : if (!data) {
136 0 : oomUnsafe.crash("Failed to allocate WholeCellSet");
137 : return nullptr;
138 : }
139 :
140 66 : if (nursery.freeSpace() < ArenaCellSet::NurseryFreeThresholdBytes)
141 0 : zone->group()->storeBuffer().setAboutToOverflow();
142 :
143 66 : auto cells = static_cast<ArenaCellSet*>(data);
144 66 : new (cells) ArenaCellSet(arena);
145 66 : arena->bufferedCells() = cells;
146 66 : zone->group()->storeBuffer().addToWholeCellBuffer(cells);
147 66 : return cells;
148 : }
149 :
150 : template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::ValueEdge>;
151 : template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::CellPtrEdge>;
152 9 : template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::SlotsEdge>;
|