Bug 470964 - Simulate CFG in imacro assembler and decompiler, r=brendan.

This commit is contained in:
Graydon Hoare 2009-04-24 09:07:49 -07:00
parent ce82f02bfb
commit a2d7971b07
6 changed files with 529 additions and 350 deletions

View File

@ -89,7 +89,7 @@ for (let i = 0; i < opinfo.length; i++) {
jsop2opcode[info.jsop] = info.opcode;
}
function formatoffset(n, w) {
function format_offset(n, w) {
let s = n.toString();
while (s.length < w)
s = ' ' + s;
@ -124,6 +124,41 @@ function immediate(op) {
throw new Error(info.jsop + " format not yet implemented");
}
function simulate_cfg(imacro, depth, i) {
while (i < imacro.code.length) {
let op = imacro.code[i];
depth -= (op.info.pops < 0) ? 2 + Number(op.imm1) : op.info.pops;
depth += op.info.pushes;
if (imacro.depths.hasOwnProperty(i) && imacro.depths[i] != depth)
throw Error("Mismatched depth at " + imacro.filename + ":" + op.line);
/*
* Underflowing depth isn't necessarily fatal; most of the imacros
* assume they are called with N>0 args so some assume it's ok to go
* to some depth <N. We simulate starting from 0, as we've no idea
* what else to do.
*
* if (depth < 0)
* throw Error("Negative static-stack depth at " + imacro.filename + ":" + op.line);
*/
if (depth > imacro.maxdepth)
imacro.maxdepth = depth;
imacro.depths[i] = depth;
if (op.hasOwnProperty("target_index")) {
if (op.target_index <= i)
throw Error("Backward jump at " + imacro.filename + ":" + op.line);
simulate_cfg(imacro, depth, op.target_index);
if (op.info.opname == "goto" || op.info.opname == "gotox")
return;
}
++i;
}
}
/*
* Syntax (spaces are significant only to delimit tokens):
*
@ -156,6 +191,7 @@ const line_regexp = new RegExp(line_regexp_parts.join(""));
function assemble(filename) {
let igroup = null, imacro = null;
let opcode2extra = [];
let igroups = [];
print("/* GENERATED BY imacro_asm.js -- DO NOT EDIT!!! */");
@ -204,7 +240,10 @@ function assemble(filename) {
offset: 0,
code: [],
labeldefs: {},
labelrefs: {}
labeldef_indexes: {},
labelrefs: {},
filename: filename,
depths: {}
};
break;
@ -232,14 +271,16 @@ function assemble(filename) {
for (let k = 0; k < imacro.code.length; k++) {
let op = imacro.code[k];
print("/*" + formatoffset(op.offset,2) + "*/ " + op.info.jsop +
print("/*" + format_offset(op.offset,2) + "*/ " + op.info.jsop +
(op.imm1 ? ", " + immediate(op) : "") + ",");
depth -= (op.info.pops < 0) ? 2 + op.imm1 : op.info.pops;
depth += op.info.pushes;
if (depth > maxdepth)
maxdepth = depth;
}
imacro.maxdepth = 0;
simulate_cfg(imacro, 0, 0);
if (imacro.maxdepth > maxdepth)
maxdepth = imacro.maxdepth;
print(" },");
}
@ -250,6 +291,7 @@ function assemble(filename) {
do {
opcode2extra[opcode] = maxdepth;
} while (opcode++ != oplast);
igroups.push(igroup);
igroup = null;
} else {
ASSERT(igroup);
@ -271,6 +313,7 @@ function assemble(filename) {
ASSERT(op.hasOwnProperty('target'));
let next = op.target;
op.target = imacro.labeldefs[label] - op.offset;
op.target_index = imacro.labeldef_indexes[label];
if (next < 0)
break;
link = next;
@ -298,14 +341,17 @@ function assemble(filename) {
if (!imacro)
throw new Error("opcode " + opname + " outside of .imacro");
if (label)
if (label) {
imacro.labeldefs[label] = imacro.offset;
imacro.labeldef_indexes[label] = imacro.code.length;
}
let op = {offset: imacro.offset, info: info, imm1: imm1, imm2: imm2};
let op = {offset: imacro.offset, info: info, imm1: imm1, imm2: imm2, line:(i+1) };
if (info.flags.indexOf("JOF_JUMP") >= 0) {
if (imacro.labeldefs.hasOwnProperty(imm1)) {
// Backward reference can be resolved right away, no backpatching needed.
op.target = imacro.labeldefs[imm1] - op.offset;
op.target_index = imacro.labeldef_indexes[imm1];
} else {
// Link op into the .target-linked backpatch chain at labelrefs[imm1].
// The linked list terminates with a -1 sentinel.
@ -329,6 +375,16 @@ function assemble(filename) {
for (let i in opcode2extra)
print(" || x == " + opinfo[i].jsop + " \\");
print(")");
print("jsbytecode*\njs_GetImacroStart(jsbytecode* pc) {");
for each (let g in igroups) {
for each (let m in g.imacros) {
let start = g.name + "_imacros." + m.name;
print(" if (size_t(pc - " + start + ") < " + m.offset + ") return " + start + ";");
}
}
print(" return NULL;");
print("}");
}
for (let i = 0; i < arguments.length; i++) {

View File

@ -1,7 +1,7 @@
/* GENERATED BY imacro_asm.js -- DO NOT EDIT!!! */
static struct {
jsbytecode any_obj[37];
jsbytecode obj_any[39];
jsbytecode any_obj[34];
jsbytecode obj_any[36];
} equality_imacros = {
{
/* 0*/ JSOP_DUP,
@ -11,18 +11,16 @@ static struct {
/* 8*/ JSOP_SWAP,
/* 9*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_VOID),
/*12*/ JSOP_CALL, 0, 1,
/*15*/ JSOP_IFPRIMTOP, 0, 18,
/*15*/ JSOP_IFPRIMTOP, 0, 15,
/*18*/ JSOP_GOTO, 0, 4,
/*21*/ JSOP_POP,
/*22*/ JSOP_POP,
/*23*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*26*/ JSOP_CALL, 0, 0,
/*29*/ JSOP_PRIMTOP,
/*30*/ JSOP_GOTO, 0, 5,
/*33*/ JSOP_SWAP,
/*34*/ JSOP_POP,
/*35*/ JSOP_IMACOP,
/*36*/ JSOP_STOP,
/*22*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*25*/ JSOP_CALL, 0, 0,
/*28*/ JSOP_PRIMTOP, (JSTYPE_NUMBER),
/*30*/ JSOP_SWAP,
/*31*/ JSOP_POP,
/*32*/ JSOP_IMACOP,
/*33*/ JSOP_STOP,
},
{
/* 0*/ JSOP_SWAP,
@ -33,25 +31,23 @@ static struct {
/* 9*/ JSOP_SWAP,
/*10*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_VOID),
/*13*/ JSOP_CALL, 0, 1,
/*16*/ JSOP_IFPRIMTOP, 0, 18,
/*16*/ JSOP_IFPRIMTOP, 0, 15,
/*19*/ JSOP_GOTO, 0, 4,
/*22*/ JSOP_POP,
/*23*/ JSOP_POP,
/*24*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*27*/ JSOP_CALL, 0, 0,
/*30*/ JSOP_PRIMTOP,
/*31*/ JSOP_GOTO, 0, 5,
/*34*/ JSOP_SWAP,
/*35*/ JSOP_POP,
/*36*/ JSOP_SWAP,
/*37*/ JSOP_IMACOP,
/*38*/ JSOP_STOP,
/*23*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*26*/ JSOP_CALL, 0, 0,
/*29*/ JSOP_PRIMTOP, (JSTYPE_NUMBER),
/*31*/ JSOP_SWAP,
/*32*/ JSOP_POP,
/*33*/ JSOP_SWAP,
/*34*/ JSOP_IMACOP,
/*35*/ JSOP_STOP,
},
};
static struct {
jsbytecode any_obj[37];
jsbytecode obj_any[39];
jsbytecode obj_obj[74];
jsbytecode any_obj[34];
jsbytecode obj_any[38];
jsbytecode obj_obj[68];
} binary_imacros = {
{
/* 0*/ JSOP_DUP,
@ -61,87 +57,81 @@ static struct {
/* 8*/ JSOP_SWAP,
/* 9*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
/*12*/ JSOP_CALL, 0, 1,
/*15*/ JSOP_IFPRIMTOP, 0, 18,
/*15*/ JSOP_IFPRIMTOP, 0, 15,
/*18*/ JSOP_GOTO, 0, 4,
/*21*/ JSOP_POP,
/*22*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*25*/ JSOP_CALL, 0, 0,
/*28*/ JSOP_PRIMTOP, (JSTYPE_NUMBER),
/*30*/ JSOP_SWAP,
/*31*/ JSOP_POP,
/*32*/ JSOP_IMACOP,
/*33*/ JSOP_STOP,
},
{
/* 0*/ JSOP_SWAP,
/* 1*/ JSOP_DUP,
/* 2*/ JSOP_DUP,
/* 3*/ JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
/* 6*/ JSOP_IFPRIMTOP, 0, 18,
/* 9*/ JSOP_SWAP,
/*10*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
/*13*/ JSOP_CALL, 0, 1,
/*16*/ JSOP_IFPRIMTOP, 0, 17,
/*19*/ JSOP_POP,
/*20*/ JSOP_DUP,
/*21*/ JSOP_GOTO, 0, 4,
/*24*/ JSOP_POP,
/*25*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*28*/ JSOP_CALL, 0, 0,
/*31*/ JSOP_PRIMTOP, (JSTYPE_NUMBER),
/*33*/ JSOP_SWAP,
/*34*/ JSOP_POP,
/*35*/ JSOP_SWAP,
/*36*/ JSOP_IMACOP,
/*37*/ JSOP_STOP,
},
{
/* 0*/ JSOP_SWAP,
/* 1*/ JSOP_DUP,
/* 2*/ JSOP_DUP,
/* 3*/ JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
/* 6*/ JSOP_IFPRIMTOP, 0, 16,
/* 9*/ JSOP_SWAP,
/*10*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
/*13*/ JSOP_CALL, 0, 1,
/*16*/ JSOP_IFPRIMTOP, 0, 15,
/*19*/ JSOP_GOTO, 0, 4,
/*22*/ JSOP_POP,
/*23*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*26*/ JSOP_CALL, 0, 0,
/*29*/ JSOP_PRIMTOP,
/*30*/ JSOP_GOTO, 0, 5,
/*29*/ JSOP_PRIMTOP, (JSTYPE_NUMBER),
/*31*/ JSOP_SWAP,
/*32*/ JSOP_POP,
/*33*/ JSOP_SWAP,
/*34*/ JSOP_POP,
/*35*/ JSOP_IMACOP,
/*36*/ JSOP_STOP,
},
{
/* 0*/ JSOP_SWAP,
/* 1*/ JSOP_DUP,
/* 2*/ JSOP_DUP,
/* 3*/ JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
/* 6*/ JSOP_IFPRIMTOP, 0, 16,
/* 9*/ JSOP_SWAP,
/*10*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
/*13*/ JSOP_CALL, 0, 1,
/*16*/ JSOP_IFPRIMTOP, 0, 18,
/*19*/ JSOP_GOTO, 0, 4,
/*22*/ JSOP_POP,
/*23*/ JSOP_POP,
/*24*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*27*/ JSOP_CALL, 0, 0,
/*30*/ JSOP_PRIMTOP,
/*31*/ JSOP_GOTO, 0, 5,
/*34*/ JSOP_SWAP,
/*35*/ JSOP_POP,
/*36*/ JSOP_SWAP,
/*37*/ JSOP_IMACOP,
/*38*/ JSOP_STOP,
},
{
/* 0*/ JSOP_SWAP,
/* 1*/ JSOP_DUP,
/* 2*/ JSOP_DUP,
/* 3*/ JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
/* 6*/ JSOP_IFPRIMTOP, 0, 16,
/* 9*/ JSOP_SWAP,
/*10*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
/*13*/ JSOP_CALL, 0, 1,
/*16*/ JSOP_IFPRIMTOP, 0, 18,
/*19*/ JSOP_GOTO, 0, 4,
/*22*/ JSOP_POP,
/*23*/ JSOP_POP,
/*24*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*27*/ JSOP_CALL, 0, 0,
/*30*/ JSOP_PRIMTOP,
/*31*/ JSOP_GOTO, 0, 5,
/*34*/ JSOP_SWAP,
/*35*/ JSOP_POP,
/*36*/ JSOP_SWAP,
/*37*/ JSOP_DUP,
/*38*/ JSOP_DUP,
/*39*/ JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
/*42*/ JSOP_IFPRIMTOP, 0, 16,
/*45*/ JSOP_SWAP,
/*46*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
/*49*/ JSOP_CALL, 0, 1,
/*52*/ JSOP_IFPRIMTOP, 0, 18,
/*55*/ JSOP_GOTO, 0, 4,
/*58*/ JSOP_POP,
/*59*/ JSOP_POP,
/*60*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*63*/ JSOP_CALL, 0, 0,
/*66*/ JSOP_PRIMTOP,
/*67*/ JSOP_GOTO, 0, 5,
/*70*/ JSOP_SWAP,
/*71*/ JSOP_POP,
/*72*/ JSOP_IMACOP,
/*73*/ JSOP_STOP,
/*34*/ JSOP_DUP,
/*35*/ JSOP_DUP,
/*36*/ JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
/*39*/ JSOP_IFPRIMTOP, 0, 16,
/*42*/ JSOP_SWAP,
/*43*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
/*46*/ JSOP_CALL, 0, 1,
/*49*/ JSOP_IFPRIMTOP, 0, 15,
/*52*/ JSOP_GOTO, 0, 4,
/*55*/ JSOP_POP,
/*56*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*59*/ JSOP_CALL, 0, 0,
/*62*/ JSOP_PRIMTOP, (JSTYPE_NUMBER),
/*64*/ JSOP_SWAP,
/*65*/ JSOP_POP,
/*66*/ JSOP_IMACOP,
/*67*/ JSOP_STOP,
},
};
static struct {
jsbytecode any_obj[37];
jsbytecode obj_any[39];
jsbytecode obj_obj[74];
jsbytecode any_obj[34];
jsbytecode obj_any[36];
jsbytecode obj_obj[68];
} add_imacros = {
{
/* 0*/ JSOP_DUP,
@ -151,18 +141,37 @@ static struct {
/* 8*/ JSOP_SWAP,
/* 9*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_VOID),
/*12*/ JSOP_CALL, 0, 1,
/*15*/ JSOP_IFPRIMTOP, 0, 18,
/*15*/ JSOP_IFPRIMTOP, 0, 15,
/*18*/ JSOP_GOTO, 0, 4,
/*21*/ JSOP_POP,
/*22*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*25*/ JSOP_CALL, 0, 0,
/*28*/ JSOP_PRIMTOP, (JSTYPE_VOID),
/*30*/ JSOP_SWAP,
/*31*/ JSOP_POP,
/*32*/ JSOP_ADD,
/*33*/ JSOP_STOP,
},
{
/* 0*/ JSOP_SWAP,
/* 1*/ JSOP_DUP,
/* 2*/ JSOP_DUP,
/* 3*/ JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
/* 6*/ JSOP_IFPRIMTOP, 0, 16,
/* 9*/ JSOP_SWAP,
/*10*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_VOID),
/*13*/ JSOP_CALL, 0, 1,
/*16*/ JSOP_IFPRIMTOP, 0, 15,
/*19*/ JSOP_GOTO, 0, 4,
/*22*/ JSOP_POP,
/*23*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*26*/ JSOP_CALL, 0, 0,
/*29*/ JSOP_PRIMTOP,
/*30*/ JSOP_GOTO, 0, 5,
/*29*/ JSOP_PRIMTOP, (JSTYPE_VOID),
/*31*/ JSOP_SWAP,
/*32*/ JSOP_POP,
/*33*/ JSOP_SWAP,
/*34*/ JSOP_POP,
/*35*/ JSOP_ADD,
/*36*/ JSOP_STOP,
/*34*/ JSOP_ADD,
/*35*/ JSOP_STOP,
},
{
/* 0*/ JSOP_SWAP,
@ -173,63 +182,36 @@ static struct {
/* 9*/ JSOP_SWAP,
/*10*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_VOID),
/*13*/ JSOP_CALL, 0, 1,
/*16*/ JSOP_IFPRIMTOP, 0, 18,
/*16*/ JSOP_IFPRIMTOP, 0, 15,
/*19*/ JSOP_GOTO, 0, 4,
/*22*/ JSOP_POP,
/*23*/ JSOP_POP,
/*24*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*27*/ JSOP_CALL, 0, 0,
/*30*/ JSOP_PRIMTOP,
/*31*/ JSOP_GOTO, 0, 5,
/*34*/ JSOP_SWAP,
/*35*/ JSOP_POP,
/*36*/ JSOP_SWAP,
/*37*/ JSOP_ADD,
/*38*/ JSOP_STOP,
},
{
/* 0*/ JSOP_SWAP,
/* 1*/ JSOP_DUP,
/* 2*/ JSOP_DUP,
/* 3*/ JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
/* 6*/ JSOP_IFPRIMTOP, 0, 16,
/* 9*/ JSOP_SWAP,
/*10*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_VOID),
/*13*/ JSOP_CALL, 0, 1,
/*16*/ JSOP_IFPRIMTOP, 0, 18,
/*19*/ JSOP_GOTO, 0, 4,
/*22*/ JSOP_POP,
/*23*/ JSOP_POP,
/*24*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*27*/ JSOP_CALL, 0, 0,
/*30*/ JSOP_PRIMTOP,
/*31*/ JSOP_GOTO, 0, 5,
/*34*/ JSOP_SWAP,
/*35*/ JSOP_POP,
/*36*/ JSOP_SWAP,
/*37*/ JSOP_DUP,
/*38*/ JSOP_DUP,
/*39*/ JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
/*42*/ JSOP_IFPRIMTOP, 0, 16,
/*45*/ JSOP_SWAP,
/*46*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_VOID),
/*49*/ JSOP_CALL, 0, 1,
/*52*/ JSOP_IFPRIMTOP, 0, 18,
/*55*/ JSOP_GOTO, 0, 4,
/*58*/ JSOP_POP,
/*59*/ JSOP_POP,
/*60*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*63*/ JSOP_CALL, 0, 0,
/*66*/ JSOP_PRIMTOP,
/*67*/ JSOP_GOTO, 0, 5,
/*70*/ JSOP_SWAP,
/*71*/ JSOP_POP,
/*72*/ JSOP_ADD,
/*73*/ JSOP_STOP,
/*23*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*26*/ JSOP_CALL, 0, 0,
/*29*/ JSOP_PRIMTOP, (JSTYPE_VOID),
/*31*/ JSOP_SWAP,
/*32*/ JSOP_POP,
/*33*/ JSOP_SWAP,
/*34*/ JSOP_DUP,
/*35*/ JSOP_DUP,
/*36*/ JSOP_GETPROP, 0, COMMON_ATOM_INDEX(valueOf),
/*39*/ JSOP_IFPRIMTOP, 0, 16,
/*42*/ JSOP_SWAP,
/*43*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_VOID),
/*46*/ JSOP_CALL, 0, 1,
/*49*/ JSOP_IFPRIMTOP, 0, 15,
/*52*/ JSOP_GOTO, 0, 4,
/*55*/ JSOP_POP,
/*56*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*59*/ JSOP_CALL, 0, 0,
/*62*/ JSOP_PRIMTOP, (JSTYPE_VOID),
/*64*/ JSOP_SWAP,
/*65*/ JSOP_POP,
/*66*/ JSOP_ADD,
/*67*/ JSOP_STOP,
},
};
static struct {
jsbytecode sign[37];
jsbytecode sign[39];
} unary_imacros = {
{
/* 0*/ JSOP_DUP,
@ -243,18 +225,19 @@ static struct {
/*18*/ JSOP_GOTO, 0, 9,
/*21*/ JSOP_SWAP,
/*22*/ JSOP_POP,
/*23*/ JSOP_GOTO, 0, 12,
/*23*/ JSOP_GOTO, 0, 14,
/*26*/ JSOP_POP,
/*27*/ JSOP_POP,
/*28*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*31*/ JSOP_CALL, 0, 0,
/*34*/ JSOP_PRIMTOP,
/*35*/ JSOP_IMACOP,
/*36*/ JSOP_STOP,
/*27*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
/*30*/ JSOP_CALL, 0, 0,
/*33*/ JSOP_PRIMTOP, (JSTYPE_NUMBER),
/*35*/ JSOP_SWAP,
/*36*/ JSOP_POP,
/*37*/ JSOP_IMACOP,
/*38*/ JSOP_STOP,
},
};
static struct {
jsbytecode String[39];
jsbytecode String[36];
} call_imacros = {
{
/* 0*/ JSOP_DUP,
@ -263,23 +246,21 @@ static struct {
/* 5*/ JSOP_IFPRIMTOP, 0, 13,
/* 8*/ JSOP_SWAP,
/* 9*/ JSOP_CALL, 0, 0,
/*12*/ JSOP_IFPRIMTOP, 0, 21,
/*12*/ JSOP_IFPRIMTOP, 0, 18,
/*15*/ JSOP_GOTO, 0, 4,
/*18*/ JSOP_POP,
/*19*/ JSOP_POP,
/*20*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
/*23*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_STRING),
/*26*/ JSOP_CALL, 0, 1,
/*29*/ JSOP_PRIMTOP,
/*30*/ JSOP_GOTO, 0, 5,
/*33*/ JSOP_SWAP,
/*34*/ JSOP_POP,
/*35*/ JSOP_CALL, 0, 1,
/*38*/ JSOP_STOP,
/*19*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
/*22*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_STRING),
/*25*/ JSOP_CALL, 0, 1,
/*28*/ JSOP_PRIMTOP, (JSTYPE_STRING),
/*30*/ JSOP_SWAP,
/*31*/ JSOP_POP,
/*32*/ JSOP_CALL, 0, 1,
/*35*/ JSOP_STOP,
},
};
static struct {
jsbytecode String[39];
jsbytecode String[36];
} new_imacros = {
{
/* 0*/ JSOP_DUP,
@ -288,19 +269,17 @@ static struct {
/* 5*/ JSOP_IFPRIMTOP, 0, 13,
/* 8*/ JSOP_SWAP,
/* 9*/ JSOP_CALL, 0, 0,
/*12*/ JSOP_IFPRIMTOP, 0, 21,
/*12*/ JSOP_IFPRIMTOP, 0, 18,
/*15*/ JSOP_GOTO, 0, 4,
/*18*/ JSOP_POP,
/*19*/ JSOP_POP,
/*20*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
/*23*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_STRING),
/*26*/ JSOP_CALL, 0, 1,
/*29*/ JSOP_PRIMTOP,
/*30*/ JSOP_GOTO, 0, 5,
/*33*/ JSOP_SWAP,
/*34*/ JSOP_POP,
/*35*/ JSOP_NEW, 0, 1,
/*38*/ JSOP_STOP,
/*19*/ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
/*22*/ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_STRING),
/*25*/ JSOP_CALL, 0, 1,
/*28*/ JSOP_PRIMTOP, (JSTYPE_STRING),
/*30*/ JSOP_SWAP,
/*31*/ JSOP_POP,
/*32*/ JSOP_NEW, 0, 1,
/*35*/ JSOP_STOP,
},
};
static struct {
@ -796,10 +775,10 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
0, /* JSOP_ELEMDEC */
0, /* JSOP_GETPROP */
0, /* JSOP_SETPROP */
2, /* JSOP_GETELEM */
3, /* JSOP_SETELEM */
1, /* JSOP_GETELEM */
2, /* JSOP_SETELEM */
0, /* JSOP_CALLNAME */
2, /* JSOP_CALL */
3, /* JSOP_CALL */
0, /* JSOP_NAME */
0, /* JSOP_DOUBLE */
0, /* JSOP_STRING */
@ -816,14 +795,14 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
0, /* JSOP_STRICTEQ */
0, /* JSOP_STRICTNE */
0, /* JSOP_SETCALL */
3, /* JSOP_ITER */
2, /* JSOP_ITER */
2, /* JSOP_NEXTITER */
0, /* JSOP_ENDITER */
8, /* JSOP_APPLY */
0, /* JSOP_SWAP */
0, /* JSOP_OBJECT */
0, /* JSOP_POP */
2, /* JSOP_NEW */
3, /* JSOP_NEW */
0, /* JSOP_TRAP */
0, /* JSOP_GETARG */
0, /* JSOP_SETARG */
@ -833,7 +812,7 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
0, /* JSOP_NEWINIT */
0, /* JSOP_ENDINIT */
0, /* JSOP_INITPROP */
3, /* JSOP_INITELEM */
2, /* JSOP_INITELEM */
0, /* JSOP_DEFSHARP */
0, /* JSOP_USESHARP */
0, /* JSOP_INCARG */
@ -935,7 +914,7 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
0, /* JSOP_RESETBASE0 */
0, /* JSOP_STARTXML */
0, /* JSOP_STARTXMLEXPR */
3, /* JSOP_CALLELEM */
2, /* JSOP_CALLELEM */
0, /* JSOP_STOP */
0, /* JSOP_GETXPROP */
0, /* JSOP_CALLXMLNAME */
@ -1001,3 +980,50 @@ uint8 js_opcode2extra[JSOP_LIMIT] = {
|| x == JSOP_INITELEM \
|| x == JSOP_CALLELEM \
)
jsbytecode*
js_GetImacroStart(jsbytecode* pc) {
if (size_t(pc - equality_imacros.any_obj) < 34) return equality_imacros.any_obj;
if (size_t(pc - equality_imacros.obj_any) < 36) return equality_imacros.obj_any;
if (size_t(pc - binary_imacros.any_obj) < 34) return binary_imacros.any_obj;
if (size_t(pc - binary_imacros.obj_any) < 38) return binary_imacros.obj_any;
if (size_t(pc - binary_imacros.obj_obj) < 68) return binary_imacros.obj_obj;
if (size_t(pc - add_imacros.any_obj) < 34) return add_imacros.any_obj;
if (size_t(pc - add_imacros.obj_any) < 36) return add_imacros.obj_any;
if (size_t(pc - add_imacros.obj_obj) < 68) return add_imacros.obj_obj;
if (size_t(pc - unary_imacros.sign) < 39) return unary_imacros.sign;
if (size_t(pc - call_imacros.String) < 36) return call_imacros.String;
if (size_t(pc - new_imacros.String) < 36) return new_imacros.String;
if (size_t(pc - apply_imacros.apply0) < 8) return apply_imacros.apply0;
if (size_t(pc - apply_imacros.apply1) < 12) return apply_imacros.apply1;
if (size_t(pc - apply_imacros.apply2) < 16) return apply_imacros.apply2;
if (size_t(pc - apply_imacros.apply3) < 21) return apply_imacros.apply3;
if (size_t(pc - apply_imacros.apply4) < 26) return apply_imacros.apply4;
if (size_t(pc - apply_imacros.apply5) < 31) return apply_imacros.apply5;
if (size_t(pc - apply_imacros.apply6) < 36) return apply_imacros.apply6;
if (size_t(pc - apply_imacros.apply7) < 41) return apply_imacros.apply7;
if (size_t(pc - apply_imacros.apply8) < 46) return apply_imacros.apply8;
if (size_t(pc - apply_imacros.call0) < 7) return apply_imacros.call0;
if (size_t(pc - apply_imacros.call1) < 7) return apply_imacros.call1;
if (size_t(pc - apply_imacros.call2) < 7) return apply_imacros.call2;
if (size_t(pc - apply_imacros.call3) < 7) return apply_imacros.call3;
if (size_t(pc - apply_imacros.call4) < 7) return apply_imacros.call4;
if (size_t(pc - apply_imacros.call5) < 7) return apply_imacros.call5;
if (size_t(pc - apply_imacros.call6) < 7) return apply_imacros.call6;
if (size_t(pc - apply_imacros.call7) < 7) return apply_imacros.call7;
if (size_t(pc - apply_imacros.call8) < 7) return apply_imacros.call8;
if (size_t(pc - iter_imacros.for_in) < 13) return iter_imacros.for_in;
if (size_t(pc - iter_imacros.for_each) < 13) return iter_imacros.for_each;
if (size_t(pc - iter_imacros.for_in_native) < 10) return iter_imacros.for_in_native;
if (size_t(pc - iter_imacros.for_each_native) < 10) return iter_imacros.for_each_native;
if (size_t(pc - nextiter_imacros.custom_iter_next) < 12) return nextiter_imacros.custom_iter_next;
if (size_t(pc - nextiter_imacros.native_iter_next) < 12) return nextiter_imacros.native_iter_next;
if (size_t(pc - getelem_imacros.getprop) < 10) return getelem_imacros.getprop;
if (size_t(pc - getelem_imacros.getelem) < 10) return getelem_imacros.getelem;
if (size_t(pc - callelem_imacros.callprop) < 12) return callelem_imacros.callprop;
if (size_t(pc - callelem_imacros.callelem) < 12) return callelem_imacros.callelem;
if (size_t(pc - setelem_imacros.setprop) < 15) return setelem_imacros.setprop;
if (size_t(pc - setelem_imacros.setelem) < 15) return setelem_imacros.setelem;
if (size_t(pc - initelem_imacros.initprop) < 15) return initelem_imacros.initprop;
if (size_t(pc - initelem_imacros.initelem) < 15) return initelem_imacros.initelem;
return NULL;
}

View File

@ -49,14 +49,12 @@
ifprimtop 3 # any obj rval
goto 2
1: pop # any obj obj
2: pop # any obj
callprop toString # any toString obj
call 0 # any rval
primtop # any rval
goto 4 # any rval
2: callprop toString # any obj toString obj
call 0 # any obj rval
primtop (JSTYPE_NUMBER) # any obj rval
3: swap # any rval obj
pop # any rval
4: imacop # eqval
imacop # eqval
stop
.end
@ -72,14 +70,12 @@
ifprimtop 3 # any obj lval
goto 2
1: pop # any obj obj
2: pop # any obj
callprop toString # any toString obj
call 0 # any lval
primtop # any rval
goto 4 # any lval
2: callprop toString # any obj toString obj
call 0 # any obj lval
primtop (JSTYPE_NUMBER) # any obj rval
3: swap # any lval obj
pop # any lval
4: swap # lval any
swap # lval any
imacop # eqval
stop
.end
@ -99,14 +95,12 @@
ifprimtop 3 # any obj rval
goto 2
1: pop # any obj obj
2: pop # any obj
callprop toString # any toString obj
call 0 # any rval
primtop # any rval
goto 4 # any rval
2: callprop toString # any obj toString obj
call 0 # any obj rval
primtop (JSTYPE_NUMBER) # any obj rval
3: swap # any rval obj
pop # any rval
4: imacop # bval
imacop # bval
stop
.end
@ -120,16 +114,16 @@
string number # any obj valueOf obj "number"
call 1 # any obj lval
ifprimtop 3 # any obj lval
pop # any obj
dup # any obj obj
goto 2
1: pop # any obj obj
2: pop # any obj
callprop toString # any toString obj
call 0 # any lval
primtop # any rval
goto 4 # any lval
2: callprop toString # any obj toString obj
call 0 # any obj lval
primtop (JSTYPE_NUMBER) # any obj lval
3: swap # any lval obj
pop # any lval
4: swap # lval any
swap # lval any
imacop # bval
stop
.end
@ -146,32 +140,28 @@
ifprimtop 3 # obj2 obj1 lval
goto 2
1: pop # obj2 obj1 obj1
2: pop # obj2 obj1
callprop toString # obj2 toString obj1
call 0 # obj2 lval
primtop # obj2 lval
goto 4 # obj2 lval
2: callprop toString # obj2 obj1 toString obj1
call 0 # obj2 obj1 lval
primtop (JSTYPE_NUMBER) # obj2 obj1 lval
3: swap # obj2 lval obj1
pop # obj2 lval
4: swap # lval obj2
swap # lval obj2
dup # lval obj1 obj1
dup # lval obj obj obj
getprop valueOf # lval obj obj valueOf
ifprimtop 5 # lval obj obj valueOf
ifprimtop 4 # lval obj obj valueOf
swap # lval obj valueOf obj
string number # lval obj valueOf obj "number"
call 1 # lval obj rval
ifprimtop 7 # lval obj rval
goto 6
5: pop # lval obj obj
6: pop # lval obj
callprop toString # lval toString obj
call 0 # lval rval
primtop # lval rval
goto 8 # lval rval
7: swap # lval rval obj
ifprimtop 6 # lval obj rval
goto 5
4: pop # lval obj obj
5: callprop toString # lval obj toString obj
call 0 # lval obj rval
primtop (JSTYPE_NUMBER) # lval obj rval
6: swap # lval rval obj
pop # lval rval
8: imacop # bval
imacop # bval
stop
.end
@ -190,14 +180,12 @@
ifprimtop 3 # any obj rval
goto 2
1: pop # any obj obj
2: pop # any obj
callprop toString # any toString obj
call 0 # any rval
primtop # any rval
goto 4 # any rval
2: callprop toString # any obj toString obj
call 0 # any obj rval
primtop (JSTYPE_VOID) # any obj rval
3: swap # any rval obj
pop # any rval
4: add # aval
add # aval
stop
.end
@ -213,14 +201,12 @@
ifprimtop 3 # any obj lval
goto 2
1: pop # any obj obj
2: pop # any obj
callprop toString # any toString obj
call 0 # any lval
primtop # any lval
goto 4 # any lval
2: callprop toString # any obj toString obj
call 0 # any obj lval
primtop (JSTYPE_VOID) # any obj lval
3: swap # any lval obj
pop # any lval
4: swap # lval any
swap # lval any
add # aval
stop
.end
@ -237,32 +223,28 @@
ifprimtop 3 # obj2 obj1 lval
goto 2
1: pop # obj2 obj1 obj1
2: pop # obj2 obj1
callprop toString # obj2 toString obj1
call 0 # obj2 lval
primtop # obj2 lval
goto 4 # obj2 lval
2: callprop toString # obj2 obj toString obj1
call 0 # obj2 obj lval
primtop (JSTYPE_VOID) # obj2 obj lval
3: swap # obj2 lval obj1
pop # obj2 lval
4: swap # lval obj2
swap # lval obj2
dup # lval obj1 obj1
dup # lval obj obj obj
getprop valueOf # lval obj obj valueOf
ifprimtop 5 # lval obj obj valueOf
ifprimtop 4 # lval obj obj valueOf
swap # lval obj valueOf obj
string void # lval obj valueOf obj "void"
call 1 # lval obj rval
ifprimtop 7 # lval obj rval
goto 6
5: pop # lval obj obj
6: pop # lval obj
callprop toString # lval toString obj
call 0 # lval rval
primtop # lval rval
goto 8 # lval rval
7: swap # lval rval obj
ifprimtop 6 # lval obj rval
goto 5
4: pop # lval obj obj
5: callprop toString # lval obj toString obj
call 0 # lval obj rval
primtop (JSTYPE_VOID) # lval obj rval
6: swap # lval rval obj
pop # lval rval
8: add # aval
add # aval
stop
.end
@ -279,15 +261,16 @@
string number # obj valueOf obj "number"
call 1 # obj lval
ifprimtop 1 # obj lval
goto 3 # obj lval
goto 3
1: swap # lval obj
pop # lval
goto 4 # lval
goto 4
2: pop # obj obj
3: pop # obj
callprop toString # toString obj
call 0 # lval
primtop # lval
3: callprop toString # obj toString obj
call 0 # obj lval
primtop (JSTYPE_NUMBER) # obj lval
swap # lval obj
pop # lval
4: imacop # aval
stop
.end
@ -306,15 +289,13 @@
ifprimtop 3 # String this obj rval
goto 2
1: pop # String this obj obj
2: pop # String this obj
callprop valueOf # String this valueOf obj
string string # String this valueOf obj "string"
call 1 # String this rval
primtop # String this rval
goto 4 # String this rval
2: callprop valueOf # String this obj valueOf obj
string string # String this obj valueOf obj "string"
call 1 # String this obj rval
primtop (JSTYPE_STRING) # String this obj rval
3: swap # String this rval obj
pop # String this rval
4: call 1 # str
call 1 # str
stop # str
.end
@ -332,15 +313,13 @@
ifprimtop 3 # String this obj rval
goto 2
1: pop # String this obj obj
2: pop # String this obj
callprop valueOf # String this valueOf obj
string string # String this valueOf obj "string"
call 1 # String this rval
primtop # String this rval
goto 4 # String this rval
2: callprop valueOf # String this obj valueOf obj
string string # String this obj valueOf obj "string"
call 1 # String this obj rval
primtop (JSTYPE_STRING) # String this obj rval
3: swap # String this rval obj
pop # String this rval
4: new 1 # strobj
new 1 # strobj
stop # strobj
.end

View File

@ -6568,10 +6568,14 @@ js_Interpret(JSContext *cx)
BEGIN_CASE(JSOP_PRIMTOP)
JS_ASSERT(regs.sp > StackBase(fp));
lval = FETCH_OPND(-1);
i = GET_INT8(regs.pc);
if (!JSVAL_IS_PRIMITIVE(lval)) {
lval = FETCH_OPND(-2);
js_ReportValueError2(cx, JSMSG_CANT_CONVERT_TO,
JSDVG_SEARCH_STACK, lval, NULL,
"primitive type");
-2, lval, NULL,
(i == JSTYPE_VOID)
? "primitive type"
: JS_TYPE_STR(i));
goto error;
}
END_CASE(JSOP_PRIMTOP)

View File

@ -5077,17 +5077,16 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
}
} while (*--sp != v);
if (sp >= stackBase + pcdepth) {
/*
* The value comes from a temporary slot that the interpreter
* uses for GC roots or when JSOP_APPLY extended the stack to
* fit the argument array elements. Assume that it is the
* current PC that caused the exception.
*/
pc = fp->imacpc ? fp->imacpc : regs->pc;
} else {
/*
* The value may have come from beyond stackBase + pcdepth,
* meaning that it came from a temporary slot that the
* interpreter uses for GC roots or when JSOP_APPLY extended
* the stack to fit the argument array elements. Only update pc
* if beneath stackBase + pcdepth; otherwise blame existing
* (current) PC.
*/
if (sp < stackBase + pcdepth)
pc = pcstack[sp - stackBase];
}
}
release_pcstack:
@ -5103,7 +5102,16 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
regs->pc = imacpc;
fp->imacpc = NULL;
}
name = DecompileExpression(cx, script, fp->fun, pc);
/*
* FIXME: bug 489843. Stack reconstruction may have returned a pc
* value *inside* an imacro; this would confuse the decompiler.
*/
if (imacpc && size_t(pc - script->code) >= script->length)
name = FAILED_EXPRESSION_DECOMPILER;
else
name = DecompileExpression(cx, script, fp->fun, pc);
if (imacpc) {
regs->pc = savepc;
fp->imacpc = imacpc;
@ -5261,12 +5269,148 @@ js_ReconstructStackDepth(JSContext *cx, JSScript *script, jsbytecode *pc)
return ReconstructPCStack(cx, script, pc, NULL);
}
#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, -1);
static intN
SimulateOp(JSContext *cx, JSScript *script, JSOp op, const JSCodeSpec *cs,
jsbytecode *pc, jsbytecode **pcstack, uintN &pcdepth)
{
uintN nuses = js_GetStackUses(cs, op, pc);
uintN ndefs = js_GetStackDefs(cx, cs, op, script, pc);
LOCAL_ASSERT(pcdepth >= nuses);
pcdepth -= nuses;
LOCAL_ASSERT(pcdepth + ndefs <= StackDepth(script));
/*
* Fill the slots that the opcode defines withs its pc unless it just
* reshuffles the stack. In the latter case we want to preserve the
* opcode that generated the original value.
*/
switch (op) {
default:
if (pcstack) {
for (uintN i = 0; i != ndefs; ++i)
pcstack[pcdepth + i] = pc;
}
break;
case JSOP_CASE:
case JSOP_CASEX:
/* Keep the switch value. */
JS_ASSERT(ndefs == 1);
break;
case JSOP_DUP:
JS_ASSERT(ndefs == 2);
if (pcstack)
pcstack[pcdepth + 1] = pcstack[pcdepth];
break;
case JSOP_DUP2:
JS_ASSERT(ndefs == 4);
if (pcstack) {
pcstack[pcdepth + 2] = pcstack[pcdepth];
pcstack[pcdepth + 3] = pcstack[pcdepth + 1];
}
break;
case JSOP_SWAP:
JS_ASSERT(ndefs == 2);
if (pcstack) {
jsbytecode *tmp = pcstack[pcdepth + 1];
pcstack[pcdepth + 1] = pcstack[pcdepth];
pcstack[pcdepth] = tmp;
}
break;
}
pcdepth += ndefs;
return pcdepth;
}
#ifdef JS_TRACER
static intN
SimulateImacroCFG(JSContext *cx, JSScript *script,
uintN pcdepth, jsbytecode *pc, jsbytecode *target,
jsbytecode **pcstack)
{
size_t nbytes = StackDepth(script) * sizeof *pcstack;
jsbytecode** tmp_pcstack = (jsbytecode **) JS_malloc(cx, nbytes);
if (!tmp_pcstack)
return -1;
memcpy(tmp_pcstack, pcstack, nbytes);
ptrdiff_t oplen;
for (; pc < target; pc += oplen) {
JSOp op = js_GetOpcode(cx, script, pc);
const JSCodeSpec *cs = &js_CodeSpec[op];
oplen = cs->length;
if (oplen < 0)
oplen = js_GetVariableBytecodeLength(pc);
if (SimulateOp(cx, script, op, cs, pc, tmp_pcstack, pcdepth) < 0)
goto failure;
uint32 type = cs->format & JOF_TYPEMASK;
if (type == JOF_JUMP || type == JOF_JUMPX) {
ptrdiff_t jmpoff = (type == JOF_JUMP) ? GET_JUMP_OFFSET(pc)
: GET_JUMPX_OFFSET(pc);
LOCAL_ASSERT(jmpoff >= 0);
uintN tmp_pcdepth = SimulateImacroCFG(cx, script, pcdepth, pc + jmpoff,
target, tmp_pcstack);
if (tmp_pcdepth >= 0) {
pcdepth = tmp_pcdepth;
goto success;
}
if (op == JSOP_GOTO || op == JSOP_GOTOX)
goto failure;
}
}
if (pc > target)
goto failure;
LOCAL_ASSERT(pc == target);
success:
LOCAL_ASSERT(pcdepth >= 0);
memcpy(pcstack, tmp_pcstack, nbytes);
JS_free(cx, tmp_pcstack);
return pcdepth;
failure:
JS_free(cx, tmp_pcstack);
return -1;
}
static intN
ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
jsbytecode **pcstack);
static intN
ReconstructImacroPCStack(JSContext *cx, JSScript *script,
jsbytecode *imacstart, jsbytecode *target,
jsbytecode **pcstack)
{
/*
* Begin with a recursive call back to ReconstructPCStack to pick up
* the state-of-the-world at the *start* of the imacro.
*/
JSStackFrame *fp = js_GetScriptedCaller(cx, NULL);
JS_ASSERT(fp->imacpc);
uintN pcdepth = ReconstructPCStack(cx, script, fp->imacpc, pcstack);
if (pcdepth < 0)
return pcdepth;
return SimulateImacroCFG(cx, script, pcdepth, imacstart, target, pcstack);
}
extern jsbytecode* js_GetImacroStart(jsbytecode* pc);
#endif
static intN
ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
jsbytecode **pcstack)
{
#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, -1);
/*
* Walk forward from script->main and compute the stack depth and stack of
* operand-generating opcode PCs in pcstack.
@ -5274,9 +5418,16 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
* FIXME: Code to compute oplen copied from js_Disassemble1 and reduced.
* FIXME: Optimize to use last empty-stack sequence point.
*/
#ifdef JS_TRACER
jsbytecode *imacstart = js_GetImacroStart(target);
if (imacstart)
return ReconstructImacroPCStack(cx, script, imacstart, target, pcstack);
#endif
LOCAL_ASSERT(script->main <= target && target < script->code + script->length);
uintN pcdepth = 0;
jsbytecode *pc = script->main;
uintN pcdepth = 0;
ptrdiff_t oplen;
for (; pc < target; pc += oplen) {
JSOp op = js_GetOpcode(cx, script, pc);
@ -5320,46 +5471,9 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
if (sn && SN_TYPE(sn) == SRC_HIDDEN)
continue;
uintN nuses = js_GetStackUses(cs, op, pc);
uintN ndefs = js_GetStackDefs(cx, cs, op, script, pc);
LOCAL_ASSERT(pcdepth >= nuses);
pcdepth -= nuses;
LOCAL_ASSERT(pcdepth + ndefs <= StackDepth(script));
if (SimulateOp(cx, script, op, cs, pc, pcstack, pcdepth) < 0)
return -1;
/*
* Fill the slots that the opcode defines withs its pc unless it just
* reshuffle the stack. In the latter case we want to preserve the
* opcode that generated the original value.
*/
switch (op) {
default:
if (pcstack) {
for (uintN i = 0; i != ndefs; ++i)
pcstack[pcdepth + i] = pc;
}
break;
case JSOP_CASE:
case JSOP_CASEX:
/* Keep the switch value. */
JS_ASSERT(ndefs == 1);
break;
case JSOP_DUP:
JS_ASSERT(ndefs == 2);
if (pcstack)
pcstack[pcdepth + 1] = pcstack[pcdepth];
break;
case JSOP_DUP2:
JS_ASSERT(ndefs == 4);
if (pcstack) {
pcstack[pcdepth + 2] = pcstack[pcdepth];
pcstack[pcdepth + 3] = pcstack[pcdepth + 1];
}
break;
}
pcdepth += ndefs;
}
LOCAL_ASSERT(pc == target);
return pcdepth;

View File

@ -493,7 +493,7 @@ OPDEF(JSOP_LEAVEBLOCK, 200,"leaveblock", NULL, 3, -1, 0, 0, JOF_UINT16
OPDEF(JSOP_IFPRIMTOP, 201,"ifprimtop", NULL, 3, 1, 1, 0, JOF_JUMP|JOF_DETECTING)
/* Throws a TypeError if the value at the top of the stack is not primitive. */
OPDEF(JSOP_PRIMTOP, 202,"primtop", NULL, 1, 1, 1, 0, JOF_BYTE)
OPDEF(JSOP_PRIMTOP, 202,"primtop", NULL, 2, 1, 1, 0, JOF_INT8)
/*
* Generator and array comprehension support.
@ -536,7 +536,7 @@ OPDEF(JSOP_INDEXBASE3, 214,"atombase3", NULL, 1, 0, 0, 0, JOF_BYTE |
OPDEF(JSOP_CALLGVAR, 215, "callgvar", NULL, 3, 0, 2, 19, JOF_ATOM|JOF_NAME|JOF_CALLOP)
OPDEF(JSOP_CALLLOCAL, 216, "calllocal", NULL, 3, 0, 2, 19, JOF_LOCAL|JOF_NAME|JOF_CALLOP)
OPDEF(JSOP_CALLARG, 217, "callarg", NULL, 3, 0, 2, 19, JOF_QARG |JOF_NAME|JOF_CALLOP)
OPDEF(JSOP_CALLBUILTIN, 218, "callbuiltin", NULL, 3, 0, 2, 0, JOF_UINT16)
OPDEF(JSOP_CALLBUILTIN, 218, "callbuiltin", NULL, 3, 1, 2, 0, JOF_UINT16)
/*
* Opcodes to hold 8-bit and 32-bit immediate integer operands.