mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 09:18:42 +09:00
Issue #2308 & #1240 Follow-up - Add BigInt support to JSOP_INC and JSOP_DEC. https://bugzilla.mozilla.org/show_bug.cgi?id=1526309
This commit is contained in:
parent
5c8a6c5bb8
commit
e12e377e51
8 changed files with 283 additions and 127 deletions
|
|
@ -4858,7 +4858,7 @@ IonBuilder::jsop_bitop(JSOp op)
|
|||
}
|
||||
|
||||
MDefinition::Opcode
|
||||
JSOpToMDefinition(JSOp op)
|
||||
BinaryJSOpToMDefinition(JSOp op)
|
||||
{
|
||||
switch (op) {
|
||||
case JSOP_ADD:
|
||||
|
|
@ -4959,6 +4959,40 @@ IonBuilder::powTrySpecialized(bool* emitted, MDefinition* base, MDefinition* pow
|
|||
return true;
|
||||
}
|
||||
|
||||
MIRType
|
||||
IonBuilder::binaryArithNumberSpecialization(MDefinition* left, MDefinition* right)
|
||||
{
|
||||
// Try to specialize as int32.
|
||||
if (left->type() == MIRType::Int32 && right->type() == MIRType::Int32 &&
|
||||
!inspector->hasSeenDoubleResult(pc)) {
|
||||
return MIRType::Int32;
|
||||
}
|
||||
return MIRType::Double;
|
||||
}
|
||||
|
||||
MBinaryArithInstruction*
|
||||
IonBuilder::binaryArithEmitSpecialized(MDefinition::Opcode op, MIRType specialization,
|
||||
MDefinition* left, MDefinition* right)
|
||||
{
|
||||
MBinaryArithInstruction* ins = MBinaryArithInstruction::New(alloc(), op, left, right);
|
||||
ins->setSpecialization(specialization);
|
||||
|
||||
if (op == MDefinition::Op_Add || op == MDefinition::Op_Mul) {
|
||||
ins->setCommutative();
|
||||
}
|
||||
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
|
||||
MOZ_ASSERT(!ins->isEffectful());
|
||||
|
||||
if(!maybeInsertResume()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ins;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
SimpleArithOperand(MDefinition* op)
|
||||
{
|
||||
|
|
@ -4992,19 +5026,20 @@ IonBuilder::binaryArithTrySpecialized(bool* emitted, JSOp op, MDefinition* left,
|
|||
return true;
|
||||
}
|
||||
|
||||
MDefinition::Opcode defOp = JSOpToMDefinition(op);
|
||||
MBinaryArithInstruction* ins = MBinaryArithInstruction::New(alloc(), defOp, left, right);
|
||||
ins->setNumberSpecialization(alloc(), inspector, pc);
|
||||
MDefinition::Opcode defOp = BinaryJSOpToMDefinition(op);
|
||||
MIRType specialization = binaryArithNumberSpecialization(left, right);
|
||||
MBinaryArithInstruction* ins = binaryArithEmitSpecialized(defOp, specialization, left, right);
|
||||
|
||||
if (op == JSOP_ADD || op == JSOP_MUL)
|
||||
ins->setCommutative();
|
||||
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
|
||||
MOZ_ASSERT(!ins->isEffectful());
|
||||
if (!maybeInsertResume())
|
||||
if(!ins) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Relax int32 to double if, despite the fact that we have int32 operands and
|
||||
// we've never seen a double result, we know the result may overflow or be a
|
||||
// double.
|
||||
if (specialization == MIRType::Int32 && ins->constantDoubleResult(alloc())) {
|
||||
ins->setSpecialization(MIRType::Double);
|
||||
}
|
||||
|
||||
trackOptimizationSuccess();
|
||||
*emitted = true;
|
||||
|
|
@ -5028,16 +5063,10 @@ IonBuilder::binaryArithTrySpecializedOnBaselineInspector(bool* emitted, JSOp op,
|
|||
return true;
|
||||
}
|
||||
|
||||
MDefinition::Opcode def_op = JSOpToMDefinition(op);
|
||||
MBinaryArithInstruction* ins = MBinaryArithInstruction::New(alloc(), def_op, left, right);
|
||||
ins->setSpecialization(specialization);
|
||||
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
|
||||
MOZ_ASSERT(!ins->isEffectful());
|
||||
if (!maybeInsertResume())
|
||||
MDefinition::Opcode defOp = BinaryJSOpToMDefinition(op);
|
||||
if(!binaryArithEmitSpecialized(defOp, specialization, left, right)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
trackOptimizationSuccess();
|
||||
*emitted = true;
|
||||
|
|
@ -5076,14 +5105,6 @@ 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:
|
||||
|
|
@ -5138,8 +5159,8 @@ IonBuilder::jsop_binary_arith(JSOp op, MDefinition* left, MDefinition* right)
|
|||
trackOptimizationAttempt(TrackedStrategy::BinaryArith_Call);
|
||||
trackOptimizationSuccess();
|
||||
|
||||
MDefinition::Opcode def_op = JSOpToMDefinition(op);
|
||||
MBinaryArithInstruction* ins = MBinaryArithInstruction::New(alloc(), def_op, left, right);
|
||||
MDefinition::Opcode defOp = BinaryJSOpToMDefinition(op);
|
||||
MBinaryArithInstruction* ins = MBinaryArithInstruction::New(alloc(), defOp, left, right);
|
||||
|
||||
// Decrease type from 'any type' to 'empty type' when one of the operands
|
||||
// is 'empty typed'.
|
||||
|
|
@ -5216,27 +5237,117 @@ IonBuilder::jsop_neg()
|
|||
return jsop_binary_arith(JSOP_MUL, negator, right);
|
||||
}
|
||||
|
||||
MDefinition*
|
||||
IonBuilder::unaryArithConvertToBinary(JSOp op, MDefinition::Opcode* defOp)
|
||||
{
|
||||
switch (op) {
|
||||
case JSOP_INC: {
|
||||
*defOp = MDefinition::Op_Add;
|
||||
MConstant* right = MConstant::New(alloc(), Int32Value(1));
|
||||
current->add(right);
|
||||
return right;
|
||||
}
|
||||
case JSOP_DEC: {
|
||||
*defOp = MDefinition::Op_Sub;
|
||||
MConstant* right = MConstant::New(alloc(), Int32Value(1));
|
||||
current->add(right);
|
||||
return right;
|
||||
}
|
||||
default:
|
||||
MOZ_CRASH("unexpected unary opcode");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::unaryArithTrySpecialized(bool* emitted, JSOp op, MDefinition* value)
|
||||
{
|
||||
MOZ_ASSERT(*emitted == false);
|
||||
|
||||
// Try to convert Inc(x) or Dec(x) to Add(x,1) or Sub(x,1) if the operand is a
|
||||
// number.
|
||||
|
||||
trackOptimizationAttempt(TrackedStrategy::UnaryArith_SpecializedTypes);
|
||||
|
||||
if (!IsNumberType(value->type())) {
|
||||
trackOptimizationOutcome(TrackedOutcome::OperandNotNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
MDefinition::Opcode defOp;
|
||||
MDefinition* rhs = unaryArithConvertToBinary(op, &defOp);
|
||||
MIRType specialization = binaryArithNumberSpecialization(value, rhs);
|
||||
if (!binaryArithEmitSpecialized(defOp, specialization, value, rhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
trackOptimizationSuccess();
|
||||
*emitted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::unaryArithTrySpecializedOnBaselineInspector(bool* emitted, JSOp op, MDefinition* value)
|
||||
{
|
||||
MOZ_ASSERT(*emitted == false);
|
||||
|
||||
// Try to emit a specialized binary instruction speculating the
|
||||
// type using the baseline caches.
|
||||
|
||||
trackOptimizationAttempt(TrackedStrategy::UnaryArith_SpecializedOnBaselineTypes);
|
||||
|
||||
MIRType specialization = inspector->expectedBinaryArithSpecialization(pc);
|
||||
if (specialization == MIRType::None) {
|
||||
trackOptimizationOutcome(TrackedOutcome::SpeculationOnInputTypesFailed);
|
||||
return true;
|
||||
}
|
||||
|
||||
MDefinition::Opcode defOp;
|
||||
MDefinition* rhs = unaryArithConvertToBinary(op, &defOp);
|
||||
if (!binaryArithEmitSpecialized(defOp, specialization, value, rhs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
trackOptimizationSuccess();
|
||||
*emitted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
bool emitted = false;
|
||||
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");
|
||||
startTrackingOptimizations();
|
||||
|
||||
trackTypeInfo(TrackedTypeSite::Operand, value->type(), value->resultTypeSet());
|
||||
|
||||
if (!unaryArithTrySpecialized(&emitted, op, value)) {
|
||||
return false;
|
||||
}
|
||||
if (emitted) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return jsop_binary_arith(op, value, one);
|
||||
if (!unaryArithTrySpecializedOnBaselineInspector(&emitted, op, value)) {
|
||||
return false;
|
||||
}
|
||||
if (emitted) {
|
||||
return true;
|
||||
}
|
||||
|
||||
trackOptimizationAttempt(TrackedStrategy::UnaryArith_InlineCache);
|
||||
trackOptimizationSuccess();
|
||||
|
||||
MInstruction* stub = MUnarySharedStub::New(alloc(), value);
|
||||
current->add(stub);
|
||||
current->push(stub);
|
||||
|
||||
// Decrease type from 'any type' to 'empty type' when one of the operands
|
||||
// is 'empty typed'.
|
||||
maybeMarkEmpty(stub);
|
||||
|
||||
return resumeAfter(stub);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -497,8 +497,13 @@ class IonBuilder
|
|||
|
||||
// jsop_binary_arith helpers.
|
||||
MBinaryArithInstruction* binaryArithInstruction(JSOp op, MDefinition* left, MDefinition* right);
|
||||
MIRType binaryArithNumberSpecialization(MDefinition* left, MDefinition* right);
|
||||
MOZ_MUST_USE bool binaryArithTryConcat(bool* emitted, JSOp op, MDefinition* left,
|
||||
MDefinition* right);
|
||||
MOZ_MUST_USE MBinaryArithInstruction* binaryArithEmitSpecialized(MDefinition::Opcode op,
|
||||
MIRType specialization,
|
||||
MDefinition* left,
|
||||
MDefinition* right);
|
||||
MOZ_MUST_USE bool binaryArithTrySpecialized(bool* emitted, JSOp op, MDefinition* left,
|
||||
MDefinition* right);
|
||||
MOZ_MUST_USE bool binaryArithTrySpecializedOnBaselineInspector(bool* emitted, JSOp op,
|
||||
|
|
@ -510,6 +515,12 @@ class IonBuilder
|
|||
// jsop_bitnot helpers.
|
||||
MOZ_MUST_USE bool bitnotTrySpecialized(bool* emitted, MDefinition* input);
|
||||
|
||||
// jsop_inc_or_dec helpers.
|
||||
MDefinition* unaryArithConvertToBinary(JSOp op, MDefinition::Opcode* defOp);
|
||||
MOZ_MUST_USE bool unaryArithTrySpecialized(bool* emitted, JSOp op, MDefinition* value);
|
||||
MOZ_MUST_USE bool unaryArithTrySpecializedOnBaselineInspector(bool* emitted, JSOp op,
|
||||
MDefinition* value);
|
||||
|
||||
// jsop_pow helpers.
|
||||
MOZ_MUST_USE bool powTrySpecialized(bool* emitted, MDefinition* base, MDefinition* power,
|
||||
MIRType outputType);
|
||||
|
|
|
|||
|
|
@ -3110,23 +3110,6 @@ MBinaryArithInstruction::New(TempAllocator& alloc, Opcode op,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
MBinaryArithInstruction::setNumberSpecialization(TempAllocator& alloc, BaselineInspector* inspector,
|
||||
jsbytecode* pc)
|
||||
{
|
||||
setSpecialization(MIRType::Double);
|
||||
|
||||
// Try to specialize as int32.
|
||||
if (getOperand(0)->type() == MIRType::Int32 && getOperand(1)->type() == MIRType::Int32) {
|
||||
bool seenDouble = inspector->hasSeenDoubleResult(pc);
|
||||
|
||||
// Use int32 specialization if the operation doesn't overflow on its
|
||||
// constant operands and if the operation has never overflowed.
|
||||
if (!seenDouble && !constantDoubleResult(alloc))
|
||||
setInt32Specialization();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
MBinaryArithInstruction::constantDoubleResult(TempAllocator& alloc)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6219,7 +6219,6 @@ class MBinaryArithInstruction
|
|||
specialization_ = MIRType::Int32;
|
||||
setResultType(MIRType::Int32);
|
||||
}
|
||||
void setNumberSpecialization(TempAllocator& alloc, BaselineInspector* inspector, jsbytecode* pc);
|
||||
|
||||
virtual void trySpecializeFloat32(TempAllocator& alloc) override;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue