Bug 1311212 - Add dead CPOW debugging facility (r=mrbkap)

This commit is contained in:
Bill McCloskey 2016-10-18 15:58:33 -07:00
Родитель ef9a4d78b7
Коммит cbd15a0459
13 изменённых файлов: 155 добавлений и 29 удалений

Просмотреть файл

@ -366,14 +366,17 @@ function dead_test(finish)
return; return;
} }
let gcTrigger = function() {
// Force the GC to dead-ify the thing.
content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.garbageCollect();
}
{ {
let thing = { value: "Gonna croak" }; let thing = { value: "Gonna croak" };
sendAsyncMessage("cpows:dead", null, { thing }); sendAsyncMessage("cpows:dead", null, { thing, gcTrigger });
} }
// Force the GC to dead-ify the thing.
content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.garbageCollect();
addMessageListener("cpows:dead_done", finish); addMessageListener("cpows:dead_done", finish);
} }

Просмотреть файл

@ -418,14 +418,18 @@
} }
function recvDead(msg) { function recvDead(msg) {
try { // Need to do this in a separate turn of the event loop.
msg.objects.thing.value; setTimeout(() => {
ok(false, "Should have been a dead CPOW"); msg.objects.gcTrigger();
} catch(e if /dead CPOW/.test(String(e))) { try {
ok(true, "Got the expected dead CPOW"); msg.objects.thing.value;
ok(e.stack, "The exception has a stack"); ok(false, "Should have been a dead CPOW");
} } catch(e if /dead CPOW/.test(String(e))) {
msg.target.messageManager.sendAsyncMessage("cpows:dead_done"); ok(true, "Got the expected dead CPOW");
ok(e.stack, "The exception has a stack");
}
msg.target.messageManager.sendAsyncMessage("cpows:dead_done");
}, 0);
} }
function run_tests(type) { function run_tests(type) {

Просмотреть файл

@ -89,6 +89,9 @@ NewJavaScriptChild();
void void
ReleaseJavaScriptChild(PJavaScriptChild* child); ReleaseJavaScriptChild(PJavaScriptChild* child);
void
AfterProcessTask();
} // namespace jsipc } // namespace jsipc
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -26,10 +26,17 @@ UpdateChildWeakPointersBeforeSweepingZoneGroup(JSContext* cx, void* data)
static_cast<JavaScriptChild*>(data)->updateWeakPointers(); static_cast<JavaScriptChild*>(data)->updateWeakPointers();
} }
static void
TraceChild(JSTracer* trc, void* data)
{
static_cast<JavaScriptChild*>(data)->trace(trc);
}
JavaScriptChild::~JavaScriptChild() JavaScriptChild::~JavaScriptChild()
{ {
JSContext* cx = dom::danger::GetJSContext(); JSContext* cx = dom::danger::GetJSContext();
JS_RemoveWeakPointerZoneGroupCallback(cx, UpdateChildWeakPointersBeforeSweepingZoneGroup); JS_RemoveWeakPointerZoneGroupCallback(cx, UpdateChildWeakPointersBeforeSweepingZoneGroup);
JS_RemoveExtraGCRootsTracer(cx, TraceChild, this);
} }
bool bool
@ -42,9 +49,16 @@ JavaScriptChild::init()
JSContext* cx = dom::danger::GetJSContext(); JSContext* cx = dom::danger::GetJSContext();
JS_AddWeakPointerZoneGroupCallback(cx, UpdateChildWeakPointersBeforeSweepingZoneGroup, this); JS_AddWeakPointerZoneGroupCallback(cx, UpdateChildWeakPointersBeforeSweepingZoneGroup, this);
JS_AddExtraGCRootsTracer(cx, TraceChild, this);
return true; return true;
} }
void
JavaScriptChild::trace(JSTracer* trc)
{
objects_.trace(trc, strongReferenceObjIdMinimum_);
}
void void
JavaScriptChild::updateWeakPointers() JavaScriptChild::updateWeakPointers()
{ {
@ -61,6 +75,13 @@ JavaScriptChild::scopeForTargetObjects()
return xpc::PrivilegedJunkScope(); return xpc::PrivilegedJunkScope();
} }
bool
JavaScriptChild::RecvDropTemporaryStrongReferences(const uint64_t& upToObjId)
{
strongReferenceObjIdMinimum_ = upToObjId + 1;
return true;
}
PJavaScriptChild* PJavaScriptChild*
mozilla::jsipc::NewJavaScriptChild() mozilla::jsipc::NewJavaScriptChild()
{ {

Просмотреть файл

@ -17,9 +17,11 @@ namespace jsipc {
class JavaScriptChild : public JavaScriptBase<PJavaScriptChild> class JavaScriptChild : public JavaScriptBase<PJavaScriptChild>
{ {
public: public:
JavaScriptChild() : strongReferenceObjIdMinimum_(0) {}
virtual ~JavaScriptChild(); virtual ~JavaScriptChild();
bool init(); bool init();
void trace(JSTracer* trc);
void updateWeakPointers(); void updateWeakPointers();
void drop(JSObject* obj); void drop(JSObject* obj);
@ -30,9 +32,16 @@ class JavaScriptChild : public JavaScriptBase<PJavaScriptChild>
virtual bool isParent() override { return false; } virtual bool isParent() override { return false; }
virtual JSObject* scopeForTargetObjects() override; virtual JSObject* scopeForTargetObjects() override;
bool RecvDropTemporaryStrongReferences(const uint64_t& upToObjId) override;
private: private:
bool fail(JSContext* cx, ReturnStatus* rs); bool fail(JSContext* cx, ReturnStatus* rs);
bool ok(ReturnStatus* rs); bool ok(ReturnStatus* rs);
// JavaScriptChild will keep strong references to JS objects that are
// referenced by the parent only if their ID is >=
// strongReferenceObjIdMinimum_.
uint64_t strongReferenceObjIdMinimum_;
}; };
} // namespace jsipc } // namespace jsipc

Просмотреть файл

@ -172,15 +172,17 @@ JavaScriptParent::scopeForTargetObjects()
return xpc::UnprivilegedJunkScope(); return xpc::UnprivilegedJunkScope();
} }
mozilla::ipc::IProtocol* void
JavaScriptParent::CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx) JavaScriptParent::afterProcessTask()
{ {
ContentParent* contentParent = aCtx->GetContentParent(); if (savedNextCPOWNumber_ == nextCPOWNumber_)
nsAutoPtr<PJavaScriptParent> actor(contentParent->AllocPJavaScriptParent()); return;
if (!actor || !contentParent->RecvPJavaScriptConstructor(actor)) {
return nullptr; savedNextCPOWNumber_ = nextCPOWNumber_;
}
return actor.forget(); MOZ_ASSERT(nextCPOWNumber_ > 0);
if (active())
Unused << SendDropTemporaryStrongReferences(nextCPOWNumber_ - 1);
} }
PJavaScriptParent* PJavaScriptParent*
@ -199,3 +201,12 @@ mozilla::jsipc::ReleaseJavaScriptParent(PJavaScriptParent* parent)
{ {
static_cast<JavaScriptParent*>(parent)->decref(); static_cast<JavaScriptParent*>(parent)->decref();
} }
void
mozilla::jsipc::AfterProcessTask()
{
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
if (PJavaScriptParent* p = LoneManagedOrNullAsserts(cp->ManagedPJavaScriptParent()))
static_cast<JavaScriptParent*>(p)->afterProcessTask();
}
}

