1/*
2 * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "CellList.h"
29#include "Heap.h"
30#include <wtf/MonotonicTime.h>
31#include <wtf/ScopedLambda.h>
32#include <wtf/UniqueArray.h>
33
34namespace JSC {
35
36class JSCell;
37class MarkedBlock;
38
39class HeapVerifier {
40 WTF_MAKE_FAST_ALLOCATED;
41public:
42 enum class Phase {
43 BeforeGC,
44 BeforeMarking,
45 AfterMarking,
46 AfterGC
47 };
48
49 HeapVerifier(Heap*, unsigned numberOfGCCyclesToRecord);
50
51 void startGC();
52 void endGC();
53
54 void gatherLiveCells(Phase);
55 void trimDeadCells();
56 void verify(Phase);
57
58 static const char* phaseName(Phase);
59
60 // Scans all previously recorded CellLists and checks if the specified
61 // cell was in any of those lists.
62 JS_EXPORT_PRIVATE static void checkIfRecorded(uintptr_t maybeCell);
63
64 // Returns false if anything is found to be inconsistent/incorrect about the specified cell.
65 JS_EXPORT_PRIVATE static bool validateCell(HeapCell*, VM* expectedVM = nullptr);
66
67private:
68 struct GCCycle {
69 WTF_MAKE_STRUCT_FAST_ALLOCATED;
70
71 GCCycle()
72 : before("Before Marking")
73 , after("After Marking")
74 {
75 }
76
77 void reset()
78 {
79 before.reset();
80 after.reset();
81 }
82
83 CollectionScope scope;
84 MonotonicTime timestamp;
85 CellList before;
86 CellList after;
87 };
88
89 void incrementCycle() { m_currentCycle = (m_currentCycle + 1) % m_numberOfCycles; }
90 GCCycle& currentCycle() { return m_cycles[m_currentCycle]; }
91 GCCycle& cycleForIndex(int cycleIndex)
92 {
93 ASSERT(cycleIndex <= 0 && cycleIndex > -m_numberOfCycles);
94 cycleIndex += m_currentCycle;
95 if (cycleIndex < 0)
96 cycleIndex += m_numberOfCycles;
97 ASSERT(cycleIndex < m_numberOfCycles);
98 return m_cycles[cycleIndex];
99 }
100
101 CellList* cellListForGathering(Phase);
102 bool verifyCellList(Phase, CellList&);
103 static bool validateJSCell(VM* expectedVM, JSCell*, CellProfile*, CellList*, const ScopedLambda<void()>& printHeaderIfNeeded, const char* prefix = "");
104
105 void printVerificationHeader();
106
107 void checkIfRecorded(HeapCell* maybeHeapCell);
108 void reportCell(CellProfile&, int cycleIndex, HeapVerifier::GCCycle&, CellList&, const char* prefix = nullptr);
109
110 Heap* m_heap;
111 int m_currentCycle;
112 int m_numberOfCycles;
113 bool m_didPrintLogs { false };
114 UniqueArray<GCCycle> m_cycles;
115};
116
117} // namespace JSC
118