Bug 1499544 - [Part 2] Use ByteCodeLocation and ByteCodeIterator r=djvj
authorMatthew Gaudet <mgaudet@mozilla.com>
Tue, 16 Oct 2018 15:44:37 -0400
changeset 442948 1417a92298ff87a3b0f328566ed20b06cbcb1d65
parent 442947 908a0972c1b529a90e9bee5055f83c86b06a0bb2
child 442949 e8b53fa4ae7e8047eabaab6b2da701c209a74cba
push id109264
push usermgaudet@mozilla.com
push dateThu, 25 Oct 2018 13:09:49 +0000
treeherdermozilla-inbound@1417a92298ff [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdjvj
bugs1499544
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1499544 - [Part 2] Use ByteCodeLocation and ByteCodeIterator r=djvj The interface is expanded and refined in this patch, showing a more complicated set of requirements and the answers to those requirements Differential Revision: https://phabricator.services.mozilla.com/D8920
js/src/vm/BytecodeLocation.h
js/src/vm/JSScript.cpp
--- a/js/src/vm/BytecodeLocation.h
+++ b/js/src/vm/BytecodeLocation.h
@@ -118,21 +118,59 @@ class BytecodeLocation
         MOZ_ASSERT(isInBounds());
         return getOp() == op;
     }
 
     bool isJumpTarget() const {
         return BytecodeIsJumpTarget(getOp());
     }
 
+    bool isJump() const {
+        return IsJumpOpcode(getOp());
+    }
+
+    bool fallsThrough() const {
+        return BytecodeFallsThrough(getOp());
+    }
+
     // Accessors:
     JSOp getOp() const {
         return JSOp(*rawBytecode_);
     }
 
