Bug 1477621 - Part 1: Add source note field constants for switch. r=jandem

This commit is contained in:
Tooru Fujisawa 2018-07-25 17:01:48 +09:00
parent 8fe894f60c
commit 53c7a51a17
5 changed files with 78 additions and 18 deletions

View File

@ -34,6 +34,44 @@ namespace js {
* NB: the js_SrcNoteSpec array in BytecodeEmitter.cpp is indexed by this
* enum, so its initializers need to match the order here.
*/
class SrcNote {
public:
// SRC_TABLESWITCH: Source note for JSOP_TABLESWITCH.
class TableSwitch {
public:
enum Fields {
// The offset of the end of switch (the first non-JumpTarget op
// after switch) from JSOP_TABLESWITCH.
EndOffset,
Count
};
};
// SRC_CONDSWITCH: Source note for JSOP_CONDSWITCH.
class CondSwitch {
public:
enum Fields {
// The offset of the end of switch (the first non-JumpTarget op
// after switch) from JSOP_CONDSWITCH.
EndOffset,
// The offset of JSOP_CASE for the first case from JSOP_CONDSWITCH.
FirstCaseOffset,
Count
};
};
// SRC_NEXTCASE: Source note for JSOP_CASE in a JSOP_CONDSWITCH.
class NextCase {
public:
enum Fields {
// Offset of the next JSOP_CASE from this JSOP_CASE. This field is
// 0 if this is the last JSOP_CASE.
NextCaseOffset,
Count
};
};
};
#define FOR_EACH_SRC_NOTE_TYPE(M) \
M(SRC_NULL, "null", 0) /* Terminates a note vector. */ \
M(SRC_IF, "if", 0) /* JSOP_IFEQ bytecode is from an if-then. */ \
@ -50,11 +88,9 @@ namespace js {
M(SRC_BREAK, "break", 0) /* JSOP_GOTO is a break. */ \
M(SRC_BREAK2LABEL, "break2label", 0) /* JSOP_GOTO for 'break label'. */ \
M(SRC_SWITCHBREAK, "switchbreak", 0) /* JSOP_GOTO is a break in a switch. */ \
M(SRC_TABLESWITCH, "tableswitch", 1) /* JSOP_TABLESWITCH; offset points to end of switch. */ \
M(SRC_CONDSWITCH, "condswitch", 2) /* JSOP_CONDSWITCH; 1st offset points to end of switch, \
2nd points to first JSOP_CASE. */ \
M(SRC_NEXTCASE, "nextcase", 1) /* Distance forward from one CASE in a CONDSWITCH to \
the next. */ \
M(SRC_TABLESWITCH, "tableswitch", SrcNote::TableSwitch::Count) \
M(SRC_CONDSWITCH, "condswitch", SrcNote::CondSwitch::Count) \
M(SRC_NEXTCASE, "nextcase", SrcNote::NextCase::Count) \
M(SRC_ASSIGNOP, "assignop", 0) /* += or another assign-op follows. */ \
M(SRC_CLASS_SPAN, "class", 2) /* The starting and ending offsets for the class, used \
for toString correctness for default ctors. */ \

View File

@ -233,8 +233,11 @@ SwitchEmitter::emitCaseOrDefaultJump(uint32_t caseIndex, bool isDefault)
if (state_ == State::Case) {
// Link the last JSOP_CASE's SRC_NEXTCASE to current JSOP_CASE for the
// benefit of IonBuilder.
if (!bce_->setSrcNoteOffset(caseNoteIndex_, 0, bce_->offset() - lastCaseOffset_))
if (!bce_->setSrcNoteOffset(caseNoteIndex_, SrcNote::NextCase::NextCaseOffset,
bce_->offset() - lastCaseOffset_))
{
return false;
}
}
if (!bce_->newSrcNote2(SRC_NEXTCASE, 0, &caseNoteIndex_))
@ -392,8 +395,14 @@ SwitchEmitter::emitEnd()
}
// Set the SRC_SWITCH note's offset operand to tell end of switch.
if (!bce_->setSrcNoteOffset(noteIndex_, 0, bce_->lastNonJumpTargetOffset() - top_))
// This code is shared between table switch and cond switch.
static_assert(unsigned(SrcNote::TableSwitch::EndOffset) == unsigned(SrcNote::CondSwitch::EndOffset),
"{TableSwitch,CondSwitch}::EndOffset should be same");
if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::TableSwitch::EndOffset,
bce_->lastNonJumpTargetOffset() - top_))
{
return false;
}
if (kind_ == Kind::Table) {
// Skip over the already-initialized switch bounds.

View File

@ -1118,8 +1118,8 @@ ControlFlowGenerator::processCondSwitch()
MOZ_ASSERT(SN_TYPE(sn) == SRC_CONDSWITCH);
// Get the exit pc
jsbytecode* exitpc = pc + GetSrcNoteOffset(sn, 0);
jsbytecode* firstCase = pc + GetSrcNoteOffset(sn, 1);
jsbytecode* exitpc = pc + GetSrcNoteOffset(sn, SrcNote::CondSwitch::EndOffset);
jsbytecode* firstCase = pc + GetSrcNoteOffset(sn, SrcNote::CondSwitch::FirstCaseOffset);
// Iterate all cases in the conditional switch.
// - Stop at the default case. (always emitted after the last case)
@ -1134,7 +1134,7 @@ ControlFlowGenerator::processCondSwitch()
// Fetch the next case.
jssrcnote* caseSn = GetSrcNote(gsn, script, curCase);
MOZ_ASSERT(caseSn && SN_TYPE(caseSn) == SRC_NEXTCASE);
ptrdiff_t off = GetSrcNoteOffset(caseSn, 0);
ptrdiff_t off = GetSrcNoteOffset(caseSn, SrcNote::NextCase::NextCaseOffset);
MOZ_ASSERT_IF(off == 0, JSOp(*GetNextPc(curCase)) == JSOP_JUMPTARGET);
curCase = off ? curCase + off : GetNextPc(GetNextPc(curCase));
MOZ_ASSERT(pc < curCase && curCase <= exitpc);
@ -1167,7 +1167,7 @@ ControlFlowGenerator::processCondSwitch()
defaultIdx++;
jssrcnote* caseSn = GetSrcNote(gsn, script, curCase);
ptrdiff_t off = GetSrcNoteOffset(caseSn, 0);
ptrdiff_t off = GetSrcNoteOffset(caseSn, SrcNote::NextCase::NextCaseOffset);
curCase = off ? curCase + off : GetNextPc(GetNextPc(curCase));
lastTarget = curTarget;
}
@ -1223,7 +1223,7 @@ ControlFlowGenerator::processCondSwitchCase(CFGState& state)
// Fetch the following case in which we will continue.
jssrcnote* sn = GetSrcNote(gsn, script, pc);
ptrdiff_t off = GetSrcNoteOffset(sn, 0);
ptrdiff_t off = GetSrcNoteOffset(sn, SrcNote::NextCase::NextCaseOffset);
MOZ_ASSERT_IF(off == 0, JSOp(*GetNextPc(pc)) == JSOP_JUMPTARGET);
jsbytecode* casePc = off ? pc + off : GetNextPc(GetNextPc(pc));
bool nextIsDefault = JSOp(*casePc) == JSOP_DEFAULT;
@ -1849,7 +1849,7 @@ ControlFlowGenerator::processTableSwitch(JSOp op, jssrcnote* sn)
MOZ_ASSERT(SN_TYPE(sn) == SRC_TABLESWITCH);
// Get the default and exit pc
jsbytecode* exitpc = pc + GetSrcNoteOffset(sn, 0);
jsbytecode* exitpc = pc + GetSrcNoteOffset(sn, SrcNote::TableSwitch::EndOffset);
jsbytecode* defaultpc = pc + GET_JUMP_OFFSET(pc);
MOZ_ASSERT(defaultpc > pc && defaultpc <= exitpc);

