/ runtime / WeakMapImpl.cpp
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