[JSC] Weak should only accept cell pointees.
[WebKit-https.git] / Source / JavaScriptCore / heap / WeakBlock.cpp
1 /*
2  * Copyright (C) 2012 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WeakBlock.h"
28
29 #include "Heap.h"
30 #include "HeapRootVisitor.h"
31 #include "JSObject.h"
32 #include "JSCInlines.h"
33 #include "Structure.h"
34
35 namespace JSC {
36
37 WeakBlock* WeakBlock::create(MarkedBlock& markedBlock)
38 {
39     return new (NotNull, fastMalloc(blockSize)) WeakBlock(markedBlock);
40 }
41
42 void WeakBlock::destroy(WeakBlock* block)
43 {
44     block->~WeakBlock();
45     fastFree(block);
46 }
47
48 WeakBlock::WeakBlock(MarkedBlock& markedBlock)
49     : DoublyLinkedListNode<WeakBlock>()
50     , m_markedBlock(&markedBlock)
51 {
52     for (size_t i = 0; i < weakImplCount(); ++i) {
53         WeakImpl* weakImpl = &weakImpls()[i];
54         new (NotNull, weakImpl) WeakImpl;
55         addToFreeList(&m_sweepResult.freeList, weakImpl);
56     }
57
58     ASSERT(isEmpty());
59 }
60
61 void WeakBlock::lastChanceToFinalize()
62 {
63     for (size_t i = 0; i < weakImplCount(); ++i) {
64         WeakImpl* weakImpl = &weakImpls()[i];
65         if (weakImpl->state() >= WeakImpl::Finalized)
66             continue;
67         weakImpl->setState(WeakImpl::Dead);
68         finalize(weakImpl);
69     }
70 }
71
72 void WeakBlock::sweep()
73 {
74     // If a block is completely empty, a sweep won't have any effect.
75     if (isEmpty())
76         return;
77
78     SweepResult sweepResult;
79     for (size_t i = 0; i < weakImplCount(); ++i) {
80         WeakImpl* weakImpl = &weakImpls()[i];
81         if (weakImpl->state() == WeakImpl::Dead)
82             finalize(weakImpl);
83         if (weakImpl->state() == WeakImpl::Deallocated)
84             addToFreeList(&sweepResult.freeList, weakImpl);
85         else {
86             sweepResult.blockIsFree = false;
87             if (weakImpl->state() == WeakImpl::Live)
88                 sweepResult.blockIsLogicallyEmpty = false;
89         }
90     }
91
92     m_sweepResult = sweepResult;
93     ASSERT(!m_sweepResult.isNull());
94 }
95
96 void WeakBlock::visit(HeapRootVisitor& heapRootVisitor)
97 {
98     // If a block is completely empty, a visit won't have any effect.
99     if (isEmpty())
100         return;
101
102     // If this WeakBlock doesn't belong to a MarkedBlock, we won't even be here.
103     ASSERT(m_markedBlock);
104
105     if (m_markedBlock->isAllocated())
106         return;
107
108     SlotVisitor& visitor = heapRootVisitor.visitor();
109
110     for (size_t i = 0; i < weakImplCount(); ++i) {
111         WeakImpl* weakImpl = &weakImpls()[i];
112         if (weakImpl->state() != WeakImpl::Live)
113             continue;
114
115         if (m_markedBlock->isMarkedOrNewlyAllocated(weakImpl->m_cell))
116             continue;
117
118         WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner();
119         if (!weakHandleOwner)
120             continue;
121
122         if (!weakHandleOwner->isReachableFromOpaqueRoots(*weakImpl->m_cell, weakImpl->context(), visitor))
123             continue;
124
125         heapRootVisitor.visit(&weakImpl->m_cell);
126     }
127 }
128
129 void WeakBlock::reap()
130 {
131     // If a block is completely empty, a reaping won't have any effect.
132     if (isEmpty())
133         return;
134
135     // If this WeakBlock doesn't belong to a MarkedBlock, we won't even be here.
136     ASSERT(m_markedBlock);
137
138     if (m_markedBlock->isAllocated())
139         return;
140
141     for (size_t i = 0; i < weakImplCount(); ++i) {
142         WeakImpl* weakImpl = &weakImpls()[i];
143         if (weakImpl->state() > WeakImpl::Dead)
144             continue;
145
146         if (m_markedBlock->isMarkedOrNewlyAllocated(weakImpl->cell())) {
147             ASSERT(weakImpl->state() == WeakImpl::Live);
148             continue;
149         }
150
151         weakImpl->setState(WeakImpl::Dead);
152     }
153 }
154
155 } // namespace JSC