зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1187062 - Part 2: Implement a concrete JS::ubi::StackFrame class backed by js::SavedFrame; r=sfink
This commit is contained in:
Родитель
9404d4d0bb
Коммит
d93cd5e9a8
|
@ -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
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче