Bug 1004110 - Memoize PCToLineNumber lookups in SavedStacks. r=terrence

This commit is contained in:
Nick Fitzgerald 2014-06-17 16:32:00 -04:00
parent 293ecd5541
commit 705db2c049
3 changed files with 105 additions and 19 deletions

View File

@ -829,6 +829,7 @@ typedef ReadBarriered<Shape*> ReadBarrieredShape;
typedef ReadBarriered<UnownedBaseShape*> ReadBarrieredUnownedBaseShape;
typedef ReadBarriered<jit::JitCode*> ReadBarrieredJitCode;
typedef ReadBarriered<types::TypeObject*> ReadBarrieredTypeObject;
typedef ReadBarriered<JSAtom*> ReadBarrieredAtom;
typedef ReadBarriered<Value> ReadBarrieredValue;

View File

@ -349,6 +349,9 @@ SavedFrame::toStringMethod(JSContext *cx, unsigned argc, Value *vp)
bool
SavedStacks::init()
{
if (!pcLocationMap.init())
return false;
return frames.init();
}
@ -394,6 +397,8 @@ SavedStacks::sweep(JSRuntime *rt)
}
}
sweepPCLocationMap();
if (savedFrameProto && IsObjectAboutToBeFinalized(&savedFrameProto)) {
savedFrameProto = nullptr;
}
@ -439,20 +444,14 @@ SavedStacks::insertFrames(JSContext *cx, ScriptFrameIter &iter, MutableHandle<Sa
if (!insertFrames(cx, ++iter, &parentFrame))
return false;
RootedScript script(cx, thisFrame.script());
RootedFunction callee(cx, thisFrame.maybeCallee());
const char *filename = script->filename();
if (!filename)
filename = "";
RootedAtom source(cx, Atomize(cx, filename, strlen(filename)));
if (!source)
LocationValue location;
if (!getLocation(cx, thisFrame.script(), thisFrame.pc(), &location))
return false;
uint32_t column;
uint32_t line = PCToLineNumber(script, thisFrame.pc(), &column);
SavedFrame::Lookup lookup(source,
line,
column,
JSFunction *callee = thisFrame.maybeCallee();
SavedFrame::Lookup lookup(location.source,
location.line,
location.column,
callee ? callee->displayAtom() : nullptr,
parentFrame,
thisFrame.compartment()->principals);
@ -528,6 +527,49 @@ SavedStacks::createFrameFromLookup(JSContext *cx, SavedFrame::Lookup &lookup)
return &f;
}
/*
* Remove entries from the table whose JSScript is being collected.
*/
void
SavedStacks::sweepPCLocationMap()
{
for (PCLocationMap::Enum e(pcLocationMap); !e.empty(); e.popFront()) {
PCKey key = e.front().key();
JSScript *script = key.script.get();
if (IsScriptAboutToBeFinalized(&script)) {
e.removeFront();
} else if (script != key.script.get()) {
key.script = script;
e.rekeyFront(key);
}
}
}
bool
SavedStacks::getLocation(JSContext *cx, JSScript *script, jsbytecode *pc,
LocationValue *locationp)
{
PCKey key(script, pc);
PCLocationMap::AddPtr p = pcLocationMap.lookupForAdd(key);
if (!p) {
const char *filename = script->filename() ? script->filename() : "";
RootedAtom source(cx, Atomize(cx, filename, strlen(filename)));
if (!source)
return false;
uint32_t column;
uint32_t line = PCToLineNumber(script, pc, &column);
LocationValue value(source, line, column);
if (!pcLocationMap.add(p, key, value))
return false;
}
*locationp = p->value();
return true;
}
bool
SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata)
{

View File

@ -81,7 +81,7 @@ class SavedFrame : public JSObject {
struct SavedFrame::Lookup {
Lookup(JSAtom *source, size_t line, size_t column, JSAtom *functionDisplayName,
Handle<SavedFrame*> parent, JSPrincipals *principals)
SavedFrame *parent, JSPrincipals *principals)
: source(source),
line(line),
column(column),
@ -92,12 +92,12 @@ struct SavedFrame::Lookup {
JS_ASSERT(source);
}
JSAtom *source;
size_t line;
size_t column;
JSAtom *functionDisplayName;
Handle<SavedFrame*> parent;
JSPrincipals *principals;
JSAtom *source;
size_t line;
size_t column;
JSAtom *functionDisplayName;
SavedFrame *parent;
JSPrincipals *principals;
};
struct SavedFrame::HashPolicy
@ -136,6 +136,49 @@ class SavedStacks {
// be accessed through this method.
JSObject *getOrCreateSavedFramePrototype(JSContext *cx);
SavedFrame *createFrameFromLookup(JSContext *cx, SavedFrame::Lookup &lookup);
// Cache for memoizing PCToLineNumber lookups.
struct PCKey {
PCKey(JSScript *script, jsbytecode *pc) : script(script), pc(pc) { }
PreBarrieredScript script;
jsbytecode *pc;
};
struct LocationValue {
LocationValue() : source(nullptr), line(0), column(0) { }
LocationValue(JSAtom *source, size_t line, size_t column)
: source(source),
line(line),
column(column)
{ }
ReadBarrieredAtom source;
size_t line;
size_t column;
};
struct PCLocationHasher : public DefaultHasher<PCKey> {
typedef PointerHasher<JSScript *, 3> ScriptPtrHasher;
typedef PointerHasher<jsbytecode *, 3> BytecodePtrHasher;
static HashNumber hash(const PCKey &key) {
return mozilla::AddToHash(ScriptPtrHasher::hash(key.script),
BytecodePtrHasher::hash(key.pc));
}
static bool match(const PCKey &l, const PCKey &k) {
return l.script == k.script && l.pc == k.pc;
}
};
typedef HashMap<PCKey, LocationValue, PCLocationHasher, SystemAllocPolicy> PCLocationMap;
PCLocationMap pcLocationMap;
void sweepPCLocationMap();
bool getLocation(JSContext *cx, JSScript *script, jsbytecode *pc, LocationValue *locationp);
};
bool SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata);