Bug 1147371 - Always decompile argument names in self-hosted code in the caller frame. (r=arai)
authorShu-yu Guo <shu@rfrn.org>
Sat, 14 Jan 2017 14:51:39 -0800
changeset 357520 142dbb4bffc04efdb358df11293079d00af693fc
parent 357519 0b9c4069ed0f9ddf163a52b52abfd32bfffefcaa
child 357521 0d7224996287e80d2fb78ba163fd97d006a83ee4
push id10621
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 16:02:43 +0000
treeherdermozilla-aurora@dca7b42e6c67 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1147371
milestone53.0a1
Bug 1147371 - Always decompile argument names in self-hosted code in the caller frame. (r=arai)
js/src/jsopcode.cpp
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -87,17 +87,18 @@ static const char * const CodeToken[] = 
 const char * const js::CodeName[] = {
 #define OPNAME(op, val, name, ...)  name,
     FOR_EACH_OPCODE(OPNAME)
 #undef OPNAME
 };
 
 /************************************************************************/
 
-#define COUNTS_LEN 16
+static bool
+DecompileArgumentFromStack(JSContext* cx, int formalIndex, char** res);
 
 size_t
 js::GetVariableBytecodeLength(jsbytecode* pc)
 {
     JSOp op = JSOp(*pc);
     MOZ_ASSERT(CodeSpec[op].length == -1);
     switch (op) {
       case JSOP_TABLESWITCH: {
@@ -1253,16 +1254,34 @@ ExpressionDecompiler::decompilePC(jsbyte
 
     switch (op) {
       case JSOP_GETGNAME:
       case JSOP_GETNAME:
       case JSOP_GETINTRINSIC:
         return write(loadAtom(pc));
       case JSOP_GETARG: {
         unsigned slot = GET_ARGNO(pc);
+
+        // For self-hosted scripts that are called from non-self-hosted code,
+        // decompiling the parameter name in the self-hosted script is
+        // unhelpful. Decompile the argument name instead.
+        if (script->selfHosted()) {
+            char* result;
+            if (!DecompileArgumentFromStack(cx, slot, &result))
+                return false;
+
+            // Note that decompiling the argument in the parent frame might
+            // not succeed.
+            if (result) {
+		bool ok = write(result);
+                js_free(result);
+		return ok;
+            }
+        }
+
         JSAtom* atom = getArg(slot);
         if (!atom)
             return false;
         return write(atom);
       }
       case JSOP_GETLOCAL: {
         JSAtom* atom = FrameSlotName(script, pc);
         MOZ_ASSERT(atom);
@@ -1593,22 +1612,27 @@ DecompileArgumentFromStack(JSContext* cx
      * Settle on the nearest script frame, which should be the builtin that
      * called the intrinsic.
      */
     FrameIter frameIter(cx);
     MOZ_ASSERT(!frameIter.done());
     MOZ_ASSERT(frameIter.script()->selfHosted());
 
     /*
-     * Get the second-to-top frame, the caller of the builtin that called the
-     * intrinsic.
+     * Get the second-to-top frame, the non-self-hosted caller of the builtin
+     * that called the intrinsic.
      */
     ++frameIter;
-    if (frameIter.done() || !frameIter.hasScript() || frameIter.compartment() != cx->compartment())
+    if (frameIter.done() ||
+        !frameIter.hasScript() ||
+        frameIter.script()->selfHosted() ||
+        frameIter.compartment() != cx->compartment())
+    {
         return true;
+    }
 
     RootedScript script(cx, frameIter.script());
     jsbytecode* current = frameIter.pc();
 
     MOZ_ASSERT(script->containsPC(current));
 
     if (current < script->main())
         return true;