зеркало из https://github.com/mozilla/gecko-dev.git
Bug 604858 - break-to-label should endLoop(); assert that recording does not leave the original loop (r=dvander)
--HG-- extra : rebase_source : b24053b3450ee47d918441f8308280335a0d22cd
This commit is contained in:
Родитель
02bfd6954f
Коммит
95527fc16e
|
@ -0,0 +1,10 @@
|
|||
// Test using 'while' with 'continue' -- the most ancient, the most powerful,
|
||||
// the most rare of all coding incantations.
|
||||
|
||||
var i = 0;
|
||||
while (i < HOTLOOP+4) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
assertEq(i, HOTLOOP+4);
|
||||
|
|
@ -6885,6 +6885,38 @@ LeaveTree(TraceMonitor *tm, TracerState& state, VMSideExit* lr)
|
|||
state.innermost = innermost;
|
||||
}
|
||||
|
||||
static jsbytecode *
|
||||
GetLoopBottom(JSContext *cx, jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(*pc == JSOP_TRACE || *pc == JSOP_NOTRACE);
|
||||
JSScript *script = cx->fp()->script();
|
||||
jssrcnote *sn = js_GetSrcNote(script, pc);
|
||||
if (!sn)
|
||||
return NULL;
|
||||
return pc + js_GetSrcNoteOffset(sn, 0);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE void
|
||||
TraceRecorder::assertInsideLoop()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
/* Asserts at callDepth == 0 will catch problems at the call op. */
|
||||
if (callDepth > 0)
|
||||
return;
|
||||
|
||||
jsbytecode *pc = cx->regs->fp->hasImacropc() ? cx->regs->fp->imacropc() : cx->regs->pc;
|
||||
jsbytecode *beg = (jsbytecode *)tree->ip;
|
||||
jsbytecode *end = GetLoopBottom(cx, beg);
|
||||
|
||||
/*
|
||||
* In some cases (continue in a while loop), we jump to the goto
|
||||
* immediately preceeding a loop (the one that jumps to the loop
|
||||
* condition).
|
||||
*/
|
||||
JS_ASSERT(pc >= beg - JSOP_GOTO_LENGTH && pc <= end);
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK MonitorResult
|
||||
RecordLoopEdge(JSContext* cx, uintN& inlineCallCount)
|
||||
{
|
||||
|
@ -6896,6 +6928,7 @@ RecordLoopEdge(JSContext* cx, uintN& inlineCallCount)
|
|||
|
||||
/* Is the recorder currently active? */
|
||||
if (tm->recorder) {
|
||||
tm->recorder->assertInsideLoop();
|
||||
jsbytecode* pc = cx->regs->pc;
|
||||
if (pc == tm->recorder->tree->ip) {
|
||||
tm->recorder->closeLoop();
|
||||
|
@ -6905,7 +6938,6 @@ RecordLoopEdge(JSContext* cx, uintN& inlineCallCount)
|
|||
if (r == MONITOR_RECORDING || r == MONITOR_ERROR)
|
||||
return r;
|
||||
|
||||
|
||||
/*
|
||||
* recordLoopEdge will invoke an inner tree if we have a matching
|
||||
* one. If we arrive here, that tree didn't run to completion and
|
||||
|
@ -7102,6 +7134,7 @@ TraceRecorder::monitorRecording(JSOp op)
|
|||
{
|
||||
TraceMonitor &localtm = JS_TRACE_MONITOR(cx);
|
||||
debug_only_stmt( JSContext *localcx = cx; )
|
||||
assertInsideLoop();
|
||||
|
||||
/* Process needFlush requests now. */
|
||||
if (localtm.needFlush) {
|
||||
|
@ -10286,7 +10319,9 @@ TraceRecorder::record_JSOP_GOTO()
|
|||
*/
|
||||
jssrcnote* sn = js_GetSrcNote(cx->fp()->script(), cx->regs->pc);
|
||||
|
||||
if (sn && (SN_TYPE(sn) == SRC_BREAK || SN_TYPE(sn) == SRC_CONT2LABEL)) {
|
||||
if (sn &&
|
||||
(SN_TYPE(sn) == SRC_BREAK || SN_TYPE(sn) == SRC_CONT2LABEL ||
|
||||
SN_TYPE(sn) == SRC_BREAK2LABEL)) {
|
||||
AUDIT(breakLoopExits);
|
||||
return endLoop();
|
||||
}
|
||||
|
@ -16308,12 +16343,7 @@ static const uintN MAX_PROFILE_OPS = 4096;
|
|||
static jsbytecode *
|
||||
GetLoopBottom(JSContext *cx)
|
||||
{
|
||||
jsbytecode* pc = cx->regs->pc;
|
||||
JSScript *script = cx->fp()->script();
|
||||
jssrcnote *sn = js_GetSrcNote(script, pc);
|
||||
if (!sn)
|
||||
return NULL;
|
||||
return pc + js_GetSrcNoteOffset(sn, 0);
|
||||
return GetLoopBottom(cx, cx->regs->pc);
|
||||
}
|
||||
|
||||
static LoopProfile *
|
||||
|
|
|
@ -1201,6 +1201,7 @@ class TraceRecorder
|
|||
#ifdef DEBUG
|
||||
bool isValidFrameObjPtr(void *obj);
|
||||
#endif
|
||||
void assertInsideLoop();
|
||||
|
||||
JS_REQUIRES_STACK void setImpl(void* p, nanojit::LIns* l, bool demote = true);
|
||||
JS_REQUIRES_STACK void set(Value* p, nanojit::LIns* l, bool demote = true);
|
||||
|
|
Загрузка…
Ссылка в новой задаче