WeakMapImpl.cpp
1 /* 2 * Copyright (C) 2017 Apple Inc. All rights reserved. 3 * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>. 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 "AuxiliaryBarrierInlines.h" 31 #include "StructureInlines.h" 32 #include "WeakMapImplInlines.h" 33 34 namespace JSC { 35 36 template <typename WeakMapBucket> 37 void WeakMapImpl<WeakMapBucket>::destroy(JSCell* cell) 38 { 39 static_cast<WeakMapImpl*>(cell)->~WeakMapImpl(); 40 } 41 42 template <typename WeakMapBucket> 43 void 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 51 template <typename WeakMapBucket> 52 size_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 58 template <> 59 void WeakMapImpl<WeakMapBucket<WeakMapBucketDataKey>>::visitOutputConstraints(JSCell*, SlotVisitor&) 60 { 61 // Only JSWeakMap needs to harvest value references 62 } 63 64 template <> 65 void 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 81 template <typename WeakMapBucket> 82 template<typename Appender> 83 void 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. 97 template <> 98 void WeakMapImpl<WeakMapBucket<WeakMapBucketDataKey>>::takeSnapshot(MarkedArgumentBuffer& buffer, unsigned limit) 99 { 100 takeSnapshotInternal(limit, [&] (JSObject* key, JSValue) { 101 buffer.append(key); 102 }); 103 } 104 105 template <> 106 void 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 114 template class WeakMapImpl<WeakMapBucket<WeakMapBucketDataKeyValue>>; 115 template class WeakMapImpl<WeakMapBucket<WeakMapBucketDataKey>>; 116 117 } // namespace JSC