1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Providing a map-like structure with JSObject pointers (actually their hash) as keys
* with correct garbage collection handling (JSObjects can move in memory).
*
* The code in this class was copied from here and modified to work in our environment.
* * https://mxr.mozilla.org/mozilla-esr38/source/js/ipc/JavaScriptShared.h
* * https://mxr.mozilla.org/mozilla-esr38/source/js/ipc/JavaScriptShared.cpp
*
* When updating SpiderMonkey, you most likely have to reintegrate an updated version
* of the class(es) in this file. The best way is probably to get a diff between the
* original files and integrate that because this file is heavily modified from the
* original version.
*/
#ifndef INCLUDED_OBJECTTOIDMAP
#define INCLUDED_OBJECTTOIDMAP
#include "scriptinterface/ScriptRuntime.h"
#include "scriptinterface/ScriptTypes.h"
#include <stdint.h>
// Map JSObjects -> ids
template <typename T>
class ObjectIdCache
{
typedef js::PointerHasher<JSObject*, 3> Hasher;
typedef js::HashMap<JSObject*, T, Hasher, js::SystemAllocPolicy> Table;
NONCOPYABLE(ObjectIdCache);
public:
ObjectIdCache(shared_ptr<ScriptRuntime> rt)
: table_(nullptr), m_rt(rt)
{
}
~ObjectIdCache()
{
if (table_)
{
m_rt->AddDeferredFinalizationObject(std::shared_ptr<void>((void*)table_, DeleteTable));
table_ = nullptr;
JS_RemoveExtraGCRootsTracer(m_rt->m_rt, ObjectIdCache::Trace, this);
}
}
bool init()
{
if (table_)
return true;
table_ = new Table(js::SystemAllocPolicy());
JS_AddExtraGCRootsTracer(m_rt->m_rt, ObjectIdCache::Trace, this);
return table_ && table_->init(32);
}
void trace(JSTracer* trc)
{
for (typename Table::Enum e(*table_); !e.empty(); e.popFront())
{
JSObject* obj = e.front().key();
JS_CallUnbarrieredObjectTracer(trc, &obj, "ipc-object");
if (obj != e.front().key())
e.rekeyFront(obj);
}
}
// TODO sweep?
bool find(JSObject* obj, T& ret)
{
typename Table::Ptr p = table_->lookup(obj);
if (!p)
return false;
ret = p->value();
return true;
}
bool add(JSContext* cx, JSObject* obj, T id)
{
if (!table_->put(obj, id))
return false;
JS_StoreObjectPostBarrierCallback(cx, keyMarkCallback, obj, table_);
return true;
}
void remove(JSObject* obj)
{
table_->remove(obj);
}
// TODO clear?
bool empty()
{
return table_->empty();
}
bool has(JSObject* obj)
{
return table_->has(obj);
}
private:
static void keyMarkCallback(JSTracer* trc, JSObject* key, void* data)
{
Table* table = static_cast<Table*>(data);
JSObject* prior = key;
JS_CallUnbarrieredObjectTracer(trc, &key, "ObjectIdCache::table_ key");
table->rekeyIfMoved(prior, key);
}
static void Trace(JSTracer* trc, void* data)
{
reinterpret_cast<ObjectIdCache*>(data)->trace(trc);
}
static void DeleteTable(void* table)
{
delete (Table*)table;
}
shared_ptr<ScriptRuntime> m_rt;
Table* table_;
};
#endif // INCLUDED_OBJECTTOIDMAP
|