Bug 1187062 - Part 2: Implement a concrete JS::ubi::StackFrame class backed by js::SavedFrame; r=sfink

This commit is contained in:
Nick Fitzgerald 2015-08-14 17:49:06 -07:00
Родитель 9404d4d0bb
Коммит d93cd5e9a8
4 изменённых файлов: 158 добавлений и 3 удалений

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

@ -956,6 +956,9 @@ class Concrete<JSObject> : public TracerConcreteWithCompartment<JSObject> {
UniquePtr<char16_t[], JS::FreePolicy>& outName) const override;
size_t size(mozilla::MallocSizeOf mallocSizeOf) const override;
bool hasAllocationStack() const override;
StackFrame allocationStack() const override;
protected:
explicit Concrete(JSObject* ptr) : TracerConcreteWithCompartment(ptr) { }

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

@ -7,6 +7,8 @@
#ifndef vm_SavedFrame_h
#define vm_SavedFrame_h
#include "js/UbiNode.h"
namespace js {
class SavedFrame : public NativeObject {
@ -109,4 +111,49 @@ inline void AssertObjectIsSavedFrameOrWrapper(JSContext* cx, HandleObject stack)
} // namespace js
namespace JS {
namespace ubi {
using js::SavedFrame;
// A concrete JS::ubi::StackFrame that is backed by a live SavedFrame object.
template<>
class ConcreteStackFrame<SavedFrame> : public BaseStackFrame {
explicit ConcreteStackFrame(SavedFrame* ptr) : BaseStackFrame(ptr) { }
SavedFrame& get() const { return *static_cast<SavedFrame*>(ptr); }
public:
static void construct(void* storage, SavedFrame* ptr) { new (storage) ConcreteStackFrame(ptr); }
StackFrame parent() const override { return get().getParent(); }
uint32_t line() const override { return get().getLine(); }
uint32_t column() const override { return get().getColumn(); }
AtomOrTwoByteChars source() const override {
auto source = get().getSource();
return AtomOrTwoByteChars(source);
}
AtomOrTwoByteChars functionDisplayName() const override {
auto name = get().getFunctionDisplayName();
return AtomOrTwoByteChars(name);
}
void trace(JSTracer* trc) override {
JSObject* obj = &get();
js::TraceManuallyBarrieredEdge(trc, &obj, "ConcreteStackFrame<SavedFrame>::ptr");
ptr = obj;
}
bool isSelfHosted() const override { return get().isSelfHosted(); }
bool isSystem() const override;
bool constructSavedFrameStack(JSContext* cx,
MutableHandleObject outSavedFrameStack) const override;
};
} // namespace ubi
} // namespace JS
#endif // vm_SavedFrame_h

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

@ -1375,3 +1375,29 @@ CompartmentChecker::check(SavedStacks* stacks)
#endif /* JS_CRASH_DIAGNOSTICS */
} /* namespace js */
namespace JS {
namespace ubi {
bool
ConcreteStackFrame<SavedFrame>::isSystem() const
{
auto trustedPrincipals = get().runtimeFromAnyThread()->trustedPrincipals();
return get().getPrincipals() == trustedPrincipals;
}
bool
ConcreteStackFrame<SavedFrame>::constructSavedFrameStack(JSContext* cx,
MutableHandleObject outSavedFrameStack)
const
{
outSavedFrameStack.set(&get());
if (!cx->compartment()->wrap(cx, outSavedFrameStack)) {
outSavedFrameStack.set(nullptr);
return false;
}
return true;
}
} // namespace ubi
} // namespace JS

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

@ -11,6 +11,8 @@
#include "mozilla/Range.h"
#include "mozilla/Scoped.h"
#include <algorithm>
#include "jscntxt.h"
#include "jsobj.h"
#include "jsscript.h"
@ -22,6 +24,7 @@
#include "js/TypeDecls.h"
#include "js/Utility.h"
#include "js/Vector.h"
#include "vm/Debugger.h"
#include "vm/GlobalObject.h"
#include "vm/ScopeObject.h"
#include "vm/Shape.h"
@ -32,24 +35,87 @@
#include "vm/Debugger-inl.h"
using mozilla::Some;
using mozilla::RangedPtr;
using mozilla::UniquePtr;
using JS::DispatchTraceKindTyped;
using JS::HandleValue;
using JS::Value;
using JS::ZoneSet;
using JS::ubi::AtomOrTwoByteChars;
using JS::ubi::Concrete;
using JS::ubi::Edge;
using JS::ubi::EdgeRange;
using JS::ubi::Node;
using JS::ubi::SimpleEdge;
using JS::ubi::SimpleEdgeVector;
using JS::ubi::StackFrame;
using JS::ubi::TracerConcrete;
using JS::ubi::TracerConcreteWithCompartment;
template<typename CharT>
static size_t
copyToBuffer(const CharT* src, RangedPtr<char16_t> dest, size_t length)
{
size_t i = 0;
for ( ; i < length; i++)
dest[i] = src[i];
return i;
}
struct CopyToBufferMatcher
{
using ReturnType = size_t;
RangedPtr<char16_t> destination;
size_t maxLength;
CopyToBufferMatcher(RangedPtr<char16_t> destination, size_t maxLength)
: destination(destination)
, maxLength(maxLength)
{ }
size_t
match(JSAtom* atom)
{
if (!atom)
return 0;
size_t length = std::min(atom->length(), maxLength);
JS::AutoCheckCannotGC noGC;
return atom->hasTwoByteChars()
? copyToBuffer(atom->twoByteChars(noGC), destination, length)
: copyToBuffer(atom->latin1Chars(noGC), destination, length);
}
size_t
match(const char16_t* chars)
{
if (!chars)
return 0;
size_t length = std::min(js_strlen(chars), maxLength);
return copyToBuffer(chars, destination, length);
}
};
size_t
StackFrame::source(RangedPtr<char16_t> destination, size_t length) const
{
CopyToBufferMatcher m(destination, length);
return source().match(m);
}
size_t
StackFrame::functionDisplayName(RangedPtr<char16_t> destination, size_t length) const
{
CopyToBufferMatcher m(destination, length);
return functionDisplayName().match(m);
}
// All operations on null ubi::Nodes crash.
const char16_t* Concrete<void>::typeName() const { MOZ_CRASH("null ubi::Node"); }
JS::Zone* Concrete<void>::zone() const { MOZ_CRASH("null ubi::Node"); }
JSCompartment* Concrete<void>::compartment() const { MOZ_CRASH("null ubi::Node"); }
const char16_t* Concrete<void>::typeName() const { MOZ_CRASH("null ubi::Node"); }
JS::Zone* Concrete<void>::zone() const { MOZ_CRASH("null ubi::Node"); }
JSCompartment* Concrete<void>::compartment() const { MOZ_CRASH("null ubi::Node"); }
UniquePtr<EdgeRange>
Concrete<void>::edges(JSContext*, bool) const {
@ -218,6 +284,19 @@ TracerConcreteWithCompartment<Referent>::compartment() const
return TracerBase::get().compartment();
}
bool
Concrete<JSObject>::hasAllocationStack() const
{
return !!js::Debugger::getObjectAllocationSite(get());
}
StackFrame
Concrete<JSObject>::allocationStack() const
{
MOZ_ASSERT(hasAllocationStack());
return StackFrame(js::Debugger::getObjectAllocationSite(get()));
}
const char*
Concrete<JSObject>::jsObjectClassName() const
{