diff --git a/js/src/imacro_asm.js.in b/js/src/imacro_asm.js.in index 132e4d1c19af..ded9fb2cb665 100644 --- a/js/src/imacro_asm.js.in +++ b/js/src/imacro_asm.js.in @@ -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 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++) { diff --git a/js/src/imacros.c.out b/js/src/imacros.c.out index c85faa0eb44c..168d706a7979 100644 --- a/js/src/imacros.c.out +++ b/js/src/imacros.c.out @@ -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; +} diff --git a/js/src/imacros.jsasm b/js/src/imacros.jsasm index 3f062fd2f431..de88da8fb018 100644 --- a/js/src/imacros.jsasm +++ b/js/src/imacros.jsasm @@ -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 diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index ee4eceb3cf11..0ee60e65ed42 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -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) diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 9cfe0caf5b4c..1888c4aface8 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -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; diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index 93cd0258e84f..654a83d663e2 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -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.