diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/runtime/WeakMapData.cpp | |
parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
download | qtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz |
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f
Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/JavaScriptCore/runtime/WeakMapData.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/WeakMapData.cpp | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/runtime/WeakMapData.cpp b/Source/JavaScriptCore/runtime/WeakMapData.cpp new file mode 100644 index 000000000..1332e8e06 --- /dev/null +++ b/Source/JavaScriptCore/runtime/WeakMapData.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WeakMapData.h" + +#include "CopiedAllocator.h" +#include "CopyVisitorInlines.h" +#include "ExceptionHelpers.h" +#include "JSCJSValueInlines.h" +#include "SlotVisitorInlines.h" + +#include <wtf/MathExtras.h> + +namespace JSC { + +const ClassInfo WeakMapData::s_info = { "WeakMapData", 0, 0, CREATE_METHOD_TABLE(WeakMapData) }; + +WeakMapData::WeakMapData(VM& vm) + : Base(vm, vm.weakMapDataStructure.get()) + , m_deadKeyCleaner(this) +{ +} + +void WeakMapData::finishCreation(VM& vm) +{ + Base::finishCreation(vm); +} + +void WeakMapData::destroy(JSCell* cell) +{ + static_cast<WeakMapData*>(cell)->~WeakMapData(); +} + +size_t WeakMapData::estimatedSize(JSCell* cell) +{ + WeakMapData* thisObj = jsCast<WeakMapData*>(cell); + return Base::estimatedSize(cell) + (thisObj->m_map.capacity() * (sizeof(JSObject*) + sizeof(WriteBarrier<Unknown>))); +} + +void WeakMapData::visitChildren(JSCell* cell, SlotVisitor& visitor) +{ + Base::visitChildren(cell, visitor); + WeakMapData* thisObj = jsCast<WeakMapData*>(cell); + visitor.addUnconditionalFinalizer(&thisObj->m_deadKeyCleaner); + visitor.addWeakReferenceHarvester(&thisObj->m_deadKeyCleaner); + + // Rough approximation of the external storage needed for the hashtable. + // This isn't exact, but it is close enough, and proportional to the actual + // external memory usage. + visitor.reportExtraMemoryVisited(thisObj->m_map.capacity() * (sizeof(JSObject*) + sizeof(WriteBarrier<Unknown>))); +} + +void WeakMapData::set(VM& vm, JSObject* key, JSValue value) +{ + // Here we force the write barrier on the key. + auto result = m_map.add(WriteBarrier<JSObject>(vm, this, key).get(), WriteBarrier<Unknown>()); + result.iterator->value.set(vm, this, value); +} + +JSValue WeakMapData::get(JSObject* key) +{ + auto iter = m_map.find(key); + if (iter == m_map.end()) + return jsUndefined(); + return iter->value.get(); +} + +bool WeakMapData::remove(JSObject* key) +{ + auto iter = m_map.find(key); + if (iter == m_map.end()) + return false; + + m_map.remove(iter); + return true; +} + +bool WeakMapData::contains(JSObject* key) +{ + return m_map.contains(key); +} + +void WeakMapData::clear() +{ + m_map.clear(); +} + +void WeakMapData::DeadKeyCleaner::visitWeakReferences(SlotVisitor& visitor) +{ + m_liveKeyCount = 0; + for (auto it = m_target->m_map.begin(), end = m_target->m_map.end(); it != end; ++it) { + if (!Heap::isMarked(it->key)) + continue; + m_liveKeyCount++; + visitor.append(&it->value); + } + RELEASE_ASSERT(m_liveKeyCount <= m_target->m_map.size()); +} + +void WeakMapData::DeadKeyCleaner::finalizeUnconditionally() +{ + if (m_liveKeyCount > m_target->m_map.size() / 2) { + RELEASE_ASSERT(m_liveKeyCount <= m_target->m_map.size()); + int deadCount = m_target->m_map.size() - m_liveKeyCount; + if (!deadCount) + return; + Vector<JSObject*> deadEntries; + deadEntries.reserveCapacity(deadCount); + for (auto it = m_target->m_map.begin(), end = m_target->m_map.end(); it != end; ++it) { + if (Heap::isMarked(it->key)) + continue; + deadEntries.uncheckedAppend(it->key); + } + for (size_t i = 0; i < deadEntries.size(); i++) + m_target->m_map.remove(deadEntries[i]); + } else { + MapType newMap; + for (auto it = m_target->m_map.begin(), end = m_target->m_map.end(); it != end; ++it) { + if (!Heap::isMarked(it->key)) + continue; + newMap.add(it->key, it->value); + } + m_target->m_map.swap(newMap); + } +} + +} |