]>
git.saurik.com Git - apple/javascriptcore.git/blob - runtime/WeakMapData.cpp
224be8a4668fd34c94954f559d96ccea88bd8b3a
   2  * Copyright (C) 2013 Apple Inc. All rights reserved. 
   4  * Redistribution and use in source and binary forms, with or without 
   5  * modification, are permitted provided that the following conditions 
   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. 
  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. 
  27 #include "WeakMapData.h" 
  29 #include "CopiedAllocator.h" 
  30 #include "CopyVisitorInlines.h" 
  31 #include "ExceptionHelpers.h" 
  32 #include "JSCJSValueInlines.h" 
  33 #include "SlotVisitorInlines.h" 
  35 #include <wtf/MathExtras.h> 
  39 const ClassInfo 
WeakMapData::s_info 
= { "WeakMapData", 0, 0, 0, CREATE_METHOD_TABLE(WeakMapData
) }; 
  41 WeakMapData::WeakMapData(VM
& vm
) 
  42     : Base(vm
, vm
.weakMapDataStructure
.get()) 
  43     , m_deadKeyCleaner(this) 
  47 void WeakMapData::finishCreation(VM
& vm
) 
  49     Base::finishCreation(vm
); 
  52 void WeakMapData::destroy(JSCell
* cell
) 
  54     static_cast<WeakMapData
*>(cell
)->~WeakMapData(); 
  57 void WeakMapData::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
) 
  59     Base::visitChildren(cell
, visitor
); 
  60     WeakMapData
* thisObj 
= jsCast
<WeakMapData
*>(cell
); 
  61     visitor
.addUnconditionalFinalizer(&thisObj
->m_deadKeyCleaner
); 
  62     visitor
.addWeakReferenceHarvester(&thisObj
->m_deadKeyCleaner
); 
  64     // Rough approximation of the external storage needed for the hashtable. 
  65     // This isn't exact, but it is close enough, and proportional to the actual 
  66     // external mermory usage. 
  67     visitor
.reportExtraMemoryUsage(thisObj
, thisObj
->m_map
.capacity() * (sizeof(JSObject
*) + sizeof(WriteBarrier
<Unknown
>))); 
  70 void WeakMapData::set(VM
& vm
, JSObject
* key
, JSValue value
) 
  72     // Here we force the write barrier on the key. 
  73     auto result 
= m_map
.add(WriteBarrier
<JSObject
>(vm
, this, key
).get(), WriteBarrier
<Unknown
>()); 
  74     result
.iterator
->value
.set(vm
, this, value
); 
  77 JSValue 
WeakMapData::get(JSObject
* key
) 
  79     auto iter 
= m_map
.find(key
); 
  80     if (iter 
== m_map
.end()) 
  82     return iter
->value
.get(); 
  85 bool WeakMapData::remove(JSObject
* key
) 
  87     auto iter 
= m_map
.find(key
); 
  88     if (iter 
== m_map
.end()) 
  95 bool WeakMapData::contains(JSObject
* key
) 
  97     return m_map
.contains(key
); 
 100 void WeakMapData::clear() 
 105 void WeakMapData::DeadKeyCleaner::visitWeakReferences(SlotVisitor
& visitor
) 
 108     for (auto it 
= m_target
->m_map
.begin(), end 
= m_target
->m_map
.end(); it 
!= end
; ++it
) { 
 109         if (!Heap::isMarked(it
->key
)) 
 112         visitor
.append(&it
->value
); 
 114     RELEASE_ASSERT(m_liveKeyCount 
<= m_target
->m_map
.size()); 
 117 void WeakMapData::DeadKeyCleaner::finalizeUnconditionally() 
 119     if (m_liveKeyCount 
> m_target
->m_map
.size() / 2) { 
 120         RELEASE_ASSERT(m_liveKeyCount 
<= m_target
->m_map
.size()); 
 121         int deadCount 
= m_target
->m_map
.size() - m_liveKeyCount
; 
 124         Vector
<JSObject
*> deadEntries
; 
 125         deadEntries
.reserveCapacity(deadCount
); 
 126         for (auto it 
= m_target
->m_map
.begin(), end 
= m_target
->m_map
.end(); it 
!= end
; ++it
) { 
 127             if (Heap::isMarked(it
->key
)) 
 129             deadEntries
.uncheckedAppend(it
->key
); 
 131         for (size_t i 
= 0; i 
< deadEntries
.size(); i
++) 
 132             m_target
->m_map
.remove(deadEntries
[i
]); 
 135         for (auto it 
= m_target
->m_map
.begin(), end 
= m_target
->m_map
.end(); it 
!= end
; ++it
) { 
 136             if (!Heap::isMarked(it
->key
)) 
 138             newMap
.add(it
->key
, it
->value
); 
 140         m_target
->m_map
.swap(newMap
);