зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 03b7d111cc86 (bug 857648)
This commit is contained in:
Родитель
bc8063b408
Коммит
d626e8a402
|
@ -37,6 +37,69 @@ JS_GetScriptFilename(JSScript *script);
|
|||
|
||||
namespace JS {
|
||||
|
||||
class FrameDescription
|
||||
{
|
||||
public:
|
||||
explicit FrameDescription(const js::FrameIter& iter);
|
||||
FrameDescription(const FrameDescription &rhs);
|
||||
~FrameDescription();
|
||||
|
||||
unsigned lineno() {
|
||||
if (!linenoComputed_) {
|
||||
lineno_ = JS_PCToLineNumber(nullptr, script_, pc_);
|
||||
linenoComputed_ = true;
|
||||
}
|
||||
return lineno_;
|
||||
}
|
||||
|
||||
const char *filename() const {
|
||||
return filename_;
|
||||
}
|
||||
|
||||
JSFlatString *funDisplayName() const {
|
||||
return funDisplayName_ ? JS_ASSERT_STRING_IS_FLAT(funDisplayName_) : nullptr;
|
||||
}
|
||||
|
||||
// Both these locations should be traced during GC but otherwise not used;
|
||||
// they are implementation details.
|
||||
Heap<JSScript*> &markedLocation1() {
|
||||
return script_;
|
||||
}
|
||||
Heap<JSString*> &markedLocation2() {
|
||||
return funDisplayName_;
|
||||
}
|
||||
|
||||
private:
|
||||
void operator=(const FrameDescription &) MOZ_DELETE;
|
||||
|
||||
// These fields are always initialized:
|
||||
Heap<JSString*> funDisplayName_;
|
||||
const char *filename_;
|
||||
|
||||
// One of script_ xor scriptSource_ is non-null.
|
||||
Heap<JSScript*> script_;
|
||||
js::ScriptSource *scriptSource_;
|
||||
|
||||
// For script_-having frames, lineno_ is lazily computed as an optimization.
|
||||
bool linenoComputed_;
|
||||
unsigned lineno_;
|
||||
|
||||
// pc_ is non-null iff script_ is non-null. If !pc_, linenoComputed_ = true.
|
||||
jsbytecode *pc_;
|
||||
};
|
||||
|
||||
struct StackDescription
|
||||
{
|
||||
unsigned nframes;
|
||||
FrameDescription *frames;
|
||||
};
|
||||
|
||||
extern JS_PUBLIC_API(StackDescription *)
|
||||
DescribeStack(JSContext *cx, unsigned maxFrames);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
FreeStackDescription(JSContext *cx, StackDescription *desc);
|
||||
|
||||
extern JS_PUBLIC_API(char *)
|
||||
FormatStackDump(JSContext *cx, char *buf, bool showArgs, bool showLocals, bool showThisProps);
|
||||
|
||||
|
|
|
@ -895,6 +895,85 @@ js_CallContextDebugHandler(JSContext *cx)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A contructor that crates a FrameDescription from a ScriptFrameIter, to avoid
|
||||
* constructing a FrameDescription on the stack just to append it to a vector.
|
||||
* FrameDescription contains Heap<T> fields that should not live on the stack.
|
||||
*/
|
||||
JS::FrameDescription::FrameDescription(const FrameIter& iter)
|
||||
: scriptSource_(nullptr),
|
||||
linenoComputed_(false),
|
||||
pc_(nullptr)
|
||||
{
|
||||
if (iter.isNonEvalFunctionFrame())
|
||||
funDisplayName_ = iter.functionDisplayAtom();
|
||||
|
||||
if (iter.hasScript()) {
|
||||
script_ = iter.script();
|
||||
pc_ = iter.pc();
|
||||
filename_ = script_->filename();
|
||||
} else {
|
||||
scriptSource_ = iter.scriptSource();
|
||||
scriptSource_->incref();
|
||||
filename_ = scriptSource_->filename();
|
||||
lineno_ = iter.computeLine();
|
||||
linenoComputed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
JS::FrameDescription::FrameDescription(const FrameDescription &rhs)
|
||||
: funDisplayName_(rhs.funDisplayName_),
|
||||
filename_(rhs.filename_),
|
||||
script_(rhs.script_),
|
||||
scriptSource_(rhs.scriptSource_),
|
||||
linenoComputed_(rhs.linenoComputed_),
|
||||
lineno_(rhs.lineno_),
|
||||
pc_(rhs.pc_)
|
||||
{
|
||||
if (scriptSource_)
|
||||
scriptSource_->incref();
|
||||
}
|
||||
|
||||
|
||||
JS::FrameDescription::~FrameDescription()
|
||||
{
|
||||
if (scriptSource_)
|
||||
scriptSource_->decref();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JS::StackDescription *)
|
||||
JS::DescribeStack(JSContext *cx, unsigned maxFrames)
|
||||
{
|
||||
Vector<FrameDescription> frames(cx);
|
||||
|
||||
NonBuiltinFrameIter i(cx, FrameIter::ALL_CONTEXTS,
|
||||
FrameIter::GO_THROUGH_SAVED,
|
||||
cx->compartment()->principals);
|
||||
for ( ; !i.done(); ++i) {
|
||||
if (!frames.append(i))
|
||||
return nullptr;
|
||||
if (frames.length() == maxFrames)
|
||||
break;
|
||||
}
|
||||
|
||||
JS::StackDescription *desc = js_new<JS::StackDescription>();
|
||||
if (!desc)
|
||||
return nullptr;
|
||||
|
||||
desc->nframes = frames.length();
|
||||
desc->frames = frames.extractRawBuffer();
|
||||
return desc;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::FreeStackDescription(JSContext *cx, JS::StackDescription *desc)
|
||||
{
|
||||
for (size_t i = 0; i < desc->nframes; ++i)
|
||||
desc->frames[i].~FrameDescription();
|
||||
js_free(desc->frames);
|
||||
js_delete(desc);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class AutoPropertyDescArray
|
||||
|
|
Загрузка…
Ссылка в новой задаче