Bug 932837 part 2. Create a refcounted object to manage the lifetime of a JS::StackDescription. r=mccr8, terrence

This commit is contained in:
Boris Zbarsky 2014-01-07 19:53:17 -05:00
parent a989ae183c
commit 72e2ce7440
8 changed files with 90 additions and 7 deletions

View File

@ -203,6 +203,62 @@ GetCurrentJSStack()
namespace exceptions {
class StackDescriptionOwner {
public:
StackDescriptionOwner(JS::StackDescription* aDescription)
: mDescription(aDescription)
{
mozilla::HoldJSObjects(this);
}
~StackDescriptionOwner()
{
// Make sure to set mDescription to null before calling DropJSObjects, since
// in debug builds DropJSObjects try to trace us and we don't want to trace
// a dead StackDescription.
if (mDescription) {
JS::FreeStackDescription(nullptr, mDescription);
mDescription = nullptr;
}
mozilla::DropJSObjects(this);
}
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(StackDescriptionOwner)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(StackDescriptionOwner)
JS::FrameDescription& FrameAt(size_t aIndex)
{
MOZ_ASSERT(aIndex < mDescription->nframes);
return mDescription->frames[aIndex];
}
private:
JS::StackDescription* mDescription;
};
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(StackDescriptionOwner, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(StackDescriptionOwner, Release)
NS_IMPL_CYCLE_COLLECTION_CLASS(StackDescriptionOwner)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(StackDescriptionOwner)
if (tmp->mDescription) {
JS::FreeStackDescription(nullptr, tmp->mDescription);
tmp->mDescription = nullptr;
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(StackDescriptionOwner)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(StackDescriptionOwner)
JS::StackDescription* desc = tmp->mDescription;
if (tmp->mDescription) {
for (size_t i = 0; i < desc->nframes; ++i) {
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDescription->frames[i].script());
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDescription->frames[i].fun());
}
}
NS_IMPL_CYCLE_COLLECTION_TRACE_END
class JSStackFrame : public nsIStackFrame
{
public:
@ -356,6 +412,8 @@ JSStackFrame::CreateStack(JSContext* cx)
return nullptr;
}
nsRefPtr<StackDescriptionOwner> descOwner = new StackDescriptionOwner(desc);
for (size_t i = 0; i < desc->nframes && self; i++) {
self->mLanguage = nsIProgrammingLanguage::JAVASCRIPT;
@ -388,8 +446,6 @@ JSStackFrame::CreateStack(JSContext* cx)
self.swap(frame);
}
JS::FreeStackDescription(cx, desc);
return first.forget();
}

View File

@ -48,17 +48,17 @@ class FrameDescription
return lineno_;
}
JSScript *script() const {
Heap<JSScript*> &script() {
return script_;
}
JSFunction *fun() const {
Heap<JSFunction*> &fun() {
return fun_;
}
private:
JSScript *script_;
JSFunction *fun_;
Heap<JSScript*> script_;
Heap<JSFunction*> fun_;
jsbytecode *pc_;
unsigned lineno_;
bool linenoComputed;

View File

@ -157,6 +157,9 @@ JS_CallHeapStringTracer(JSTracer *trc, JS::Heap<JSString *> *strp, const char *n
extern JS_PUBLIC_API(void)
JS_CallHeapScriptTracer(JSTracer *trc, JS::Heap<JSScript *> *scriptp, const char *name);
extern JS_PUBLIC_API(void)
JS_CallHeapFunctionTracer(JSTracer *trc, JS::Heap<JSFunction *> *funp, const char *name);
template <typename HashSetEnum>
inline void
JS_CallHashSetObjectTracer(JSTracer *trc, HashSetEnum &e, JSObject *const &key, const char *name)

View File

@ -78,6 +78,12 @@ JS_CallHeapScriptTracer(JSTracer *trc, JS::Heap<JSScript *> *scriptp, const char
MarkScriptUnbarriered(trc, scriptp->unsafeGet(), name);
}
JS_PUBLIC_API(void)
JS_CallHeapFunctionTracer(JSTracer *trc, JS::Heap<JSFunction *> *funp, const char *name)
{
MarkObjectUnbarriered(trc, funp->unsafeGet(), name);
}
JS_PUBLIC_API(void)
JS_CallTenuredObjectTracer(JSTracer *trc, JS::TenuredHeap<JSObject *> *objp, const char *name)
{

View File

@ -953,7 +953,9 @@ JS::DescribeStack(JSContext *cx, unsigned maxFrames)
JS_PUBLIC_API(void)
JS::FreeStackDescription(JSContext *cx, JS::StackDescription *desc)
{
js_delete(desc->frames);
for (size_t i = 0; i < desc->nframes; ++i)
desc->frames[i].~FrameDescription();
js_free(desc->frames);
js_delete(desc);
}

View File

@ -750,6 +750,9 @@ struct JsGcTracer : public TraceCallbacks
virtual void Trace(JS::Heap<JSScript *> *p, const char *name, void *closure) const MOZ_OVERRIDE {
JS_CallHeapScriptTracer(static_cast<JSTracer*>(closure), p, name);
}
virtual void Trace(JS::Heap<JSFunction *> *p, const char *name, void *closure) const MOZ_OVERRIDE {
JS_CallHeapFunctionTracer(static_cast<JSTracer*>(closure), p, name);
}
};
static PLDHashOperator
@ -802,6 +805,11 @@ struct ClearJSHolder : TraceCallbacks
{
*aPtr = nullptr;
}
virtual void Trace(JS::Heap<JSFunction*>* aPtr, const char*, void*) const MOZ_OVERRIDE
{
*aPtr = nullptr;
}
};
void

View File

@ -87,6 +87,12 @@ TraceCallbackFunc::Trace(JS::Heap<JSObject*>* p, const char* name, void* closure
mCallback(*p, name, closure);
}
void
TraceCallbackFunc::Trace(JS::Heap<JSFunction*>* p, const char* name, void* closure) const
{
mCallback(*p, name, closure);
}
void
TraceCallbackFunc::Trace(JS::Heap<JSString*>* p, const char* name, void* closure) const
{

View File

@ -60,6 +60,7 @@ struct TraceCallbacks
virtual void Trace(JS::Heap<JSObject*>* p, const char* name, void* closure) const = 0;
virtual void Trace(JS::Heap<JSString*>* p, const char* name, void* closure) const = 0;
virtual void Trace(JS::Heap<JSScript*>* p, const char* name, void* closure) const = 0;
virtual void Trace(JS::Heap<JSFunction*>* p, const char* name, void* closure) const = 0;
};
/*
@ -77,6 +78,7 @@ struct TraceCallbackFunc : public TraceCallbacks
virtual void Trace(JS::Heap<JSObject*>* p, const char* name, void* closure) const MOZ_OVERRIDE;
virtual void Trace(JS::Heap<JSString*>* p, const char* name, void* closure) const MOZ_OVERRIDE;
virtual void Trace(JS::Heap<JSScript*>* p, const char* name, void* closure) const MOZ_OVERRIDE;
virtual void Trace(JS::Heap<JSFunction*>* p, const char* name, void* closure) const MOZ_OVERRIDE;
private:
Func mCallback;