MarkedBlock should know what objects are live during marking
[WebKit-https.git] / Source / JavaScriptCore / heap / MarkedBlockInlines.h
1 /*
2  * Copyright (C) 2016 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 "MarkedAllocator.h"
29 #include "MarkedBlock.h"
30 #include "MarkedSpace.h"
31
32 namespace JSC {
33
34 inline unsigned MarkedBlock::Handle::cellsPerBlock()
35 {
36     return MarkedSpace::blockPayload / cellSize();
37 }
38
39 inline bool MarkedBlock::marksConveyLivenessDuringMarking(HeapVersion markingVersion)
40 {
41     // This returns true if any of these is true:
42     // - We just created the block and so the bits are clear already.
43     // - This block has objects marked during the last GC, and so its version was up-to-date just
44     //   before the current collection did beginMarking(). This means that any objects that have 
45     //   their mark bit set are valid objects that were never deleted, and so are candidates for
46     //   marking in any conservative scan. Using our jargon, they are "live".
47     // - We did ~2^32 collections and rotated the version back to null, so we needed to hard-reset
48     //   everything. If the marks had been stale, we would have cleared them. So, we can be sure that
49     //   any set mark bit reflects objects marked during last GC, i.e. "live" objects.
50     // It would be absurd to use this method when not collecting, since this special "one version
51     // back" state only makes sense when we're in a concurrent collection and have to be
52     // conservative.
53     ASSERT(space()->isMarking());
54     return m_markingVersion == MarkedSpace::nullVersion
55         || MarkedSpace::nextVersion(m_markingVersion) == markingVersion;
56 }
57
58 inline bool MarkedBlock::Handle::isLive(HeapVersion markingVersion, bool isMarking, const HeapCell* cell)
59 {
60     ASSERT(!isFreeListed());
61     
62     if (UNLIKELY(hasAnyNewlyAllocated())) {
63         if (isNewlyAllocated(cell))
64             return true;
65     }
66     
67     if (allocator()->isAllocated(this))
68         return true;
69     
70     MarkedBlock& block = this->block();
71     
72     if (block.areMarksStale()) {
73         if (!isMarking)
74             return false;
75         if (!block.marksConveyLivenessDuringMarking(markingVersion))
76             return false;
77     }
78
79     return block.m_marks.get(block.atomNumber(cell));
80 }
81
82 inline bool MarkedBlock::Handle::isLiveCell(HeapVersion markingVersion, bool isMarking, const void* p)
83 {
84     if (!m_block->isAtom(p))
85         return false;
86     return isLive(markingVersion, isMarking, static_cast<const HeapCell*>(p));
87 }
88
89 inline bool MarkedBlock::Handle::isNewlyAllocatedStale() const
90 {
91     return m_newlyAllocatedVersion != space()->newlyAllocatedVersion();
92 }
93
94 inline bool MarkedBlock::Handle::hasAnyNewlyAllocated()
95 {
96     return !isNewlyAllocatedStale();
97 }
98
99 template <typename Functor>
100 inline IterationStatus MarkedBlock::Handle::forEachLiveCell(const Functor& functor)
101 {
102     HeapCell::Kind kind = m_attributes.cellKind;
103     for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
104         HeapCell* cell = reinterpret_cast_ptr<HeapCell*>(&m_block->atoms()[i]);
105         if (!isLive(cell))
106             continue;
107
108         if (functor(cell, kind) == IterationStatus::Done)
109             return IterationStatus::Done;
110     }
111     return IterationStatus::Continue;
112 }
113
114 template <typename Functor>
115 inline IterationStatus MarkedBlock::Handle::forEachDeadCell(const Functor& functor)
116 {
117     HeapCell::Kind kind = m_attributes.cellKind;
118     for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
119         HeapCell* cell = reinterpret_cast_ptr<HeapCell*>(&m_block->atoms()[i]);
120         if (isLive(cell))
121             continue;
122
123         if (functor(cell, kind) == IterationStatus::Done)
124             return IterationStatus::Done;
125     }
126     return IterationStatus::Continue;
127 }
128
129 inline Heap* MarkedBlock::heap() const
130 {
131     return &vm()->heap;
132 }
133
134 inline MarkedSpace* MarkedBlock::space() const
135 {
136     return &heap()->objectSpace();
137 }
138
139 inline MarkedSpace* MarkedBlock::Handle::space() const
140 {
141     return &heap()->objectSpace();
142 }
143
144 } // namespace JSC
145