From 00300d588dd5b61dc62a3e65c0e533ca8b22de5d Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Fri, 10 Apr 2015 11:38:50 +0200 Subject: [PATCH] Bug 1147216 part 1 - Give JSOP_LINENO a 4-byte instead of 2-byte operand. r=luke --- js/src/frontend/BytecodeEmitter.cpp | 19 +++++++++++--- js/src/frontend/BytecodeEmitter.h | 5 +++- js/src/jit-test/tests/basic/bug1147216.js | 14 +++++++++++ js/src/jsopcode.cpp | 4 +++ js/src/jsopcode.h | 30 ++++++++++++++++------- js/src/jsscript.cpp | 2 +- js/src/vm/Opcodes.h | 2 +- js/src/vm/Xdr.h | 2 +- 8 files changed, 61 insertions(+), 17 deletions(-) create mode 100644 js/src/jit-test/tests/basic/bug1147216.js diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 978486e68d8..d827c019586 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -523,15 +523,26 @@ BytecodeEmitter::checkTypeSet(JSOp op) } bool -BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t i) +BytecodeEmitter::emitUint16Operand(JSOp op, uint32_t operand) { - MOZ_ASSERT(i <= UINT16_MAX); - if (!emit3(op, UINT16_HI(i), UINT16_LO(i))) + MOZ_ASSERT(operand <= UINT16_MAX); + if (!emit3(op, UINT16_HI(operand), UINT16_LO(operand))) return false; checkTypeSet(op); return true; } +bool +BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand) +{ + ptrdiff_t off; + if (!emitN(op, 4, &off)) + return false; + SET_UINT32(code(off), operand); + checkTypeSet(op); + return true; +} + bool BytecodeEmitter::flushPops(int* npops) { @@ -6426,7 +6437,7 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn) pn->isOp(JSOP_STRICTSPREADEVAL)) { uint32_t lineNum = parser->tokenStream.srcCoords.lineNum(pn->pn_pos.begin); - if (!emitUint16Operand(JSOP_LINENO, lineNum)) + if (!emitUint32Operand(JSOP_LINENO, lineNum)) return false; } if (pn->pn_xflags & PNX_SETCALL) { diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 23187645292..f3e38612868 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -397,7 +397,10 @@ struct BytecodeEmitter // Emit a bytecode followed by an uint16 immediate operand stored in // big-endian order. - bool emitUint16Operand(JSOp op, uint32_t i); + bool emitUint16Operand(JSOp op, uint32_t operand); + + // Emit a bytecode followed by an uint32 immediate operand. + bool emitUint32Operand(JSOp op, uint32_t operand); // Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand. bool emitN(JSOp op, size_t extra, ptrdiff_t* offset = nullptr); diff --git a/js/src/jit-test/tests/basic/bug1147216.js b/js/src/jit-test/tests/basic/bug1147216.js new file mode 100644 index 00000000000..cc0df8c21d2 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug1147216.js @@ -0,0 +1,14 @@ +// Ensure JSOP_LINENO (emitted after JSOP_EVAL) handles big line +// numbers correctly. +function f() { + var s = ""; + var stack; + for (var i=0; i<66002; i++) { + s += "\n"; + if (i === 66000) + s += "eval('stack = Error().stack');"; + } + eval(s); + assertEq(stack.indexOf("line 66002") > 0, true); +} +f(); diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index cde39fcdd91..84be8689acb 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -1041,6 +1041,10 @@ js::Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc, Sprint(sp, " %u", GET_LOCALNO(pc)); break; + case JOF_UINT32: + Sprint(sp, " %u", GET_UINT32(pc)); + break; + { int i; diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index d8d82733a57..6d6794600f7 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -48,8 +48,8 @@ enum { JOF_UINT8 = 13, /* uint8_t immediate, e.g. top 8 bits of 24-bit atom index */ JOF_INT32 = 14, /* int32_t immediate operand */ - JOF_OBJECT = 15, /* unsigned 16-bit object index */ - /* 16 is unused */ + JOF_UINT32 = 15, /* uint32_t immediate operand */ + JOF_OBJECT = 16, /* unsigned 16-bit object index */ JOF_REGEXP = 17, /* unsigned 32-bit regexp index */ JOF_INT8 = 18, /* int8_t immediate operand */ JOF_ATOMOBJECT = 19, /* uint16_t constant index + object index */ @@ -222,8 +222,8 @@ GET_INT8(const jsbytecode* pc) return int8_t(pc[1]); } -static MOZ_ALWAYS_INLINE int32_t -GET_INT32(const jsbytecode* pc) +static MOZ_ALWAYS_INLINE uint32_t +GET_UINT32(const jsbytecode* pc) { return (uint32_t(pc[1]) << 24) | (uint32_t(pc[2]) << 16) | @@ -232,12 +232,24 @@ GET_INT32(const jsbytecode* pc) } static MOZ_ALWAYS_INLINE void -SET_INT32(jsbytecode* pc, uint32_t i) +SET_UINT32(jsbytecode* pc, uint32_t u) { - pc[1] = jsbytecode(uint32_t(i) >> 24); - pc[2] = jsbytecode(uint32_t(i) >> 16); - pc[3] = jsbytecode(uint32_t(i) >> 8); - pc[4] = jsbytecode(uint32_t(i)); + pc[1] = jsbytecode(u >> 24); + pc[2] = jsbytecode(u >> 16); + pc[3] = jsbytecode(u >> 8); + pc[4] = jsbytecode(u); +} + +static MOZ_ALWAYS_INLINE int32_t +GET_INT32(const jsbytecode* pc) +{ + return static_cast(GET_UINT32(pc)); +} + +static MOZ_ALWAYS_INLINE void +SET_INT32(jsbytecode* pc, int32_t i) +{ + SET_UINT32(pc, static_cast(i)); } /* Index limit is determined by SN_4BYTE_OFFSET_FLAG, see frontend/BytecodeEmitter.h. */ diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index a46e20a2eed..4fb90dcf7d9 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -2928,7 +2928,7 @@ js::DescribeScriptedCallerForCompilation(JSContext* cx, MutableHandleScript mayb JSOp(*pc) == JSOP_STRICTSPREADEVAL; MOZ_ASSERT(*(pc + (isSpread ? JSOP_SPREADEVAL_LENGTH : JSOP_EVAL_LENGTH)) == JSOP_LINENO); *file = maybeScript->filename(); - *linenop = GET_UINT16(pc + (JSOp(*pc) == JSOP_EVAL ? JSOP_EVAL_LENGTH + *linenop = GET_UINT32(pc + (JSOp(*pc) == JSOP_EVAL ? JSOP_EVAL_LENGTH : JSOP_SPREADEVAL_LENGTH)); *pcOffset = pc - maybeScript->code(); *mutedErrors = maybeScript->mutedErrors(); diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h index f7eb3af2d97..45c6de65fec 100644 --- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -1166,7 +1166,7 @@ * Operands: uint32_t lineno * Stack: => */ \ - macro(JSOP_LINENO, 119,"lineno", NULL, 3, 0, 0, JOF_UINT16) \ + macro(JSOP_LINENO, 119,"lineno", NULL, 5, 0, 0, JOF_UINT32) \ \ /* * This no-op appears after the bytecode for EXPR in 'switch (EXPR) {...}' diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h index c8adca11256..d9e213d2048 100644 --- a/js/src/vm/Xdr.h +++ b/js/src/vm/Xdr.h @@ -29,7 +29,7 @@ namespace js { * * https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode */ -static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 275; +static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 276; static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);