Issue #2308 & #1240 Follow-up - Introduce new increment and decrement operations. https://bugzilla.mozilla.org/show_bug.cgi?id=1508521

This commit is contained in:
Brian Smith 2023-09-16 05:38:42 -05:00 committed by roytam1
commit 5c8a6c5bb8
13 changed files with 157 additions and 30 deletions

View file

@ -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()) {

View file

@ -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()) {

View file

@ -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()) {

View file

@ -1939,6 +1939,18 @@ BaselineCompiler::emit_JSOP_NEG()
return emitUnaryArith();
}
bool
BaselineCompiler::emit_JSOP_INC()
{
return emitUnaryArith();
}
bool
BaselineCompiler::emit_JSOP_DEC()
{
return emitUnaryArith();
}
bool
BaselineCompiler::emit_JSOP_LT()
{

View file

@ -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.

View file

@ -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:
@ -5202,6 +5216,29 @@ IonBuilder::jsop_neg()
return jsop_binary_arith(JSOP_MUL, negator, right);
}
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()
{

View file

@ -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);

View file

@ -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");
}

View file

@ -1855,6 +1855,8 @@ class ICBinaryArith_DoubleWithInt32 : public ICStub
// UnaryArith
// JSOP_BITNOT
// JSOP_NEG
// JSOP_INC
// JSOP_DEC
class ICUnaryArith_Fallback : public ICFallbackStub
{

View file

@ -4958,7 +4958,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);
@ -4967,7 +4967,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);
@ -4977,7 +4977,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);
@ -4991,7 +4991,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);

View file

@ -416,6 +416,40 @@ NegOperation(JSContext* cx, HandleScript script, jsbytecode* pc, MutableHandleVa
return true;
}
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)

View file

@ -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)));

View file

@ -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) \