mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1047120 - PurpleBuffer doesn't actually need to use Heap<T>; r=mccr8,jonco
This commit is contained in:
parent
412332301d
commit
b282e9647a
@ -8,6 +8,7 @@
|
||||
#define js_RootingAPI_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/GuardObjects.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/NullPtr.h"
|
||||
@ -166,6 +167,23 @@ struct JS_PUBLIC_API(NullPtr)
|
||||
static void * const constNullValue;
|
||||
};
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
JS_FRIEND_API(void) HeapCellPostBarrier(js::gc::Cell **cellp);
|
||||
JS_FRIEND_API(void) HeapCellRelocate(js::gc::Cell **cellp);
|
||||
#endif
|
||||
|
||||
#ifdef JS_DEBUG
|
||||
/*
|
||||
* For generational GC, assert that an object is in the tenured generation as
|
||||
* opposed to being in the nursery.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
AssertGCThingMustBeTenured(JSObject* obj);
|
||||
#else
|
||||
inline void
|
||||
AssertGCThingMustBeTenured(JSObject *obj) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The Heap<T> class is a heap-stored reference to a JS GC thing. All members of
|
||||
* heap classes that refer to GC things should use Heap<T> (or possibly
|
||||
@ -285,18 +303,6 @@ class Heap : public js::HeapBase<T>
|
||||
T ptr;
|
||||
};
|
||||
|
||||
#ifdef JS_DEBUG
|
||||
/*
|
||||
* For generational GC, assert that an object is in the tenured generation as
|
||||
* opposed to being in the nursery.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
AssertGCThingMustBeTenured(JSObject* obj);
|
||||
#else
|
||||
inline void
|
||||
AssertGCThingMustBeTenured(JSObject *obj) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The TenuredHeap<T> class is similar to the Heap<T> class above in that it
|
||||
* encapsulates the GC concerns of an on-heap reference to a JS object. However,
|
||||
@ -560,11 +566,6 @@ class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T>
|
||||
void operator=(MutableHandle other) MOZ_DELETE;
|
||||
};
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
JS_FRIEND_API(void) HeapCellPostBarrier(js::gc::Cell **cellp);
|
||||
JS_FRIEND_API(void) HeapCellRelocate(js::gc::Cell **cellp);
|
||||
#endif
|
||||
|
||||
} /* namespace JS */
|
||||
|
||||
namespace js {
|
||||
@ -666,6 +667,12 @@ struct GCMethods<JSObject *>
|
||||
{
|
||||
static JSObject *initial() { return nullptr; }
|
||||
static bool poisoned(JSObject *v) { return JS::IsPoisonedPtr(v); }
|
||||
static gc::Cell *asGCThingOrNull(JSObject *v) {
|
||||
if (!v)
|
||||
return nullptr;
|
||||
JS_ASSERT(uintptr_t(v) > 32);
|
||||
return reinterpret_cast<gc::Cell *>(v);
|
||||
}
|
||||
static bool needsPostBarrier(JSObject *v) {
|
||||
return v != nullptr && gc::IsInsideNursery(reinterpret_cast<gc::Cell *>(v));
|
||||
}
|
||||
@ -1246,6 +1253,24 @@ class CompilerRootNode
|
||||
js::gc::Cell *ptr_;
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
namespace gc {
|
||||
|
||||
template <typename T, typename TraceCallbacks>
|
||||
void
|
||||
CallTraceCallbackOnNonHeap(T *v, const TraceCallbacks &aCallbacks, const char *aName, void *aClosure)
|
||||
{
|
||||
static_assert(sizeof(T) == sizeof(JS::Heap<T>), "T and Heap<T> must be compatible.");
|
||||
MOZ_ASSERT(v);
|
||||
mozilla::DebugOnly<Cell *> cell = GCMethods<T>::asGCThingOrNull(*v);
|
||||
MOZ_ASSERT(cell);
|
||||
MOZ_ASSERT(!IsInsideNursery(cell));
|
||||
JS::Heap<T> *asHeapT = reinterpret_cast<JS::Heap<T>*>(v);
|
||||
aCallbacks.Trace(asHeapT, aName, aClosure);
|
||||
MOZ_ASSERT(GCMethods<T>::asGCThingOrNull(*v) == cell);
|
||||
}
|
||||
|
||||
} /* namespace gc */
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* js_RootingAPI_h */
|
||||
|
@ -1637,6 +1637,9 @@ template <> struct GCMethods<JS::Value>
|
||||
static bool poisoned(const JS::Value &v) {
|
||||
return v.isMarkable() && JS::IsPoisonedPtr(v.toGCThing());
|
||||
}
|
||||
static gc::Cell *asGCThingOrNull(const JS::Value &v) {
|
||||
return v.isMarkable() ? v.toGCThing() : nullptr;
|
||||
}
|
||||
static bool needsPostBarrier(const JS::Value &v) {
|
||||
return v.isObject() && gc::IsInsideNursery(reinterpret_cast<gc::Cell*>(&v.toObject()));
|
||||
}
|
||||
|
@ -2521,7 +2521,6 @@ class JSPurpleBuffer
|
||||
{
|
||||
MOZ_ASSERT(mValues.IsEmpty());
|
||||
MOZ_ASSERT(mObjects.IsEmpty());
|
||||
MOZ_ASSERT(mTenuredObjects.IsEmpty());
|
||||
}
|
||||
|
||||
public:
|
||||
@ -2538,7 +2537,6 @@ public:
|
||||
mReferenceToThis = nullptr;
|
||||
mValues.Clear();
|
||||
mObjects.Clear();
|
||||
mTenuredObjects.Clear();
|
||||
mozilla::DropJSObjects(this);
|
||||
NS_RELEASE_THIS();
|
||||
}
|
||||
@ -2547,9 +2545,13 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(JSPurpleBuffer)
|
||||
|
||||
JSPurpleBuffer*& mReferenceToThis;
|
||||
SegmentedArray<JS::Heap<JS::Value>> mValues;
|
||||
SegmentedArray<JS::Heap<JSObject*>> mObjects;
|
||||
SegmentedArray<JS::TenuredHeap<JSObject*>> mTenuredObjects;
|
||||
|
||||
// These are raw pointers instead of Heap<T> because we only need Heap<T> for
|
||||
// pointers which may point into the nursery. The purple buffer never contains
|
||||
// pointers to the nursery because nursery gcthings can never be gray and only
|
||||
// gray things can be inserted into the purple buffer.
|
||||
SegmentedArray<JS::Value> mValues;
|
||||
SegmentedArray<JSObject*> mObjects;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(JSPurpleBuffer)
|
||||
@ -2563,21 +2565,21 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(JSPurpleBuffer)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
#define NS_TRACE_SEGMENTED_ARRAY(_field) \
|
||||
{ \
|
||||
auto segment = tmp->_field.GetFirstSegment(); \
|
||||
while (segment) { \
|
||||
for (uint32_t i = segment->Length(); i > 0;) { \
|
||||
aCallbacks.Trace(&segment->ElementAt(--i), #_field, aClosure); \
|
||||
} \
|
||||
segment = segment->getNext(); \
|
||||
} \
|
||||
}
|
||||
#define NS_TRACE_SEGMENTED_ARRAY(_field, _type) \
|
||||
{ \
|
||||
auto segment = tmp->_field.GetFirstSegment(); \
|
||||
while (segment) { \
|
||||
for (uint32_t i = segment->Length(); i > 0;) { \
|
||||
js::gc::CallTraceCallbackOnNonHeap<_type, TraceCallbacks>( \
|
||||
&segment->ElementAt(--i), aCallbacks, #_field, aClosure); \
|
||||
} \
|
||||
segment = segment->getNext(); \
|
||||
} \
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(JSPurpleBuffer)
|
||||
NS_TRACE_SEGMENTED_ARRAY(mValues)
|
||||
NS_TRACE_SEGMENTED_ARRAY(mObjects)
|
||||
NS_TRACE_SEGMENTED_ARRAY(mTenuredObjects)
|
||||
NS_TRACE_SEGMENTED_ARRAY(mValues, JS::Value)
|
||||
NS_TRACE_SEGMENTED_ARRAY(mObjects, JSObject*)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(JSPurpleBuffer, AddRef)
|
||||
@ -2644,10 +2646,12 @@ public:
|
||||
virtual void Trace(JS::Heap<JS::Value>* aValue, const char* aName,
|
||||
void* aClosure) const
|
||||
{
|
||||
if (aValue->isMarkable()) {
|
||||
void* thing = aValue->toGCThing();
|
||||
JS::Value val = *aValue;
|
||||
if (val.isMarkable()) {
|
||||
void* thing = val.toGCThing();
|
||||
if (thing && xpc_GCThingIsGrayCCThing(thing)) {
|
||||
mCollector->GetJSPurpleBuffer()->mValues.AppendElement(*aValue);
|
||||
MOZ_ASSERT(!js::gc::IsInsideNursery((js::gc::Cell *)thing));
|
||||
mCollector->GetJSPurpleBuffer()->mValues.AppendElement(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2657,20 +2661,24 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void AppendJSObjectToPurpleBuffer(JSObject *obj) const
|
||||
{
|
||||
if (obj && xpc_GCThingIsGrayCCThing(obj)) {
|
||||
MOZ_ASSERT(!js::gc::IsInsideNursery(JS::AsCell(obj)));
|
||||
mCollector->GetJSPurpleBuffer()->mObjects.AppendElement(obj);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Trace(JS::Heap<JSObject*>* aObject, const char* aName,
|
||||
void* aClosure) const
|
||||
{
|
||||
if (*aObject && xpc_GCThingIsGrayCCThing(*aObject)) {
|
||||
mCollector->GetJSPurpleBuffer()->mObjects.AppendElement(*aObject);
|
||||
}
|
||||
AppendJSObjectToPurpleBuffer(*aObject);
|
||||
}
|
||||
|
||||
virtual void Trace(JS::TenuredHeap<JSObject*>* aObject, const char* aName,
|
||||
void* aClosure) const
|
||||
{
|
||||
if (*aObject && xpc_GCThingIsGrayCCThing(*aObject)) {
|
||||
mCollector->GetJSPurpleBuffer()->mTenuredObjects.AppendElement(*aObject);
|
||||
}
|
||||
AppendJSObjectToPurpleBuffer(*aObject);
|
||||
}
|
||||
|
||||
virtual void Trace(JS::Heap<JSString*>* aString, const char* aName,
|
||||
@ -3817,6 +3825,8 @@ JSPurpleBuffer*
|
||||
nsCycleCollector::GetJSPurpleBuffer()
|
||||
{
|
||||
if (!mJSPurpleBuffer) {
|
||||
// The Release call here confuses the GC analysis.
|
||||
JS::AutoSuppressGCAnalysis nogc;
|
||||
// JSPurpleBuffer keeps itself alive, but we need to create it in such way
|
||||
// that it ends up in the normal purple buffer. That happens when
|
||||
// nsRefPtr goes out of the scope and calls Release.
|
||||
|
Loading…
Reference in New Issue
Block a user