Bug 1147371 - Implement JSOP_PICK and JSOP_UNPICK in the expression decompiler. (r=arai)
authorShu-yu Guo <shu@rfrn.org>
Sat, 14 Jan 2017 14:51:39 -0800
changeset 374495 0b9c4069ed0f9ddf163a52b52abfd32bfffefcaa
parent 374494 e0dc4150f8ac3236dfe2804c7c933baf832398b9
child 374496 142dbb4bffc04efdb358df11293079d00af693fc
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1147371
milestone53.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 1147371 - Implement JSOP_PICK and JSOP_UNPICK in the expression decompiler. (r=arai)
js/src/jsopcode.cpp
js/src/jsopcode.h
js/src/jsopcodeinlines.h
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -455,16 +455,44 @@ BytecodeParser::simulateOp(JSOp op, uint
       case JSOP_SWAP:
         MOZ_ASSERT(ndefs == 2);
         if (offsetStack) {
             uint32_t tmp = offsetStack[stackDepth + 1];
             offsetStack[stackDepth + 1] = offsetStack[stackDepth];
             offsetStack[stackDepth] = tmp;
         }
         break;
+
+      case JSOP_PICK: {
+        jsbytecode* pc = script_->offsetToPC(offset);
+        unsigned n = GET_UINT8(pc);
+        MOZ_ASSERT(ndefs == n + 1);
+        if (offsetStack) {
+            uint32_t top = stackDepth + n;
+            uint32_t tmp = offsetStack[stackDepth];
+            for (uint32_t i = stackDepth; i < top; i++)
+                offsetStack[i] = offsetStack[i + 1];
+            offsetStack[top] = tmp;
+        }
+        break;
+      }
+
+      case JSOP_UNPICK: {
+        jsbytecode* pc = script_->offsetToPC(offset);
+        unsigned n = GET_UINT8(pc);
+        MOZ_ASSERT(ndefs == n + 1);
+        if (offsetStack) {
+            uint32_t top = stackDepth + n;
+            uint32_t tmp = offsetStack[top];
+            for (uint32_t i = top; i > stackDepth; i--)
+                offsetStack[i] = offsetStack[i - 1];
+            offsetStack[stackDepth] = tmp;
+        }
+        break;
+      }
     }
     stackDepth += ndefs;
     return stackDepth;
 }
 
 bool
 BytecodeParser::recordBytecode(uint32_t offset, const uint32_t* offsetStack,
                                uint32_t stackDepth)
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -418,16 +418,17 @@ BytecodeFallsThrough(JSOp op)
 {
     switch (op) {
       case JSOP_GOTO:
       case JSOP_DEFAULT:
       case JSOP_RETURN:
       case JSOP_RETRVAL:
       case JSOP_FINALYIELDRVAL:
       case JSOP_THROW:
+      case JSOP_THROWMSG:
       case JSOP_TABLESWITCH:
         return false;
       case JSOP_GOSUB:
         /* These fall through indirectly, after executing a 'finally'. */
         return true;
       default:
         return true;
     }
--- a/js/src/jsopcodeinlines.h
+++ b/js/src/jsopcodeinlines.h
@@ -22,16 +22,17 @@ GetDefCount(JSScript* script, unsigned o
      * Add an extra pushed value for OR/AND opcodes, so that they are included
      * in the pushed array of stack values for type inference.
      */
     switch (JSOp(*pc)) {
       case JSOP_OR:
       case JSOP_AND:
         return 1;
       case JSOP_PICK:
+      case JSOP_UNPICK:
         /*
          * Pick pops and pushes how deep it looks in the stack + 1
          * items. i.e. if the stack were |a b[2] c[1] d[0]|, pick 2
          * would pop b, c, and d to rearrange the stack to |a c[0]
          * d[1] b[2]|.
          */
         return pc[1] + 1;
       default:
@@ -39,17 +40,17 @@ GetDefCount(JSScript* script, unsigned o
     }
 }
 
 static inline unsigned
 GetUseCount(JSScript* script, unsigned offset)
 {
     jsbytecode* pc = script->offsetToPC(offset);
 
-    if (JSOp(*pc) == JSOP_PICK)
+    if (JSOp(*pc) == JSOP_PICK || JSOp(*pc) == JSOP_UNPICK)
         return pc[1] + 1;
     if (CodeSpec[*pc].nuses == -1)
         return StackUses(script, pc);
     return CodeSpec[*pc].nuses;
 }
 
 static inline JSOp
 ReverseCompareOp(JSOp op)