View File

@ -2757,16 +2757,26 @@ SrcNotes(JSContext* cx, HandleScript script, Sprinter* sp)
break;
case SRC_WHILE:
case SRC_NEXTCASE:
if (!sp->jsprintf(" offset %u", unsigned(GetSrcNoteOffset(sn, 0))))
return false;
break;
case SRC_NEXTCASE:
if (!sp->jsprintf(" next case offset %u",
unsigned(GetSrcNoteOffset(sn, SrcNote::NextCase::NextCaseOffset))))
{
return false;
}
break;
case SRC_TABLESWITCH: {
mozilla::DebugOnly<JSOp> op = JSOp(script->code()[offset]);
MOZ_ASSERT(op == JSOP_TABLESWITCH);
if (!sp->jsprintf(" length %u", unsigned(GetSrcNoteOffset(sn, 0))))
if (!sp->jsprintf(" end offset %u",
unsigned(GetSrcNoteOffset(sn, SrcNote::TableSwitch::EndOffset))))
{
return false;
}
UpdateSwitchTableBounds(cx, script, offset,
&switchTableStart, &switchTableEnd);
break;
@ -2774,9 +2784,14 @@ SrcNotes(JSContext* cx, HandleScript script, Sprinter* sp)
case SRC_CONDSWITCH: {
mozilla::DebugOnly<JSOp> op = JSOp(script->code()[offset]);
MOZ_ASSERT(op == JSOP_CONDSWITCH);
if (!sp->jsprintf(" length %u", unsigned(GetSrcNoteOffset(sn, 0))))
if (!sp->jsprintf(" end offset %u",
unsigned(GetSrcNoteOffset(sn, SrcNote::CondSwitch::EndOffset))))
{
return false;
if (unsigned caseOff = (unsigned) GetSrcNoteOffset(sn, 1)) {
}
if (unsigned caseOff =
unsigned(GetSrcNoteOffset(sn, SrcNote::CondSwitch::FirstCaseOffset)))
{
if (!sp->jsprintf(" first case offset %u", caseOff))
return false;
}

View File

@ -200,7 +200,7 @@ LCovSource::writeScript(JSScript* script)
else if (type == SRC_NEWLINE)
lineno++;
else if (type == SRC_TABLESWITCH)
tableswitchExitOffset = GetSrcNoteOffset(sn, 0);
tableswitchExitOffset = GetSrcNoteOffset(sn, SrcNote::TableSwitch::EndOffset);
sn = SN_NEXT(sn);
snpc += SN_DELTA(sn);