1/*
2 * Copyright (C) 2017 Apple Inc. All rights reserved.
3 * Copyright (C) 2017 Yusuke Suzuki <[email protected]>.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "WeakMapImpl.h"
29
30#include "IsoCellSetInlines.h"
31#include "JSCInlines.h"
32#include "WeakMapImplInlines.h"
33
34namespace JSC {
35
36template <typename WeakMapBucket>
37void WeakMapImpl<WeakMapBucket>::destroy(JSCell* cell)
38{
39 static_cast<WeakMapImpl*>(cell)->~WeakMapImpl();
40}
41
42template <typename WeakMapBucket>
43void WeakMapImpl<WeakMapBucket>::visitChildren(JSCell* cell, SlotVisitor& visitor)
44{
45 WeakMapImpl* thisObject = jsCast<WeakMapImpl*>(cell);
46 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
47 Base::visitChildren(thisObject, visitor);
48 visitor.reportExtraMemoryVisited(thisObject->m_capacity * sizeof(WeakMapBucket));
49}
50
51template <typename WeakMapBucket>
52size_t WeakMapImpl<WeakMapBucket>::estimatedSize(JSCell* cell, VM& vm)
53{
54 auto* thisObject = static_cast<WeakMapImpl*>(cell);
55 return Base::estimatedSize(thisObject, vm) + (sizeof(WeakMapImpl) - sizeof(Base)) + thisObject->m_capacity * sizeof(WeakMapBucket);
56}
57
58template <>
59void WeakMapImpl<WeakMapBucket<WeakMapBucketDataKey>>::visitOutputConstraints(JSCell*, SlotVisitor&)
60{
61 // Only JSWeakMap needs to harvest value references
62}
63
64template <>
65void WeakMapImpl<WeakMapBucket<WeakMapBucketDataKeyValue>>::visitOutputConstraints(JSCell* cell, SlotVisitor& visitor)
66{
67 VM& vm = visitor.vm();
68 auto* thisObject = jsCast<WeakMapImpl*>(cell);
69 auto locker = holdLock(thisObject->cellLock());
70 auto* buffer = thisObject->buffer();
71 for (uint32_t index = 0; index < thisObject->m_capacity; ++index) {
72 auto* bucket = buffer + index;
73 if (bucket->isEmpty() || bucket->isDeleted())
74 continue;
75 if (!vm.heap.isMarked(bucket->key()))
76 continue;
77 bucket->visitAggregate(visitor);
78 }
79}
80
81template <typename WeakMapBucket>
82template<typename Appender>
83void WeakMapImpl<WeakMapBucket>::takeSnapshotInternal(unsigned limit, Appender appender)
84{
85 DisallowGC disallowGC;
86 unsigned fetched = 0;
87 forEach([&] (JSObject* key, JSValue value) {
88 appender(key, value);
89 ++fetched;
90 if (limit && fetched >= limit)
91 return IterationState::Stop;
92 return IterationState::Continue;
93 });
94}
95
96// takeSnapshot must not invoke garbage collection since iterating WeakMap may be modified.
97template <>
98void WeakMapImpl<WeakMapBucket<WeakMapBucketDataKey>>::takeSnapshot(MarkedArgumentBuffer& buffer, unsigned limit)
99{
100 takeSnapshotInternal(limit, [&] (JSObject* key, JSValue) {
101 buffer.append(key);
102 });
103}
104
105template <>
106void WeakMapImpl<WeakMapBucket<WeakMapBucketDataKeyValue>>::takeSnapshot(MarkedArgumentBuffer& buffer, unsigned limit)
107{
108 takeSnapshotInternal(limit, [&] (JSObject* key, JSValue value) {
109 buffer.append(key);
110 buffer.append(value);
111 });
112}
113
114template class WeakMapImpl<WeakMapBucket<WeakMapBucketDataKeyValue>>;
115template class WeakMapImpl<WeakMapBucket<WeakMapBucketDataKey>>;
116
117} // namespace JSC
118