Commit 53c7a51a authored by Tooru Fujisawa's avatar Tooru Fujisawa
Browse files

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

parent 8fe894f6
Loading
Loading
Loading
Loading
+41 −5
Original line number Diff line number Diff line
@@ -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. */       \
+11 −2
Original line number Diff line number Diff line
@@ -233,9 +233,12 @@ 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_))
        return false;
@@ -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.
+6 −6
Original line number Diff line number Diff line
@@ -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);
+19 −4
Original line number Diff line number Diff line
@@ -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;
            }
+1 −1
Original line number Diff line number Diff line
@@ -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);