Optimize WeakBlock's "reap" and "visit" operations.
[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         const JSValue& jsValue = weakImpl->jsValue();
116         if (m_markedBlock->isMarkedOrNewlyAllocated(jsValue.asCell()))
117             continue;
118
119         WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner();
120         if (!weakHandleOwner)
121             continue;
122
123         if (!weakHandleOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(jsValue)), weakImpl->context(), visitor))
124             continue;
125
126         heapRootVisitor.visit(&const_cast<JSValue&>(jsValue));
127     }
128 }
129
130 void WeakBlock::reap()
131 {
132     // If a block is completely empty, a reaping won't have any effect.
133     if (isEmpty())
134         return;
135
136     // If this WeakBlock doesn't belong to a MarkedBlock, we won't even be here.
137     ASSERT(m_markedBlock);
138
139     if (m_markedBlock->isAllocated())
140         return;
141
142     for (size_t i = 0; i < weakImplCount(); ++i) {
143         WeakImpl* weakImpl = &weakImpls()[i];
144         if (weakImpl->state() > WeakImpl::Dead)
145             continue;
146
147         if (m_markedBlock->isMarkedOrNewlyAllocated(weakImpl->jsValue().asCell())) {
148             ASSERT(weakImpl->state() == WeakImpl::Live);
149             continue;
150         }
151
152         weakImpl->setState(WeakImpl::Dead);
153     }
154 }
155
156 } // namespace JSC