Просмотреть файл

@ -17,6 +17,7 @@ namespace jsipc {
class JavaScriptParent : public JavaScriptBase<PJavaScriptParent> class JavaScriptParent : public JavaScriptBase<PJavaScriptParent>
{ {
public: public:
JavaScriptParent() : savedNextCPOWNumber_(1) {}
virtual ~JavaScriptParent(); virtual ~JavaScriptParent();
bool init(); bool init();
@ -25,13 +26,14 @@ class JavaScriptParent : public JavaScriptBase<PJavaScriptParent>
void drop(JSObject* obj); void drop(JSObject* obj);
bool allowMessage(JSContext* cx) override; bool allowMessage(JSContext* cx) override;
void afterProcessTask();
mozilla::ipc::IProtocol*
CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx) override;
protected: protected:
virtual bool isParent() override { return true; } virtual bool isParent() override { return true; }
virtual JSObject* scopeForTargetObjects() override; virtual JSObject* scopeForTargetObjects() override;
private:
uint64_t savedNextCPOWNumber_;
}; };
} // namespace jsipc } // namespace jsipc

Просмотреть файл

@ -33,10 +33,12 @@ IdToObjectMap::init()
} }
void void
IdToObjectMap::trace(JSTracer* trc) IdToObjectMap::trace(JSTracer* trc, uint64_t minimimId)
{ {
for (Table::Range r(table_.all()); !r.empty(); r.popFront()) for (Table::Range r(table_.all()); !r.empty(); r.popFront()) {
JS::TraceEdge(trc, &r.front().value(), "ipc-object"); if (r.front().key().serialNumber() >= minimimId)
JS::TraceEdge(trc, &r.front().value(), "ipc-object");
}
} }
void void
@ -145,7 +147,8 @@ bool JavaScriptShared::sStackLoggingEnabled;
JavaScriptShared::JavaScriptShared() JavaScriptShared::JavaScriptShared()
: refcount_(1), : refcount_(1),
nextSerialNumber_(1) nextSerialNumber_(1),
nextCPOWNumber_(1)
{ {
if (!sLoggingInitialized) { if (!sLoggingInitialized) {
sLoggingInitialized = true; sLoggingInitialized = true;

Просмотреть файл

@ -91,7 +91,7 @@ class IdToObjectMap
IdToObjectMap(); IdToObjectMap();
bool init(); bool init();
void trace(JSTracer* trc); void trace(JSTracer* trc, uint64_t minimumId = 0);
void sweep(); void sweep();
bool add(ObjectId id, JSObject* obj); bool add(ObjectId id, JSObject* obj);
@ -200,6 +200,10 @@ class JavaScriptShared : public CPOWManager
uint64_t nextSerialNumber_; uint64_t nextSerialNumber_;
// nextCPOWNumber_ should be the value of nextSerialNumber_ in the other
// process. The next new CPOW we get should have this serial number.
uint64_t nextCPOWNumber_;
// CPOW references can be weak, and any object we store in a map may be // CPOW references can be weak, and any object we store in a map may be
// GCed (at which point the CPOW will report itself "dead" to the owner). // GCed (at which point the CPOW will report itself "dead" to the owner).
// This means that we don't want to store any js::Wrappers in the CPOW map, // This means that we don't want to store any js::Wrappers in the CPOW map,

Просмотреть файл

@ -51,6 +51,9 @@ both:
parent: parent:
async __delete__(); async __delete__();
child:
async DropTemporaryStrongReferences(uint64_t upToObjId);
}; };
} }

