Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/heap/incremental-marking-job.h"
6 :
7 : #include "src/base/platform/time.h"
8 : #include "src/heap/embedder-tracing.h"
9 : #include "src/heap/heap-inl.h"
10 : #include "src/heap/heap.h"
11 : #include "src/heap/incremental-marking.h"
12 : #include "src/isolate.h"
13 : #include "src/v8.h"
14 : #include "src/vm-state-inl.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 72886 : class IncrementalMarkingJob::Task : public CancelableTask {
20 : public:
21 : static StepResult Step(Heap* heap,
22 : EmbedderHeapTracer::EmbedderStackState stack_state);
23 :
24 : Task(Isolate* isolate, IncrementalMarkingJob* job,
25 : EmbedderHeapTracer::EmbedderStackState stack_state, TaskType task_type)
26 : : CancelableTask(isolate),
27 : isolate_(isolate),
28 : job_(job),
29 : stack_state_(stack_state),
30 36443 : task_type_(task_type) {}
31 :
32 : // CancelableTask overrides.
33 : void RunInternal() override;
34 :
35 : Isolate* isolate() const { return isolate_; }
36 :
37 : private:
38 : Isolate* const isolate_;
39 : IncrementalMarkingJob* const job_;
40 : const EmbedderHeapTracer::EmbedderStackState stack_state_;
41 : const TaskType task_type_;
42 : };
43 :
44 1031682 : void IncrementalMarkingJob::Start(Heap* heap) {
45 : DCHECK(!heap->incremental_marking()->IsStopped());
46 1031682 : ScheduleTask(heap);
47 1031682 : }
48 :
49 1087945 : void IncrementalMarkingJob::ScheduleTask(Heap* heap, TaskType task_type) {
50 2139447 : if (!IsTaskPending(task_type) && !heap->IsTearingDown()) {
51 : v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap->isolate());
52 : SetTaskPending(task_type, true);
53 : auto taskrunner =
54 36443 : V8::GetCurrentPlatform()->GetForegroundTaskRunner(isolate);
55 36443 : if (task_type == TaskType::kNormal) {
56 30925 : if (taskrunner->NonNestableTasksEnabled()) {
57 0 : taskrunner->PostNonNestableTask(base::make_unique<Task>(
58 : heap->isolate(), this,
59 0 : EmbedderHeapTracer::EmbedderStackState::kEmpty, task_type));
60 : } else {
61 30925 : taskrunner->PostTask(base::make_unique<Task>(
62 : heap->isolate(), this,
63 123700 : EmbedderHeapTracer::EmbedderStackState::kUnknown, task_type));
64 : }
65 : } else {
66 5518 : if (taskrunner->NonNestableDelayedTasksEnabled()) {
67 0 : taskrunner->PostNonNestableDelayedTask(
68 : base::make_unique<Task>(
69 : heap->isolate(), this,
70 : EmbedderHeapTracer::EmbedderStackState::kEmpty, task_type),
71 0 : kDelayInSeconds);
72 : } else {
73 5518 : taskrunner->PostDelayedTask(
74 : base::make_unique<Task>(
75 : heap->isolate(), this,
76 : EmbedderHeapTracer::EmbedderStackState::kUnknown, task_type),
77 22072 : kDelayInSeconds);
78 : }
79 : }
80 : }
81 1051502 : }
82 :
83 30248 : StepResult IncrementalMarkingJob::Task::Step(
84 : Heap* heap, EmbedderHeapTracer::EmbedderStackState stack_state) {
85 : const int kIncrementalMarkingDelayMs = 1;
86 : double deadline =
87 30248 : heap->MonotonicallyIncreasingTimeInMs() + kIncrementalMarkingDelayMs;
88 : StepResult result = heap->incremental_marking()->AdvanceWithDeadline(
89 : deadline, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD,
90 30248 : i::StepOrigin::kTask);
91 : {
92 : EmbedderStackStateScope scope(heap->local_embedder_heap_tracer(),
93 : stack_state);
94 : heap->FinalizeIncrementalMarkingIfComplete(
95 30248 : GarbageCollectionReason::kFinalizeMarkingViaTask);
96 : }
97 30248 : return result;
98 : }
99 :
100 61474 : void IncrementalMarkingJob::Task::RunInternal() {
101 : VMState<GC> state(isolate());
102 92211 : TRACE_EVENT_CALL_STATS_SCOPED(isolate(), "v8", "V8.Task");
103 :
104 30737 : Heap* heap = isolate()->heap();
105 : IncrementalMarking* incremental_marking = heap->incremental_marking();
106 30737 : if (incremental_marking->IsStopped()) {
107 1536 : if (heap->IncrementalMarkingLimitReached() !=
108 : Heap::IncrementalMarkingLimit::kNoLimit) {
109 : heap->StartIncrementalMarking(heap->GCFlagsForIncrementalMarking(),
110 : GarbageCollectionReason::kIdleTask,
111 1047 : kGCCallbackScheduleIdleGarbageCollection);
112 : }
113 : }
114 :
115 : // Clear this flag after StartIncrementalMarking call to avoid
116 : // scheduling a new task when startining incremental marking.
117 30737 : job_->SetTaskPending(task_type_, false);
118 :
119 30737 : if (!incremental_marking->IsStopped()) {
120 30248 : StepResult step_result = Step(heap, stack_state_);
121 : if (!incremental_marking->IsStopped()) {
122 : job_->ScheduleTask(heap, step_result == StepResult::kDone
123 : ? TaskType::kDelayed
124 17759 : : TaskType::kNormal);
125 : }
126 : }
127 30737 : }
128 :
129 : } // namespace internal
130 178779 : } // namespace v8
|