summaryrefslogtreecommitdiffstats
path: root/js/src/jsopcode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jsopcode.cpp')
-rw-r--r--js/src/jsopcode.cpp60
1 files changed, 56 insertions, 4 deletions
diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp
index 31bbfb471..6adb5401e 100644
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -92,7 +92,8 @@ const char * const js::CodeName[] = {
/************************************************************************/
-#define COUNTS_LEN 16
+static bool
+DecompileArgumentFromStack(JSContext* cx, int formalIndex, char** res);
size_t
js::GetVariableBytecodeLength(jsbytecode* pc)
@@ -460,6 +461,34 @@ BytecodeParser::simulateOp(JSOp op, uint32_t offset, uint32_t* offsetStack, uint
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;
@@ -1230,6 +1259,24 @@ ExpressionDecompiler::decompilePC(jsbytecode* pc)
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;
@@ -1593,12 +1640,17 @@ DecompileArgumentFromStack(JSContext* cx, int formalIndex, char** res)
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();