Просмотреть файл

@ -27,6 +27,22 @@ using namespace mozilla::jsipc;
using mozilla::dom::AutoJSAPI; using mozilla::dom::AutoJSAPI;
using mozilla::dom::AutoEntryScript; using mozilla::dom::AutoEntryScript;
static void
MaybeForceDebugGC()
{
static bool sEnvVarInitialized = false;
static bool sDebugGCs = false;
if (!sEnvVarInitialized)
sDebugGCs = !!PR_GetEnv("MOZ_DEBUG_DEAD_CPOWS");
if (sDebugGCs) {
JSContext* cx = nsXPConnect::GetContextInstance()->Context();
PrepareForFullGC(cx);
GCForReason(cx, GC_NORMAL, gcreason::COMPONENT_UTILS);
}
}
bool bool
WrapperAnswer::fail(AutoJSAPI& jsapi, ReturnStatus* rs) WrapperAnswer::fail(AutoJSAPI& jsapi, ReturnStatus* rs)
{ {
@ -85,6 +101,8 @@ WrapperAnswer::deadCPOW(AutoJSAPI& jsapi, ReturnStatus* rs)
bool bool
WrapperAnswer::RecvPreventExtensions(const ObjectId& objId, ReturnStatus* rs) WrapperAnswer::RecvPreventExtensions(const ObjectId& objId, ReturnStatus* rs)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;
@ -116,6 +134,8 @@ bool
WrapperAnswer::RecvGetPropertyDescriptor(const ObjectId& objId, const JSIDVariant& idVar, WrapperAnswer::RecvGetPropertyDescriptor(const ObjectId& objId, const JSIDVariant& idVar,
ReturnStatus* rs, PPropertyDescriptor* out) ReturnStatus* rs, PPropertyDescriptor* out)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;
@ -146,6 +166,8 @@ bool
WrapperAnswer::RecvGetOwnPropertyDescriptor(const ObjectId& objId, const JSIDVariant& idVar, WrapperAnswer::RecvGetOwnPropertyDescriptor(const ObjectId& objId, const JSIDVariant& idVar,
ReturnStatus* rs, PPropertyDescriptor* out) ReturnStatus* rs, PPropertyDescriptor* out)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;
@ -176,6 +198,8 @@ bool
WrapperAnswer::RecvDefineProperty(const ObjectId& objId, const JSIDVariant& idVar, WrapperAnswer::RecvDefineProperty(const ObjectId& objId, const JSIDVariant& idVar,
const PPropertyDescriptor& descriptor, ReturnStatus* rs) const PPropertyDescriptor& descriptor, ReturnStatus* rs)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;
@ -204,6 +228,8 @@ WrapperAnswer::RecvDefineProperty(const ObjectId& objId, const JSIDVariant& idVa
bool bool
WrapperAnswer::RecvDelete(const ObjectId& objId, const JSIDVariant& idVar, ReturnStatus* rs) WrapperAnswer::RecvDelete(const ObjectId& objId, const JSIDVariant& idVar, ReturnStatus* rs)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;
@ -229,6 +255,8 @@ bool
WrapperAnswer::RecvHas(const ObjectId& objId, const JSIDVariant& idVar, ReturnStatus* rs, WrapperAnswer::RecvHas(const ObjectId& objId, const JSIDVariant& idVar, ReturnStatus* rs,
bool* foundp) bool* foundp)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;
@ -254,6 +282,8 @@ bool
WrapperAnswer::RecvHasOwn(const ObjectId& objId, const JSIDVariant& idVar, ReturnStatus* rs, WrapperAnswer::RecvHasOwn(const ObjectId& objId, const JSIDVariant& idVar, ReturnStatus* rs,
bool* foundp) bool* foundp)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;
@ -279,6 +309,8 @@ bool
WrapperAnswer::RecvGet(const ObjectId& objId, const JSVariant& receiverVar, WrapperAnswer::RecvGet(const ObjectId& objId, const JSVariant& receiverVar,
const JSIDVariant& idVar, ReturnStatus* rs, JSVariant* result) const JSIDVariant& idVar, ReturnStatus* rs, JSVariant* result)
{ {
MaybeForceDebugGC();
// We may run scripted getters. // We may run scripted getters.
AutoEntryScript aes(scopeForTargetObjects(), AutoEntryScript aes(scopeForTargetObjects(),
"Cross-Process Object Wrapper 'get'"); "Cross-Process Object Wrapper 'get'");
@ -316,6 +348,8 @@ bool
WrapperAnswer::RecvSet(const ObjectId& objId, const JSIDVariant& idVar, const JSVariant& value, WrapperAnswer::RecvSet(const ObjectId& objId, const JSIDVariant& idVar, const JSVariant& value,
const JSVariant& receiverVar, ReturnStatus* rs) const JSVariant& receiverVar, ReturnStatus* rs)
{ {
MaybeForceDebugGC();
// We may run scripted setters. // We may run scripted setters.
AutoEntryScript aes(scopeForTargetObjects(), AutoEntryScript aes(scopeForTargetObjects(),
"Cross-Process Object Wrapper 'set'"); "Cross-Process Object Wrapper 'set'");
@ -349,6 +383,8 @@ WrapperAnswer::RecvSet(const ObjectId& objId, const JSIDVariant& idVar, const JS
bool bool
WrapperAnswer::RecvIsExtensible(const ObjectId& objId, ReturnStatus* rs, bool* result) WrapperAnswer::RecvIsExtensible(const ObjectId& objId, ReturnStatus* rs, bool* result)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;
@ -377,6 +413,8 @@ WrapperAnswer::RecvCallOrConstruct(const ObjectId& objId,
JSVariant* result, JSVariant* result,
nsTArray<JSParam>* outparams) nsTArray<JSParam>* outparams)
{ {
MaybeForceDebugGC();
AutoEntryScript aes(scopeForTargetObjects(), AutoEntryScript aes(scopeForTargetObjects(),
"Cross-Process Object Wrapper call/construct"); "Cross-Process Object Wrapper call/construct");
JSContext* cx = aes.cx(); JSContext* cx = aes.cx();
@ -475,6 +513,8 @@ WrapperAnswer::RecvCallOrConstruct(const ObjectId& objId,
bool bool
WrapperAnswer::RecvHasInstance(const ObjectId& objId, const JSVariant& vVar, ReturnStatus* rs, bool* bp) WrapperAnswer::RecvHasInstance(const ObjectId& objId, const JSVariant& vVar, ReturnStatus* rs, bool* bp)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;
@ -500,6 +540,8 @@ bool
WrapperAnswer::RecvGetBuiltinClass(const ObjectId& objId, ReturnStatus* rs, WrapperAnswer::RecvGetBuiltinClass(const ObjectId& objId, ReturnStatus* rs,
uint32_t* classValue) uint32_t* classValue)
{ {
MaybeForceDebugGC();
*classValue = uint32_t(js::ESClass::Other); *classValue = uint32_t(js::ESClass::Other);
AutoJSAPI jsapi; AutoJSAPI jsapi;
@ -525,6 +567,8 @@ bool
WrapperAnswer::RecvIsArray(const ObjectId& objId, ReturnStatus* rs, WrapperAnswer::RecvIsArray(const ObjectId& objId, ReturnStatus* rs,
uint32_t* ans) uint32_t* ans)
{ {
MaybeForceDebugGC();
*ans = uint32_t(IsArrayAnswer::NotArray); *ans = uint32_t(IsArrayAnswer::NotArray);
AutoJSAPI jsapi; AutoJSAPI jsapi;
@ -549,6 +593,8 @@ WrapperAnswer::RecvIsArray(const ObjectId& objId, ReturnStatus* rs,
bool bool
WrapperAnswer::RecvClassName(const ObjectId& objId, nsCString* name) WrapperAnswer::RecvClassName(const ObjectId& objId, nsCString* name)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;
@ -570,6 +616,8 @@ WrapperAnswer::RecvClassName(const ObjectId& objId, nsCString* name)
bool bool
WrapperAnswer::RecvGetPrototype(const ObjectId& objId, ReturnStatus* rs, ObjectOrNullVariant* result) WrapperAnswer::RecvGetPrototype(const ObjectId& objId, ReturnStatus* rs, ObjectOrNullVariant* result)
{ {
MaybeForceDebugGC();
*result = NullVariant(); *result = NullVariant();
AutoJSAPI jsapi; AutoJSAPI jsapi;
@ -597,6 +645,8 @@ bool
WrapperAnswer::RecvGetPrototypeIfOrdinary(const ObjectId& objId, ReturnStatus* rs, bool* isOrdinary, WrapperAnswer::RecvGetPrototypeIfOrdinary(const ObjectId& objId, ReturnStatus* rs, bool* isOrdinary,
ObjectOrNullVariant* result) ObjectOrNullVariant* result)
{ {
MaybeForceDebugGC();
*result = NullVariant(); *result = NullVariant();
*isOrdinary = false; *isOrdinary = false;
@ -625,6 +675,8 @@ bool
WrapperAnswer::RecvRegExpToShared(const ObjectId& objId, ReturnStatus* rs, WrapperAnswer::RecvRegExpToShared(const ObjectId& objId, ReturnStatus* rs,
nsString* source, uint32_t* flags) nsString* source, uint32_t* flags)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;
@ -651,6 +703,8 @@ bool
WrapperAnswer::RecvGetPropertyKeys(const ObjectId& objId, const uint32_t& flags, WrapperAnswer::RecvGetPropertyKeys(const ObjectId& objId, const uint32_t& flags,
ReturnStatus* rs, nsTArray<JSIDVariant>* ids) ReturnStatus* rs, nsTArray<JSIDVariant>* ids)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;
@ -681,6 +735,8 @@ bool
WrapperAnswer::RecvInstanceOf(const ObjectId& objId, const JSIID& iid, ReturnStatus* rs, WrapperAnswer::RecvInstanceOf(const ObjectId& objId, const JSIID& iid, ReturnStatus* rs,
bool* instanceof) bool* instanceof)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;
@ -708,6 +764,8 @@ bool
WrapperAnswer::RecvDOMInstanceOf(const ObjectId& objId, const int& prototypeID, WrapperAnswer::RecvDOMInstanceOf(const ObjectId& objId, const int& prototypeID,
const int& depth, ReturnStatus* rs, bool* instanceof) const int& depth, ReturnStatus* rs, bool* instanceof)
{ {
MaybeForceDebugGC();
AutoJSAPI jsapi; AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false; return false;

Просмотреть файл

@ -1203,6 +1203,8 @@ WrapperOwner::fromRemoteObjectVariant(JSContext* cx, RemoteObject objVar)
if (!cpows_.add(objId, obj)) if (!cpows_.add(objId, obj))
return nullptr; return nullptr;
nextCPOWNumber_ = objId.serialNumber() + 1;
// Incref once we know the decref will be called. // Incref once we know the decref will be called.
incref(); incref();

Просмотреть файл

@ -44,6 +44,7 @@
#include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Element.h" #include "mozilla/dom/Element.h"
#include "mozilla/dom/WindowBinding.h" #include "mozilla/dom/WindowBinding.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/Atomics.h" #include "mozilla/Atomics.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/ProcessHangMonitor.h" #include "mozilla/ProcessHangMonitor.h"
@ -3612,6 +3613,8 @@ XPCJSContext::AfterProcessTask(uint32_t aNewRecursionDepth)
// Now that we are certain that the event is complete, // Now that we are certain that the event is complete,
// we can flush any ongoing performance measurement. // we can flush any ongoing performance measurement.
js::FlushPerformanceMonitoring(Get()->Context()); js::FlushPerformanceMonitoring(Get()->Context());
mozilla::jsipc::AfterProcessTask();
} }
/***************************************************************************/ /***************************************************************************/