From 1be7cb6acd71cc2ed0a3d95b2ea2f79aa1be2268 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Mon, 6 Jun 2011 14:11:08 -0700 Subject: [PATCH] Bug 719294 - Eliminate the bytecode space optimization where it omits the starting line number. r=luke As per this comment: /* * Special case: function definition needs no line number note because * the function's script contains its starting line number. */ But this is the only reason why you need a JSContext in js_PCToLineNumber, and I have a user that needs to do the lookup without a context. --HG-- extra : rebase_source : 73064dbbbf31949d19c8f1e1b18eb4febf127c87 --- js/src/frontend/BytecodeEmitter.cpp | 2 ++ js/src/jscntxt.cpp | 2 +- js/src/jsdbgapi.cpp | 2 +- js/src/jsexn.cpp | 4 +-- js/src/jsscript.cpp | 39 +++++++++++++++-------------- js/src/jsscript.h | 9 ++++--- js/src/jsxml.cpp | 2 +- js/src/methodjit/InvokeHelpers.cpp | 2 +- 8 files changed, 34 insertions(+), 28 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index b43138feca5..dae0a11e513 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -5110,6 +5110,8 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) MOZ_ASSERT(!fun->isFlatClosure(), "global functions can't have upvars, so they are never flat"); if (!EmitFunctionOp(cx, JSOP_DEFFUN, index, bce)) + if (!UpdateLineNumberNotes(cx, bce, pn->pn_pos.begin.lineno)) + return JS_FALSE; return false; bce->switchToMain(); } diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index ede93d4eb5d..9e17890408c 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -379,7 +379,7 @@ PopulateReportBlame(JSContext *cx, JSErrorReport *report) for (FrameRegsIter iter(cx); !iter.done(); ++iter) { if (iter.fp()->isScriptFrame()) { report->filename = iter.fp()->script()->filename; - report->lineno = js_PCToLineNumber(cx, iter.fp()->script(), iter.pc()); + report->lineno = PCToLineNumber(iter.fp()->script(), iter.pc()); report->originPrincipals = iter.fp()->script()->originPrincipals; break; } diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 51c4c4f85af..df303f4f560 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -351,7 +351,7 @@ JS_ClearAllWatchPoints(JSContext *cx) JS_PUBLIC_API(unsigned) JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc) { - return js_PCToLineNumber(cx, script, pc); + return js::PCToLineNumber(script, pc); } JS_PUBLIC_API(jsbytecode *) diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index a5d230a9417..5a43d326cd2 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -343,7 +343,7 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message, } if (fp->isScriptFrame()) { frame.filename = fp->script()->filename; - frame.ulineno = js_PCToLineNumber(cx, fp->script(), i.pc()); + frame.ulineno = PCToLineNumber(fp->script(), i.pc()); } else { frame.ulineno = 0; frame.filename = NULL; @@ -783,7 +783,7 @@ Exception(JSContext *cx, unsigned argc, Value *vp) if (!ToUint32(cx, args[2], &lineno)) return false; } else { - lineno = iter.done() ? 0 : js_PCToLineNumber(cx, iter.fp()->script(), iter.pc()); + lineno = iter.done() ? 0 : PCToLineNumber(iter.fp()->script(), iter.pc()); } int exnType = args.callee().toFunction()->getExtendedSlot(0).toInt32(); diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 51a3dde9a83..cadbcca7db6 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -1571,28 +1571,18 @@ js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc) } unsigned -js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc) +js::PCToLineNumber(unsigned startLine, jssrcnote *notes, jsbytecode *code, jsbytecode *pc) { - /* Cope with StackFrame.pc value prior to entering js_Interpret. */ - if (!pc) - return 0; + unsigned lineno = startLine; /* - * Special case: function definition needs no line number note because - * the function's script contains its starting line number. + * Walk through source notes accumulating their deltas, keeping track of + * line-number notes, until we pass the note for pc's offset within + * script->code. */ - if (*pc == JSOP_DEFFUN) - return script->getFunction(GET_UINT32_INDEX(pc))->script()->lineno; - - /* - * General case: walk through source notes accumulating their deltas, - * keeping track of line-number notes, until we pass the note for pc's - * offset within script->code. - */ - unsigned lineno = script->lineno; ptrdiff_t offset = 0; - ptrdiff_t target = pc - script->code; - for (jssrcnote *sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { + ptrdiff_t target = pc - code; + for (jssrcnote *sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { offset += SN_DELTA(sn); SrcNoteType type = (SrcNoteType) SN_TYPE(sn); if (type == SRC_SETLINE) { @@ -1605,9 +1595,20 @@ js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc) if (offset > target) break; } + return lineno; } +unsigned +js::PCToLineNumber(JSScript *script, jsbytecode *pc) +{ + /* Cope with StackFrame.pc value prior to entering js_Interpret. */ + if (!pc) + return 0; + + return PCToLineNumber(script->lineno, script->notes(), script->code, pc); +} + /* The line number limit is the same as the jssrcnote offset limit. */ #define SN_LINE_LIMIT (SN_3BYTE_OFFSET_FLAG << 16) @@ -1680,7 +1681,7 @@ namespace js { unsigned CurrentLine(JSContext *cx) { - return js_PCToLineNumber(cx, cx->fp()->script(), cx->regs().pc); + return PCToLineNumber(cx->fp()->script(), cx->regs().pc); } void @@ -1700,7 +1701,7 @@ CurrentScriptFileLineOriginSlow(JSContext *cx, const char **file, unsigned *line JSScript *script = iter.fp()->script(); *file = script->filename; - *linenop = js_PCToLineNumber(cx, iter.fp()->script(), iter.pc()); + *linenop = PCToLineNumber(iter.fp()->script(), iter.pc()); *origin = script->originPrincipals; } diff --git a/js/src/jsscript.h b/js/src/jsscript.h index b1817a556b4..96783b5797c 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -902,9 +902,6 @@ CheckScript(JSScript *script, JSScript *prev) extern jssrcnote * js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc); -extern unsigned -js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc); - extern jsbytecode * js_LineNumberToPC(JSScript *script, unsigned lineno); @@ -913,6 +910,12 @@ js_GetScriptLineExtent(JSScript *script); namespace js { +extern unsigned +PCToLineNumber(JSScript *script, jsbytecode *pc); + +extern unsigned +PCToLineNumber(unsigned startLine, jssrcnote *notes, jsbytecode *code, jsbytecode *pc); + extern unsigned CurrentLine(JSContext *cx); diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 6c4c4d6a8ca..30555b06467 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -1790,7 +1790,7 @@ ParseXMLSource(JSContext *cx, JSString *src) op = (JSOp) *i.pc(); if (op == JSOP_TOXML || op == JSOP_TOXMLLIST) { filename = i.fp()->script()->filename; - lineno = js_PCToLineNumber(cx, i.fp()->script(), i.pc()); + lineno = PCToLineNumber(i.fp()->script(), i.pc()); for (endp = srcp + srclen; srcp < endp; srcp++) { if (*srcp == '\n') --lineno; diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index f51ccb8cf94..5ac2418a862 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -800,7 +800,7 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM #ifdef JS_METHODJIT_SPEW JaegerSpew(JSpew_Recompile, "interpreter rejoin (file \"%s\") (line \"%d\") (op %s) (opline \"%d\")\n", - script->filename, script->lineno, OpcodeNames[op], js_PCToLineNumber(cx, script, pc)); + script->filename, script->lineno, OpcodeNames[op], PCToLineNumber(script, pc)); #endif uint32_t nextDepth = UINT32_MAX;