2012-05-16 10:07:50 +00:00
|
|
|
// Copyright 2012 the V8 project authors. All rights reserved.
|
2011-09-19 18:36:47 +00:00
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are
|
|
|
|
// met:
|
|
|
|
//
|
|
|
|
// * Redistributions of source code must retain the above copyright
|
|
|
|
// notice, this list of conditions and the following disclaimer.
|
|
|
|
// * Redistributions in binary form must reproduce the above
|
|
|
|
// copyright notice, this list of conditions and the following
|
|
|
|
// disclaimer in the documentation and/or other materials provided
|
|
|
|
// with the distribution.
|
|
|
|
// * Neither the name of Google Inc. nor the names of its
|
|
|
|
// contributors may be used to endorse or promote products derived
|
|
|
|
// from this software without specific prior written permission.
|
|
|
|
//
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
#ifndef V8_INCREMENTAL_MARKING_H_
|
|
|
|
#define V8_INCREMENTAL_MARKING_H_
|
|
|
|
|
|
|
|
|
|
|
|
#include "execution.h"
|
|
|
|
#include "mark-compact.h"
|
|
|
|
#include "objects.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
|
|
|
|
class IncrementalMarking {
|
|
|
|
public:
|
|
|
|
enum State {
|
|
|
|
STOPPED,
|
|
|
|
SWEEPING,
|
|
|
|
MARKING,
|
|
|
|
COMPLETE
|
|
|
|
};
|
|
|
|
|
2012-04-03 07:32:19 +00:00
|
|
|
enum CompletionAction {
|
|
|
|
GC_VIA_STACK_GUARD,
|
|
|
|
NO_GC_VIA_STACK_GUARD
|
|
|
|
};
|
|
|
|
|
2011-09-19 18:36:47 +00:00
|
|
|
explicit IncrementalMarking(Heap* heap);
|
|
|
|
|
2012-07-25 15:23:07 +00:00
|
|
|
static void Initialize();
|
|
|
|
|
2011-09-19 18:36:47 +00:00
|
|
|
void TearDown();
|
|
|
|
|
|
|
|
State state() {
|
|
|
|
ASSERT(state_ == STOPPED || FLAG_incremental_marking);
|
|
|
|
return state_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool should_hurry() { return should_hurry_; }
|
2012-01-11 09:39:37 +00:00
|
|
|
void set_should_hurry(bool val) { should_hurry_ = val; }
|
2011-09-19 18:36:47 +00:00
|
|
|
|
|
|
|
inline bool IsStopped() { return state() == STOPPED; }
|
|
|
|
|
2011-10-31 20:59:28 +00:00
|
|
|
INLINE(bool IsMarking()) { return state() >= MARKING; }
|
2011-09-19 18:36:47 +00:00
|
|
|
|
|
|
|
inline bool IsMarkingIncomplete() { return state() == MARKING; }
|
|
|
|
|
2011-11-30 11:13:36 +00:00
|
|
|
inline bool IsComplete() { return state() == COMPLETE; }
|
|
|
|
|
2011-09-19 18:36:47 +00:00
|
|
|
bool WorthActivating();
|
|
|
|
|
2013-05-07 09:48:42 +00:00
|
|
|
enum CompactionFlag { ALLOW_COMPACTION, PREVENT_COMPACTION };
|
|
|
|
|
|
|
|
void Start(CompactionFlag flag = ALLOW_COMPACTION);
|
2011-09-19 18:36:47 +00:00
|
|
|
|
|
|
|
void Stop();
|
|
|
|
|
|
|
|
void PrepareForScavenge();
|
|
|
|
|
|
|
|
void UpdateMarkingDequeAfterScavenge();
|
|
|
|
|
|
|
|
void Hurry();
|
|
|
|
|
|
|
|
void Finalize();
|
|
|
|
|
|
|
|
void Abort();
|
|
|
|
|
2012-04-03 07:32:19 +00:00
|
|
|
void MarkingComplete(CompletionAction action);
|
2011-09-19 18:36:47 +00:00
|
|
|
|
|
|
|
// It's hard to know how much work the incremental marker should do to make
|
|
|
|
// progress in the face of the mutator creating new work for it. We start
|
|
|
|
// of at a moderate rate of work and gradually increase the speed of the
|
|
|
|
// incremental marker until it completes.
|
2012-09-26 11:35:42 +00:00
|
|
|
// Do some marking every time this much memory has been allocated or that many
|
|
|
|
// heavy (color-checking) write barriers have been invoked.
|
2011-09-19 18:36:47 +00:00
|
|
|
static const intptr_t kAllocatedThreshold = 65536;
|
2012-09-26 11:35:42 +00:00
|
|
|
static const intptr_t kWriteBarriersInvokedThreshold = 65536;
|
2011-09-19 18:36:47 +00:00
|
|
|
// Start off by marking this many times more memory than has been allocated.
|
2012-09-26 11:35:42 +00:00
|
|
|
static const intptr_t kInitialMarkingSpeed = 1;
|
2011-09-19 18:36:47 +00:00
|
|
|
// But if we are promoting a lot of data we need to mark faster to keep up
|
|
|
|
// with the data that is entering the old space through promotion.
|
|
|
|
static const intptr_t kFastMarking = 3;
|
|
|
|
// After this many steps we increase the marking/allocating factor.
|
2012-09-26 11:35:42 +00:00
|
|
|
static const intptr_t kMarkingSpeedAccellerationInterval = 1024;
|
2011-09-19 18:36:47 +00:00
|
|
|
// This is how much we increase the marking/allocating factor by.
|
2012-09-26 11:35:42 +00:00
|
|
|
static const intptr_t kMarkingSpeedAccelleration = 2;
|
|
|
|
static const intptr_t kMaxMarkingSpeed = 1000;
|
2011-09-19 18:36:47 +00:00
|
|
|
|
2013-05-06 16:17:49 +00:00
|
|
|
void OldSpaceStep(intptr_t allocated);
|
2011-11-30 11:13:36 +00:00
|
|
|
|
2012-04-03 07:32:19 +00:00
|
|
|
void Step(intptr_t allocated, CompletionAction action);
|
2011-09-19 18:36:47 +00:00
|
|
|
|
|
|
|
inline void RestartIfNotMarking() {
|
|
|
|
if (state_ == COMPLETE) {
|
|
|
|
state_ = MARKING;
|
|
|
|
if (FLAG_trace_incremental_marking) {
|
|
|
|
PrintF("[IncrementalMarking] Restarting (new grey objects)\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void RecordWriteFromCode(HeapObject* obj,
|
2012-11-22 07:05:20 +00:00
|
|
|
Object** slot,
|
2011-09-19 18:36:47 +00:00
|
|
|
Isolate* isolate);
|
|
|
|
|
|
|
|
static void RecordWriteForEvacuationFromCode(HeapObject* obj,
|
|
|
|
Object** slot,
|
|
|
|
Isolate* isolate);
|
|
|
|
|
2012-09-11 14:01:39 +00:00
|
|
|
// Record a slot for compaction. Returns false for objects that are
|
|
|
|
// guaranteed to be rescanned or not guaranteed to survive.
|
|
|
|
//
|
|
|
|
// No slots in white objects should be recorded, as some slots are typed and
|
2012-09-26 09:01:13 +00:00
|
|
|
// cannot be interpreted correctly if the underlying object does not survive
|
2012-09-11 14:01:39 +00:00
|
|
|
// the incremental cycle (stays white).
|
2011-10-31 20:59:28 +00:00
|
|
|
INLINE(bool BaseRecordWrite(HeapObject* obj, Object** slot, Object* value));
|
|
|
|
INLINE(void RecordWrite(HeapObject* obj, Object** slot, Object* value));
|
|
|
|
INLINE(void RecordWriteIntoCode(HeapObject* obj,
|
|
|
|
RelocInfo* rinfo,
|
|
|
|
Object* value));
|
|
|
|
INLINE(void RecordWriteOfCodeEntry(JSFunction* host,
|
|
|
|
Object** slot,
|
|
|
|
Code* value));
|
2011-09-19 18:36:47 +00:00
|
|
|
|
|
|
|
|
2011-10-31 20:59:28 +00:00
|
|
|
void RecordWriteSlow(HeapObject* obj, Object** slot, Object* value);
|
|
|
|
void RecordWriteIntoCodeSlow(HeapObject* obj,
|
|
|
|
RelocInfo* rinfo,
|
|
|
|
Object* value);
|
|
|
|
void RecordWriteOfCodeEntrySlow(JSFunction* host, Object** slot, Code* value);
|
2011-10-18 15:07:42 +00:00
|
|
|
void RecordCodeTargetPatch(Code* host, Address pc, HeapObject* value);
|
2011-09-19 18:36:47 +00:00
|
|
|
void RecordCodeTargetPatch(Address pc, HeapObject* value);
|
|
|
|
|
|
|
|
inline void RecordWrites(HeapObject* obj);
|
|
|
|
|
|
|
|
inline void BlackToGreyAndUnshift(HeapObject* obj, MarkBit mark_bit);
|
|
|
|
|
|
|
|
inline void WhiteToGreyAndPush(HeapObject* obj, MarkBit mark_bit);
|
|
|
|
|
|
|
|
inline int steps_count() {
|
|
|
|
return steps_count_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline double steps_took() {
|
|
|
|
return steps_took_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline double longest_step() {
|
|
|
|
return longest_step_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int steps_count_since_last_gc() {
|
|
|
|
return steps_count_since_last_gc_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline double steps_took_since_last_gc() {
|
|
|
|
return steps_took_since_last_gc_;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void SetOldSpacePageFlags(MemoryChunk* chunk) {
|
2011-09-28 17:45:58 +00:00
|
|
|
SetOldSpacePageFlags(chunk, IsMarking(), IsCompacting());
|
2011-09-19 18:36:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void SetNewSpacePageFlags(NewSpacePage* chunk) {
|
|
|
|
SetNewSpacePageFlags(chunk, IsMarking());
|
|
|
|
}
|
|
|
|
|
|
|
|
MarkingDeque* marking_deque() { return &marking_deque_; }
|
|
|
|
|
|
|
|
bool IsCompacting() { return IsMarking() && is_compacting_; }
|
|
|
|
|
|
|
|
void ActivateGeneratedStub(Code* stub);
|
|
|
|
|
|
|
|
void NotifyOfHighPromotionRate() {
|
|
|
|
if (IsMarking()) {
|
2012-09-26 11:35:42 +00:00
|
|
|
if (marking_speed_ < kFastMarking) {
|
2011-09-19 18:36:47 +00:00
|
|
|
if (FLAG_trace_gc) {
|
2012-07-10 12:52:36 +00:00
|
|
|
PrintPID("Increasing marking speed to %d "
|
|
|
|
"due to high promotion rate\n",
|
|
|
|
static_cast<int>(kFastMarking));
|
2011-09-19 18:36:47 +00:00
|
|
|
}
|
2012-09-26 11:35:42 +00:00
|
|
|
marking_speed_ = kFastMarking;
|
2011-09-19 18:36:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-21 10:32:38 +00:00
|
|
|
void EnterNoMarkingScope() {
|
|
|
|
no_marking_scope_depth_++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LeaveNoMarkingScope() {
|
|
|
|
no_marking_scope_depth_--;
|
|
|
|
}
|
|
|
|
|
2011-11-08 12:42:02 +00:00
|
|
|
void UncommitMarkingDeque();
|
|
|
|
|
2013-05-29 11:13:59 +00:00
|
|
|
void NotifyIncompleteScanOfObject(int unscanned_bytes) {
|
|
|
|
unscanned_bytes_of_large_object_ = unscanned_bytes;
|
|
|
|
}
|
|
|
|
|
2011-09-19 18:36:47 +00:00
|
|
|
private:
|
|
|
|
int64_t SpaceLeftInOldSpace();
|
|
|
|
|
|
|
|
void ResetStepCounters();
|
|
|
|
|
2011-10-11 16:50:58 +00:00
|
|
|
void StartMarking(CompactionFlag flag);
|
2011-09-19 18:36:47 +00:00
|
|
|
|
2011-09-28 17:45:58 +00:00
|
|
|
void ActivateIncrementalWriteBarrier(PagedSpace* space);
|
2011-09-19 18:36:47 +00:00
|
|
|
static void ActivateIncrementalWriteBarrier(NewSpace* space);
|
|
|
|
void ActivateIncrementalWriteBarrier();
|
|
|
|
|
|
|
|
static void DeactivateIncrementalWriteBarrierForSpace(PagedSpace* space);
|
|
|
|
static void DeactivateIncrementalWriteBarrierForSpace(NewSpace* space);
|
|
|
|
void DeactivateIncrementalWriteBarrier();
|
|
|
|
|
2011-09-28 17:45:58 +00:00
|
|
|
static void SetOldSpacePageFlags(MemoryChunk* chunk,
|
|
|
|
bool is_marking,
|
|
|
|
bool is_compacting);
|
|
|
|
|
2011-09-19 18:36:47 +00:00
|
|
|
static void SetNewSpacePageFlags(NewSpacePage* chunk, bool is_marking);
|
|
|
|
|
|
|
|
void EnsureMarkingDequeIsCommitted();
|
|
|
|
|
2012-11-12 10:12:35 +00:00
|
|
|
INLINE(void ProcessMarkingDeque());
|
|
|
|
|
|
|
|
INLINE(void ProcessMarkingDeque(intptr_t bytes_to_process));
|
|
|
|
|
|
|
|
INLINE(void VisitObject(Map* map, HeapObject* obj, int size));
|
|
|
|
|
2011-09-19 18:36:47 +00:00
|
|
|
Heap* heap_;
|
|
|
|
|
|
|
|
State state_;
|
|
|
|
bool is_compacting_;
|
|
|
|
|
|
|
|
VirtualMemory* marking_deque_memory_;
|
2011-11-08 12:42:02 +00:00
|
|
|
bool marking_deque_memory_committed_;
|
2011-09-19 18:36:47 +00:00
|
|
|
MarkingDeque marking_deque_;
|
|
|
|
|
|
|
|
int steps_count_;
|
|
|
|
double steps_took_;
|
|
|
|
double longest_step_;
|
|
|
|
int64_t old_generation_space_available_at_start_of_incremental_;
|
|
|
|
int64_t old_generation_space_used_at_start_of_incremental_;
|
|
|
|
int steps_count_since_last_gc_;
|
|
|
|
double steps_took_since_last_gc_;
|
|
|
|
int64_t bytes_rescanned_;
|
|
|
|
bool should_hurry_;
|
2012-09-26 11:35:42 +00:00
|
|
|
int marking_speed_;
|
2011-11-08 10:28:58 +00:00
|
|
|
intptr_t bytes_scanned_;
|
2011-09-19 18:36:47 +00:00
|
|
|
intptr_t allocated_;
|
2012-09-26 11:35:42 +00:00
|
|
|
intptr_t write_barriers_invoked_since_last_step_;
|
2011-09-19 18:36:47 +00:00
|
|
|
|
2011-10-21 10:32:38 +00:00
|
|
|
int no_marking_scope_depth_;
|
|
|
|
|
2013-05-29 11:13:59 +00:00
|
|
|
int unscanned_bytes_of_large_object_;
|
|
|
|
|
2011-09-19 18:36:47 +00:00
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(IncrementalMarking);
|
|
|
|
};
|
|
|
|
|
|
|
|
} } // namespace v8::internal
|
|
|
|
|
|
|
|
#endif // V8_INCREMENTAL_MARKING_H_
|