diff options
author | Brian Smith <brian@dbsoft.org> | 2023-09-16 05:38:42 -0500 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2023-09-20 03:33:33 +0200 |
commit | d8441d7c8175608835f3b56a76666f48e4da0548 (patch) | |
tree | 610784b2357dcd8f8dc0f46d2712d6917c1813bb | |
parent | c2446f2478ef847c8787092165443a8674384408 (diff) | |
download | uxp-d8441d7c8175608835f3b56a76666f48e4da0548.tar.gz |
Issue #2308 & #1240 Follow-up - Introduce new increment and decrement operations.
https://bugzilla.mozilla.org/show_bug.cgi?id=1508521
-rw-r--r-- | js/src/frontend/ElemOpEmitter.cpp | 7 | ||||
-rw-r--r-- | js/src/frontend/NameOpEmitter.cpp | 7 | ||||
-rw-r--r-- | js/src/frontend/PropOpEmitter.cpp | 7 | ||||
-rw-r--r-- | js/src/jit/BaselineCompiler.cpp | 12 | ||||
-rw-r--r-- | js/src/jit/BaselineCompiler.h | 8 | ||||
-rw-r--r-- | js/src/jit/IonBuilder.cpp | 37 | ||||
-rw-r--r-- | js/src/jit/IonBuilder.h | 1 | ||||
-rw-r--r-- | js/src/jit/SharedIC.cpp | 20 | ||||
-rw-r--r-- | js/src/jit/SharedIC.h | 2 | ||||
-rw-r--r-- | js/src/jit/x86-shared/BaseAssembler-x86-shared.h | 8 | ||||
-rw-r--r-- | js/src/vm/Interpreter-inl.h | 34 | ||||
-rw-r--r-- | js/src/vm/Interpreter.cpp | 20 | ||||
-rw-r--r-- | js/src/vm/Opcodes.h | 24 |
13 files changed, 157 insertions, 30 deletions
diff --git a/js/src/frontend/ElemOpEmitter.cpp b/js/src/frontend/ElemOpEmitter.cpp index f17b554e7a..dd6da9dcb4 100644 --- a/js/src/frontend/ElemOpEmitter.cpp +++ b/js/src/frontend/ElemOpEmitter.cpp @@ -233,7 +233,7 @@ ElemOpEmitter::emitIncDec() MOZ_ASSERT(state_ == State::Get); - JSOp binOp = isInc() ? JSOP_ADD : JSOP_SUB; + JSOp incOp = isInc() ? JSOP_INC : JSOP_DEC; if (!bce_->emit1(JSOP_POS)) { // ... N return false; } @@ -242,10 +242,7 @@ ElemOpEmitter::emitIncDec() return false; } } - if (!bce_->emit1(JSOP_ONE)) { // ... N? N 1 - return false; - } - if (!bce_->emit1(binOp)) { // ... N? N+1 + if (!bce_->emit1(incOp)) { // ... N? N+1 return false; } if (isPostIncDec()) { diff --git a/js/src/frontend/NameOpEmitter.cpp b/js/src/frontend/NameOpEmitter.cpp index 8fa7f9d966..478cd44151 100644 --- a/js/src/frontend/NameOpEmitter.cpp +++ b/js/src/frontend/NameOpEmitter.cpp @@ -339,7 +339,7 @@ NameOpEmitter::emitIncDec() { MOZ_ASSERT(state_ == State::Start); - JSOp binOp = isInc() ? JSOP_ADD : JSOP_SUB; + JSOp incOp = isInc() ? JSOP_INC : JSOP_DEC; if (!prepareForRhs()) { // ENV? V return false; } @@ -351,10 +351,7 @@ NameOpEmitter::emitIncDec() return false; } } - if (!bce_->emit1(JSOP_ONE)) { // ENV? N? N 1 - return false; - } - if (!bce_->emit1(binOp)) { // ENV? N? N+1 + if (!bce_->emit1(incOp)) { // ENV? N? N+1 return false; } if (isPostIncDec() && emittedBindOp()) { diff --git a/js/src/frontend/PropOpEmitter.cpp b/js/src/frontend/PropOpEmitter.cpp index bfbca00e1d..01e365f154 100644 --- a/js/src/frontend/PropOpEmitter.cpp +++ b/js/src/frontend/PropOpEmitter.cpp @@ -217,7 +217,7 @@ PropOpEmitter::emitIncDec(JSAtom* prop) MOZ_ASSERT(state_ == State::Get); - JSOp binOp = isInc() ? JSOP_ADD : JSOP_SUB; + JSOp incOp = isInc() ? JSOP_INC : JSOP_DEC; if (!bce_->emit1(JSOP_POS)) { // ... N return false; @@ -227,10 +227,7 @@ PropOpEmitter::emitIncDec(JSAtom* prop) return false; } } - if (!bce_->emit1(JSOP_ONE)) { // ... N? N 1 - return false; - } - if (!bce_->emit1(binOp)) { // ... N? N+1 + if (!bce_->emit1(incOp)) { // ... N? N+1 return false; } if (isPostIncDec()) { diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index 7dbd076c6b..7985a3b2a9 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -1940,6 +1940,18 @@ BaselineCompiler::emit_JSOP_NEG() } bool +BaselineCompiler::emit_JSOP_INC() +{ + return emitUnaryArith(); +} + +bool +BaselineCompiler::emit_JSOP_DEC() +{ + return emitUnaryArith(); +} + +bool BaselineCompiler::emit_JSOP_LT() { return emitCompare(); diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h index 8e9976b17f..9996c0f47f 100644 --- a/js/src/jit/BaselineCompiler.h +++ b/js/src/jit/BaselineCompiler.h @@ -242,8 +242,10 @@ namespace jit { _(JSOP_JUMPTARGET) \ _(JSOP_IS_CONSTRUCTING) \ _(JSOP_TRY_DESTRUCTURING_ITERCLOSE) \ - _(JSOP_IMPORTMETA) \ - _(JSOP_DYNAMIC_IMPORT) + _(JSOP_IMPORTMETA) \ + _(JSOP_DYNAMIC_IMPORT) \ + _(JSOP_INC) \ + _(JSOP_DEC) class BaselineCompiler : public BaselineCompilerSpecific { @@ -327,7 +329,7 @@ class BaselineCompiler : public BaselineCompilerSpecific OPCODE_LIST(EMIT_OP) #undef EMIT_OP - // JSOP_NEG, JSOP_BITNOT + // JSOP_NEG, JSOP_BITNOT, JSOP_INC, JSOP_DEC MOZ_MUST_USE bool emitUnaryArith(); // JSOP_BITXOR, JSOP_LSH, JSOP_ADD etc. diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index a440bfa598..2134d1b613 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -719,6 +719,8 @@ IonBuilder::analyzeNewLoopTypes(MBasicBlock* entry, jsbytecode* start, jsbytecod case JSOP_DIV: case JSOP_MOD: case JSOP_NEG: + case JSOP_INC: + case JSOP_DEC: type = inspector->expectedResultType(last); break; case JSOP_BIGINT: @@ -1740,6 +1742,10 @@ IonBuilder::inspectOpcode(JSOp op) case JSOP_NEG: return jsop_neg(); + case JSOP_INC: + case JSOP_DEC: + return jsop_inc_or_dec(op); + case JSOP_TOSTRING: return jsop_tostring(); @@ -5070,6 +5076,14 @@ IonBuilder::arithTrySharedStub(bool* emitted, JSOp op, stub = MUnarySharedStub::New(alloc(), right); break; + case JSOP_INC: + MOZ_ASSERT(op == JSOP_ADD && right->toConstant()->toInt32() == 1); + stub = MUnarySharedStub::New(alloc(), left); + break; + case JSOP_DEC: + MOZ_ASSERT(op == JSOP_SUB && right->toConstant()->toInt32() == 1); + stub = MUnarySharedStub::New(alloc(), left); + break; case JSOP_ADD: case JSOP_SUB: case JSOP_MUL: @@ -5203,6 +5217,29 @@ IonBuilder::jsop_neg() } bool +IonBuilder::jsop_inc_or_dec(JSOp op) +{ + // As above, pass constant without slot traffic. + MConstant* one = MConstant::New(alloc(), Int32Value(1)); + current->add(one); + + MDefinition* value = current->pop(); + + switch (op) { + case JSOP_INC: + op = JSOP_ADD; + break; + case JSOP_DEC: + op = JSOP_SUB; + break; + default: + MOZ_CRASH("jsop_inc_or_dec with bad op"); + } + + return jsop_binary_arith(op, value, one); +} + +bool IonBuilder::jsop_tostring() { if (current->peek(-1)->type() == MIRType::String) diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index 6f3fc027f6..162edb36f2 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -692,6 +692,7 @@ class IonBuilder MOZ_MUST_USE bool jsop_pow(); MOZ_MUST_USE bool jsop_pos(); MOZ_MUST_USE bool jsop_neg(); + MOZ_MUST_USE bool jsop_inc_or_dec(JSOp op); MOZ_MUST_USE bool jsop_tostring(); MOZ_MUST_USE bool jsop_setarg(uint32_t arg); MOZ_MUST_USE bool jsop_defvar(uint32_t index); diff --git a/js/src/jit/SharedIC.cpp b/js/src/jit/SharedIC.cpp index 375edb1400..0afc7e12b5 100644 --- a/js/src/jit/SharedIC.cpp +++ b/js/src/jit/SharedIC.cpp @@ -1469,21 +1469,33 @@ DoUnaryArithFallback(JSContext* cx, void* payload, ICUnaryArith_Fallback* stub_, JSOp op = JSOp(*pc); FallbackICSpew(cx, stub, "UnaryArith(%s)", CodeName[op]); + // The unary operations take a copied val because the original value is needed + // below. + RootedValue valCopy(cx, val); switch (op) { case JSOP_BITNOT: { - RootedValue valCopy(cx, val); if (!BitNot(cx, &valCopy, res)) { return false; } break; } case JSOP_NEG: { - // We copy val here because the original value is needed below. - RootedValue valCopy(cx, val); - if (!NegOperation(cx, script, pc, &valCopy, res)) + if (!NegOperation(cx, script, pc, &valCopy, res)) return false; break; } + case JSOP_INC: { + if (!IncOperation(cx, &valCopy, res)) { + return false; + } + break; + } + case JSOP_DEC: { + if (!DecOperation(cx, &valCopy, res)) { + return false; + } + break; + } default: MOZ_CRASH("Unexpected op"); } diff --git a/js/src/jit/SharedIC.h b/js/src/jit/SharedIC.h index d0038c9378..d259ebf0bc 100644 --- a/js/src/jit/SharedIC.h +++ b/js/src/jit/SharedIC.h @@ -1855,6 +1855,8 @@ class ICBinaryArith_DoubleWithInt32 : public ICStub // UnaryArith // JSOP_BITNOT // JSOP_NEG +// JSOP_INC +// JSOP_DEC class ICUnaryArith_Fallback : public ICFallbackStub { diff --git a/js/src/jit/x86-shared/BaseAssembler-x86-shared.h b/js/src/jit/x86-shared/BaseAssembler-x86-shared.h index b5f800cdab..e8f7f07e2c 100644 --- a/js/src/jit/x86-shared/BaseAssembler-x86-shared.h +++ b/js/src/jit/x86-shared/BaseAssembler-x86-shared.h @@ -4937,7 +4937,7 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off void twoByteOp8(TwoByteOpcodeID opcode, RegisterID rm, RegisterID reg) { m_buffer.ensureSpace(MaxInstructionSize); - emitRexIf(byteRegRequiresRex(reg)|byteRegRequiresRex(rm), reg, 0, rm); + emitRexIf(byteRegRequiresRex(reg)||byteRegRequiresRex(rm), reg, 0, rm); m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); m_buffer.putByteUnchecked(opcode); registerModRM(rm, reg); @@ -4946,7 +4946,7 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off void twoByteOp8(TwoByteOpcodeID opcode, int32_t offset, RegisterID base, RegisterID reg) { m_buffer.ensureSpace(MaxInstructionSize); - emitRexIf(byteRegRequiresRex(reg)|regRequiresRex(base), reg, 0, base); + emitRexIf(byteRegRequiresRex(reg)||regRequiresRex(base), reg, 0, base); m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); m_buffer.putByteUnchecked(opcode); memoryModRM(offset, base, reg); @@ -4956,7 +4956,7 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off int scale, RegisterID reg) { m_buffer.ensureSpace(MaxInstructionSize); - emitRexIf(byteRegRequiresRex(reg)|regRequiresRex(base)|regRequiresRex(index), + emitRexIf(byteRegRequiresRex(reg)||regRequiresRex(base)||regRequiresRex(index), reg, index, base); m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); m_buffer.putByteUnchecked(opcode); @@ -4970,7 +4970,7 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off void twoByteOp8_movx(TwoByteOpcodeID opcode, RegisterID rm, RegisterID reg) { m_buffer.ensureSpace(MaxInstructionSize); - emitRexIf(regRequiresRex(reg)|byteRegRequiresRex(rm), reg, 0, rm); + emitRexIf(regRequiresRex(reg)||byteRegRequiresRex(rm), reg, 0, rm); m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); m_buffer.putByteUnchecked(opcode); registerModRM(rm, reg); diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h index a48c753f1d..93d2672b0f 100644 --- a/js/src/vm/Interpreter-inl.h +++ b/js/src/vm/Interpreter-inl.h @@ -417,6 +417,40 @@ NegOperation(JSContext* cx, HandleScript script, jsbytecode* pc, MutableHandleVa } static MOZ_ALWAYS_INLINE bool +IncOperation(JSContext* cx, + MutableHandleValue val, + MutableHandleValue res) +{ + MOZ_ASSERT(val.isNumber(), "+1 only callable on result of JSOP_TONUMERIC"); + + int32_t i; + if (val.isInt32() && (i = val.toInt32()) != INT32_MAX) { + res.setInt32(i + 1); + return true; + } + + res.setNumber(val.toNumber() + 1); + return true; +} + +static MOZ_ALWAYS_INLINE bool +DecOperation(JSContext* cx, + MutableHandleValue val, + MutableHandleValue res) +{ + MOZ_ASSERT(val.isNumber(), "-1 only callable on result of JSOP_TONUMERIC"); + + int32_t i; + if (val.isInt32() && (i = val.toInt32()) != INT32_MIN) { + res.setInt32(i - 1); + return true; + } + + res.setNumber(val.toNumber() - 1); + return true; +} + +static MOZ_ALWAYS_INLINE bool ToIdOperation(JSContext* cx, HandleScript script, jsbytecode* pc, HandleValue idval, MutableHandleValue res) { diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index a03fa847f7..7b04f5fb72 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -4176,6 +4176,26 @@ CASE(JSOP_IS_CONSTRUCTING) PUSH_MAGIC(JS_IS_CONSTRUCTING); END_CASE(JSOP_IS_CONSTRUCTING) +CASE(JSOP_INC) +{ + ReservedRooted<Value> val(&rootValue0, REGS.sp[-1]); + MutableHandleValue res = REGS.stackHandleAt(-1); + if (!IncOperation(cx, &val, res)) { + goto error; + } +} +END_CASE(JSOP_INC) + +CASE(JSOP_DEC) +{ + ReservedRooted<Value> val(&rootValue0, REGS.sp[-1]); + MutableHandleValue res = REGS.stackHandleAt(-1); + if (!DecOperation(cx, &val, res)) { + goto error; + } +} +END_CASE(JSOP_DEC) + CASE(JSOP_BIGINT) { PUSH_COPY(script->getConst(GET_UINT32_INDEX(REGS.pc))); diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h index ff707aac08..c86a22baac 100644 --- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -2357,7 +2357,25 @@ * Operands: * Stack: arg => rval */ \ - macro(JSOP_DYNAMIC_IMPORT, 234, "call-import", NULL, 1, 1, 1, JOF_BYTE) \ + macro(JSOP_DYNAMIC_IMPORT, 234, "call-import", NULL, 1, 1, 1, JOF_BYTE) \ + /* + * Pops the numeric value 'val' from the stack, then pushes 'val + 1'. + * + * Category: Operators + * Type: Arithmetic Operators + * Operands: + * Stack: val => (val + 1) + */ \ + macro(JSOP_INC, 235, "inc", NULL, 1, 1, 1, JOF_BYTE) \ + /* + * Pops the numeric value 'val' from the stack, then pushes 'val - 1'. + * + * Category: Operators + * Type: Arithmetic Operators + * Operands: + * Stack: val => (val - 1) + */ \ + macro(JSOP_DEC, 236, "dec", NULL, 1, 1, 1, JOF_BYTE) \ /* * Pushes a BigInt constant onto the stack. * Category: Literals @@ -2365,14 +2383,12 @@ * Operands: uint32_t constIndex * Stack: => val */ \ - macro(JSOP_BIGINT, 235, "bigint", NULL, 5, 0, 1, JOF_BIGINT) + macro(JSOP_BIGINT, 237, "bigint", NULL, 5, 0, 1, JOF_BIGINT) /* * In certain circumstances it may be useful to "pad out" the opcode space to * a power of two. Use this macro to do so. */ #define FOR_EACH_TRAILING_UNUSED_OPCODE(macro) \ - macro(236) \ - macro(237) \ macro(238) \ macro(239) \ macro(240) \ |