+    BytecodeLocation getJumpTarget() const {
+        // The default target of a JSOP_TABLESWITCH also follows this format.
+        MOZ_ASSERT(isJump() || is(JSOP_TABLESWITCH));
+        return BytecodeLocation(*this, rawBytecode_ + GET_JUMP_OFFSET(rawBytecode_));
+    }
+
+    // Return the 'low' parameter to the tableswitch opcode
+    int32_t getTableSwitchLow() const {
+        MOZ_ASSERT(is(JSOP_TABLESWITCH));
+        return GET_JUMP_OFFSET(rawBytecode_ + JUMP_OFFSET_LEN);
+    }
+
+    // Return the 'high' parameter to the tableswitch opcode
+    int32_t getTableSwitchHigh() const {
+        MOZ_ASSERT(is(JSOP_TABLESWITCH));
+        return GET_JUMP_OFFSET(rawBytecode_ + (2 * JUMP_OFFSET_LEN));
+    }
+
+    // Return the BytecodeLocation referred to by index number in the table
+    // of the table switch.
+    //
+    // Returns (effectively) |this| on a gap in the table.
+    BytecodeLocation getTableSwitchCaseByIndex(size_t index) const {
+        MOZ_ASSERT(is(JSOP_TABLESWITCH));
+        RawBytecode offsetLoc = rawBytecode_ +
+                                (3 *  JUMP_OFFSET_LEN) + // Skip over low and high
+                                (index * JUMP_OFFSET_LEN); // Select table entry
+        return BytecodeLocation(*this, rawBytecode_ + GET_JUMP_OFFSET(offsetLoc));
+    }
+
 #ifdef DEBUG
     // To ease writing assertions
     bool isValid() const {
         return isValid(debugOnlyScript_);
     }
 
     bool isInBounds() const {
         return isInBounds(debugOnlyScript_);
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -3564,60 +3564,59 @@ JSScript::fullyInitFromEmitter(JSContext
 
     return true;
 }
 
 #ifdef DEBUG
 void
 JSScript::assertValidJumpTargets() const
 {
-    jsbytecode* end = codeEnd();
-    jsbytecode* mainEntry = main();
-    for (jsbytecode* pc = code(); pc != end; pc = GetNextPc(pc)) {
+    BytecodeLocation mainLoc = mainLocation();
+    BytecodeLocation endLoc = endLocation();
+    AllBytecodesIterable iter(this);
+    for (BytecodeLocation loc : iter) {
         // Check jump instructions' target.
-        if (IsJumpOpcode(JSOp(*pc))) {
-            jsbytecode* target = pc + GET_JUMP_OFFSET(pc);
-            MOZ_ASSERT(mainEntry <= target && target < end);
-            MOZ_ASSERT(BytecodeIsJumpTarget(JSOp(*target)));
+        if (loc.isJump()){
+            BytecodeLocation target = loc.getJumpTarget();
+            MOZ_ASSERT(mainLoc <= target && target < endLoc);
+            MOZ_ASSERT(target.isJumpTarget());
 
             // Check fallthrough of conditional jump instructions.
-            if (BytecodeFallsThrough(JSOp(*pc))) {
-                jsbytecode* fallthrough = GetNextPc(pc);
-                MOZ_ASSERT(mainEntry <= fallthrough && fallthrough < end);
-                MOZ_ASSERT(BytecodeIsJumpTarget(JSOp(*fallthrough)));
+            if (loc.fallsThrough()) {
+                BytecodeLocation fallthrough = loc.next();
+                MOZ_ASSERT(mainLoc <= fallthrough && fallthrough < endLoc);
+                MOZ_ASSERT(fallthrough.isJumpTarget());
             }
         }
 
         // Check table switch case labels.
-        if (JSOp(*pc) == JSOP_TABLESWITCH) {
-            jsbytecode* pc2 = pc;
-            int32_t len = GET_JUMP_OFFSET(pc2);
+        if (loc.is(JSOP_TABLESWITCH)) {
+            BytecodeLocation target = loc.getJumpTarget();
 
             // Default target.
-            MOZ_ASSERT(mainEntry <= pc + len && pc + len < end);
-            MOZ_ASSERT(BytecodeIsJumpTarget(JSOp(*(pc + len))));
-
-            pc2 += JUMP_OFFSET_LEN;
-            int32_t low = GET_JUMP_OFFSET(pc2);
-            pc2 += JUMP_OFFSET_LEN;
-            int32_t high = GET_JUMP_OFFSET(pc2);
+            MOZ_ASSERT(mainLoc <= target && target < endLoc);
+            MOZ_ASSERT(target.isJumpTarget());
+
+            int32_t low = loc.getTableSwitchLow();
+            int32_t high = loc.getTableSwitchHigh();
 
             for (int i = 0; i < high - low + 1; i++) {
-                pc2 += JUMP_OFFSET_LEN;
-                int32_t off = (int32_t) GET_JUMP_OFFSET(pc2);
-                // Case (i + low)
-                MOZ_ASSERT_IF(off, mainEntry <= pc + off && pc + off < end);
-                MOZ_ASSERT_IF(off, BytecodeIsJumpTarget(JSOp(*(pc + off))));
+                BytecodeLocation switchCase = loc.getTableSwitchCaseByIndex(i);
+                MOZ_ASSERT_IF(switchCase != loc, mainLoc <= switchCase && switchCase < endLoc);
+                MOZ_ASSERT_IF(switchCase != loc, switchCase.isJumpTarget());
             }
         }
     }
 
     // Check catch/finally blocks as jump targets.
     if (hasTrynotes()) {
         for (const JSTryNote& tn : trynotes()) {
+            jsbytecode* end = codeEnd();
+            jsbytecode* mainEntry = main();
+
             jsbytecode* tryStart = offsetToPC(tn.start);
             jsbytecode* tryPc = tryStart - 1;
             if (tn.kind != JSTRY_CATCH && tn.kind != JSTRY_FINALLY) {
                 continue;
             }
 
             MOZ_ASSERT(JSOp(*tryPc) == JSOP_TRY);
             jsbytecode* tryTarget = tryStart + tn.length;