blob: fc5a978cc445b6d4627b0aaf5632d700201c3855 [file] [log] [blame]
yangguo@chromium.org5f0b8ea2012-05-16 12:37:04 +00001// Copyright 2012 the V8 project authors. All rights reserved.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_INCREMENTAL_MARKING_H_
29#define V8_INCREMENTAL_MARKING_H_
30
31
32#include "execution.h"
33#include "mark-compact.h"
34#include "objects.h"
35
36namespace v8 {
37namespace internal {
38
39
40class IncrementalMarking {
41 public:
42 enum State {
43 STOPPED,
44 SWEEPING,
45 MARKING,
46 COMPLETE
47 };
48
fschneider@chromium.org7d10be52012-04-10 12:30:14 +000049 enum CompletionAction {
50 GC_VIA_STACK_GUARD,
51 NO_GC_VIA_STACK_GUARD
52 };
53
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000054 explicit IncrementalMarking(Heap* heap);
55
verwaest@chromium.orgb6d052d2012-07-27 08:03:27 +000056 static void Initialize();
57
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000058 void TearDown();
59
60 State state() {
61 ASSERT(state_ == STOPPED || FLAG_incremental_marking);
62 return state_;
63 }
64
65 bool should_hurry() { return should_hurry_; }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000066 void set_should_hurry(bool val) { should_hurry_ = val; }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000067
68 inline bool IsStopped() { return state() == STOPPED; }
69
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000070 INLINE(bool IsMarking()) { return state() >= MARKING; }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000071
72 inline bool IsMarkingIncomplete() { return state() == MARKING; }
73
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000074 inline bool IsComplete() { return state() == COMPLETE; }
75
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000076 bool WorthActivating();
77
78 void Start();
79
80 void Stop();
81
82 void PrepareForScavenge();
83
84 void UpdateMarkingDequeAfterScavenge();
85
86 void Hurry();
87
88 void Finalize();
89
90 void Abort();
91
fschneider@chromium.org7d10be52012-04-10 12:30:14 +000092 void MarkingComplete(CompletionAction action);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000093
94 // It's hard to know how much work the incremental marker should do to make
95 // progress in the face of the mutator creating new work for it. We start
96 // of at a moderate rate of work and gradually increase the speed of the
97 // incremental marker until it completes.
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000098 // Do some marking every time this much memory has been allocated or that many
99 // heavy (color-checking) write barriers have been invoked.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000100 static const intptr_t kAllocatedThreshold = 65536;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000101 static const intptr_t kWriteBarriersInvokedThreshold = 65536;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000102 // Start off by marking this many times more memory than has been allocated.
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000103 static const intptr_t kInitialMarkingSpeed = 1;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000104 // But if we are promoting a lot of data we need to mark faster to keep up
105 // with the data that is entering the old space through promotion.
106 static const intptr_t kFastMarking = 3;
107 // After this many steps we increase the marking/allocating factor.
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000108 static const intptr_t kMarkingSpeedAccellerationInterval = 1024;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000109 // This is how much we increase the marking/allocating factor by.
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000110 static const intptr_t kMarkingSpeedAccelleration = 2;
111 static const intptr_t kMaxMarkingSpeed = 1000;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000112
113 void OldSpaceStep(intptr_t allocated) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000114 Step(allocated * kFastMarking / kInitialMarkingSpeed,
fschneider@chromium.org7d10be52012-04-10 12:30:14 +0000115 GC_VIA_STACK_GUARD);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000116 }
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +0000117
fschneider@chromium.org7d10be52012-04-10 12:30:14 +0000118 void Step(intptr_t allocated, CompletionAction action);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000119
120 inline void RestartIfNotMarking() {
121 if (state_ == COMPLETE) {
122 state_ = MARKING;
123 if (FLAG_trace_incremental_marking) {
124 PrintF("[IncrementalMarking] Restarting (new grey objects)\n");
125 }
126 }
127 }
128
129 static void RecordWriteFromCode(HeapObject* obj,
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000130 Object** slot,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000131 Isolate* isolate);
132
133 static void RecordWriteForEvacuationFromCode(HeapObject* obj,
134 Object** slot,
135 Isolate* isolate);
136
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000137 // Record a slot for compaction. Returns false for objects that are
138 // guaranteed to be rescanned or not guaranteed to survive.
139 //
140 // No slots in white objects should be recorded, as some slots are typed and
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000141 // cannot be interpreted correctly if the underlying object does not survive
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000142 // the incremental cycle (stays white).
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000143 INLINE(bool BaseRecordWrite(HeapObject* obj, Object** slot, Object* value));
144 INLINE(void RecordWrite(HeapObject* obj, Object** slot, Object* value));
145 INLINE(void RecordWriteIntoCode(HeapObject* obj,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000146 RelocInfo* rinfo,
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000147 Object* value));
148 INLINE(void RecordWriteOfCodeEntry(JSFunction* host,
149 Object** slot,
150 Code* value));
151
152
153 void RecordWriteSlow(HeapObject* obj, Object** slot, Object* value);
154 void RecordWriteIntoCodeSlow(HeapObject* obj,
155 RelocInfo* rinfo,
156 Object* value);
157 void RecordWriteOfCodeEntrySlow(JSFunction* host, Object** slot, Code* value);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000158 void RecordCodeTargetPatch(Code* host, Address pc, HeapObject* value);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000159 void RecordCodeTargetPatch(Address pc, HeapObject* value);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000160
161 inline void RecordWrites(HeapObject* obj);
162
163 inline void BlackToGreyAndUnshift(HeapObject* obj, MarkBit mark_bit);
164
165 inline void WhiteToGreyAndPush(HeapObject* obj, MarkBit mark_bit);
166
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000167 inline int steps_count() {
168 return steps_count_;
169 }
170
171 inline double steps_took() {
172 return steps_took_;
173 }
174
175 inline double longest_step() {
176 return longest_step_;
177 }
178
179 inline int steps_count_since_last_gc() {
180 return steps_count_since_last_gc_;
181 }
182
183 inline double steps_took_since_last_gc() {
184 return steps_took_since_last_gc_;
185 }
186
187 inline void SetOldSpacePageFlags(MemoryChunk* chunk) {
188 SetOldSpacePageFlags(chunk, IsMarking(), IsCompacting());
189 }
190
191 inline void SetNewSpacePageFlags(NewSpacePage* chunk) {
192 SetNewSpacePageFlags(chunk, IsMarking());
193 }
194
195 MarkingDeque* marking_deque() { return &marking_deque_; }
196
197 bool IsCompacting() { return IsMarking() && is_compacting_; }
198
199 void ActivateGeneratedStub(Code* stub);
200
201 void NotifyOfHighPromotionRate() {
202 if (IsMarking()) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000203 if (marking_speed_ < kFastMarking) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000204 if (FLAG_trace_gc) {
rossberg@chromium.org657d53b2012-07-12 11:06:03 +0000205 PrintPID("Increasing marking speed to %d "
206 "due to high promotion rate\n",
207 static_cast<int>(kFastMarking));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000208 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000209 marking_speed_ = kFastMarking;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000210 }
211 }
212 }
213
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000214 void EnterNoMarkingScope() {
215 no_marking_scope_depth_++;
216 }
217
218 void LeaveNoMarkingScope() {
219 no_marking_scope_depth_--;
220 }
221
danno@chromium.orgc612e022011-11-10 11:38:15 +0000222 void UncommitMarkingDeque();
223
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000224 private:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000225 int64_t SpaceLeftInOldSpace();
226
227 void ResetStepCounters();
228
ricow@chromium.orgfa52deb2011-10-11 19:09:42 +0000229 enum CompactionFlag { ALLOW_COMPACTION, PREVENT_COMPACTION };
230
231 void StartMarking(CompactionFlag flag);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000232
233 void ActivateIncrementalWriteBarrier(PagedSpace* space);
234 static void ActivateIncrementalWriteBarrier(NewSpace* space);
235 void ActivateIncrementalWriteBarrier();
236
237 static void DeactivateIncrementalWriteBarrierForSpace(PagedSpace* space);
238 static void DeactivateIncrementalWriteBarrierForSpace(NewSpace* space);
239 void DeactivateIncrementalWriteBarrier();
240
241 static void SetOldSpacePageFlags(MemoryChunk* chunk,
242 bool is_marking,
243 bool is_compacting);
244
245 static void SetNewSpacePageFlags(NewSpacePage* chunk, bool is_marking);
246
247 void EnsureMarkingDequeIsCommitted();
248
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +0000249 INLINE(void ProcessMarkingDeque());
250
251 INLINE(void ProcessMarkingDeque(intptr_t bytes_to_process));
252
253 INLINE(void VisitObject(Map* map, HeapObject* obj, int size));
254
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000255 Heap* heap_;
256
257 State state_;
258 bool is_compacting_;
259
260 VirtualMemory* marking_deque_memory_;
danno@chromium.orgc612e022011-11-10 11:38:15 +0000261 bool marking_deque_memory_committed_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000262 MarkingDeque marking_deque_;
263
264 int steps_count_;
265 double steps_took_;
266 double longest_step_;
267 int64_t old_generation_space_available_at_start_of_incremental_;
268 int64_t old_generation_space_used_at_start_of_incremental_;
269 int steps_count_since_last_gc_;
270 double steps_took_since_last_gc_;
271 int64_t bytes_rescanned_;
272 bool should_hurry_;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000273 int marking_speed_;
danno@chromium.orgc612e022011-11-10 11:38:15 +0000274 intptr_t bytes_scanned_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000275 intptr_t allocated_;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000276 intptr_t write_barriers_invoked_since_last_step_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000277
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000278 int no_marking_scope_depth_;
279
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000280 DISALLOW_IMPLICIT_CONSTRUCTORS(IncrementalMarking);
281};
282
283} } // namespace v8::internal
284
285#endif // V8_INCREMENTAL_MARKING_H_