File: ObjectToIDMap.h

package info (click to toggle)
0ad 0.0.23.1-5
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 78,412 kB
  • sloc: cpp: 245,162; ansic: 200,249; javascript: 19,244; python: 13,754; sh: 6,104; perl: 4,620; makefile: 977; xml: 810; java: 533; ruby: 229; erlang: 46; pascal: 30; sql: 21; tcl: 4
file content (132 lines) | stat: -rw-r--r-- 3,134 bytes parent folder | download | duplicates (4)
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