1/*
2 * Copyright (C) 2011 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 "HandleSet.h"
28
29#include "HandleBlock.h"
30#include "HandleBlockInlines.h"
31#include "HeapRootVisitor.h"
32#include "JSObject.h"
33#include "JSCInlines.h"
34#include <wtf/DataLog.h>
35
36namespace JSC {
37
38HandleSet::HandleSet(VM* vm)
39    : m_vm(vm)
40{
41    grow();
42}
43
44HandleSet::~HandleSet()
45{
46    while (!m_blockList.isEmpty())
47        m_vm->heap.blockAllocator().deallocate(HandleBlock::destroy(m_blockList.removeHead()));
48}
49
50void HandleSet::grow()
51{
52    HandleBlock* newBlock = HandleBlock::create(m_vm->heap.blockAllocator().allocate<HandleBlock>(), this);
53    m_blockList.append(newBlock);
54
55    for (int i = newBlock->nodeCapacity() - 1; i >= 0; --i) {
56        Node* node = newBlock->nodeAtIndex(i);
57        new (NotNull, node) Node;
58        m_freeList.push(node);
59    }
60}
61
62void HandleSet::visitStrongHandles(HeapRootVisitor& heapRootVisitor)
63{
64    Node* end = m_strongList.end();
65    for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
66#if ENABLE(GC_VALIDATION)
67        RELEASE_ASSERT(isLiveNode(node));
68#endif
69        heapRootVisitor.visit(node->slot());
70    }
71}
72
73void HandleSet::writeBarrier(HandleSlot slot, const JSValue& value)
74{
75    if (!value == !*slot && slot->isCell() == value.isCell())
76        return;
77
78    Node* node = toNode(slot);
79#if ENABLE(GC_VALIDATION)
80    RELEASE_ASSERT(isLiveNode(node));
81#endif
82    SentinelLinkedList<Node>::remove(node);
83    if (!value || !value.isCell()) {
84        m_immediateList.push(node);
85        return;
86    }
87
88    m_strongList.push(node);
89#if ENABLE(GC_VALIDATION)
90    RELEASE_ASSERT(isLiveNode(node));
91#endif
92}
93
94unsigned HandleSet::protectedGlobalObjectCount()
95{
96    unsigned count = 0;
97    Node* end = m_strongList.end();
98    for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
99        JSValue value = *node->slot();
100        if (value.isObject() && asObject(value.asCell())->isGlobalObject())
101            count++;
102    }
103    return count;
104}
105
106#if ENABLE(GC_VALIDATION) || !ASSERT_DISABLED
107bool HandleSet::isLiveNode(Node* node)
108{
109    if (node->prev()->next() != node)
110        return false;
111    if (node->next()->prev() != node)
112        return false;
113
114    return true;
115}
116#endif
117
118} // namespace JSC
119