Bug 878160 - GC: post barrier weak references in the browser - part 1 JS engine r=terrence

--HG--
extra : rebase_source : 4dfd4f8f46564d3a9858646a0f68c9047c2f7e93
This commit is contained in:
Jon Coppeard 2013-07-02 09:43:45 +01:00
parent e77f65c20f
commit 32a8cfef5d
5 changed files with 64 additions and 5 deletions

View File

@ -255,6 +255,14 @@ class HashMap
remove(p);
}
// Infallibly rekey one entry, if present.
void rekey(const Lookup &old_key, const Key &new_key) {
if (old_key != new_key) {
if (Ptr p = lookup(old_key))
impl.rekey(p, new_key, new_key);
}
}
// HashMap is movable
HashMap(MoveRef<HashMap> rhs) : impl(Move(rhs->impl)) {}
void operator=(MoveRef<HashMap> rhs) { impl = Move(rhs->impl); }
@ -802,10 +810,7 @@ class HashTable : private AllocPolicy
// a new key at the new Lookup position. |front()| is invalid after
// this operation until the next call to |popFront()|.
void rekeyFront(const Lookup &l, const Key &k) {
typename HashTableEntry<T>::NonConstT t(Move(this->cur->get()));
HashPolicy::setKey(t, const_cast<Key &>(k));
table.remove(*this->cur);
table.putNewInfallible(l, Move(t));
table.rekey(*this->cur, l, k);
rekeyed = true;
this->validEntry = false;
}
@ -1453,6 +1458,17 @@ class HashTable : private AllocPolicy
checkUnderloaded();
}
void rekey(Ptr p, const Lookup &l, const Key &k)
{
JS_ASSERT(table);
ReentrancyGuard g(*this);
JS_ASSERT(p.found());
typename HashTableEntry<T>::NonConstT t(Move(*p));
HashPolicy::setKey(t, const_cast<Key &>(k));
remove(*p.entry_);
putNewInfallible(l, Move(t));
}
#undef METER
};

View File

@ -203,8 +203,11 @@ class Heap : public js::HeapBase<T>
relocate();
}
bool operator!=(const T &other) const { return ptr != other; }
bool operator==(const Heap<T> &other) { return ptr == other.ptr; }
bool operator!=(const Heap<T> &other) { return ptr != other.ptr; }
bool operator==(const T &other) const { return ptr == other; }
bool operator!=(const T &other) const { return ptr != other; }
operator T() const { return ptr; }
T operator->() const { return ptr; }

View File

@ -212,6 +212,9 @@ class StoreBuffer
void put(const T &t) {
JS_ASSERT(!owner->inParallelSection());
/* Ensure T is derived from BufferableRef. */
(void)static_cast<const BufferableRef*>(&t);
/* Check if we have been enabled. */
if (!pos)
return;
@ -348,6 +351,22 @@ class StoreBuffer
void mark(JSTracer *trc);
};
class CallbackRef : public BufferableRef
{
public:
typedef void (*MarkCallback)(JSTracer *trc, void *key);
CallbackRef(MarkCallback cb, void *k) : callback(cb), key(k) {}
virtual void mark(JSTracer *trc) {
callback(trc, key);
}
private:
MarkCallback callback;
void *key;
};
MonoTypeBuffer<ValueEdge> bufferVal;
MonoTypeBuffer<CellPtrEdge> bufferCell;
MonoTypeBuffer<SlotEdge> bufferSlot;
@ -429,6 +448,11 @@ class StoreBuffer
bufferGeneric.put(t);
}
/* Insert or update a callback entry. */
void putCallback(CallbackRef::MarkCallback callback, void *key) {
bufferGeneric.put(CallbackRef(callback, key));
}
/* Mark the source of all edges in the store buffer. */
void mark(JSTracer *trc);

View File

@ -1123,3 +1123,11 @@ js::IsInRequest(JSContext *cx)
return !!cx->runtime()->requestDepth;
}
#endif
#ifdef JSGC_GENERATIONAL
JS_FRIEND_API(void)
JS_StorePostBarrierCallback(JSContext* cx, void (*callback)(JSTracer *trc, void *key), void *key)
{
cx->runtime()->gcStoreBuffer.putCallback(callback, key);
}
#endif /* JSGC_GENERATIONAL */

View File

@ -1762,4 +1762,12 @@ js_DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg,
extern JS_FRIEND_API(JSBool)
js_ReportIsNotFunction(JSContext *cx, const JS::Value& v);
#ifdef JSGC_GENERATIONAL
extern JS_FRIEND_API(void)
JS_StorePostBarrierCallback(JSContext* cx, void (*callback)(JSTracer *trc, void *key), void *key);
#else
inline void
JS_StorePostBarrierCallback(JSContext* cx, void (*callback)(JSTracer *trc, void *key), void *key) {}
#endif /* JSGC_GENERATIONAL */
#endif /* jsfriendapi_h */