зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1679750 - Part 4: Move BigInt with Int32 comparison to the MacroAssembler. r=jandem
Also rename `branchIfNegativeBigInt` to `branchIfBigIntIsNegative` to match the other branch methods from part 2 and part 8. Differential Revision: https://phabricator.services.mozilla.com/D98158
This commit is contained in:
Родитель
db6b1eddb2
Коммит
15634ee875
|
@ -146,7 +146,7 @@ def get_macroassembler_definitions(filename):
|
|||
style_section = False
|
||||
lines = ""
|
||||
signatures = []
|
||||
with open(filename) as f:
|
||||
with open(filename, encoding="utf-8") as f:
|
||||
for line in f:
|
||||
if "//{{{ check_macroassembler_style" in line:
|
||||
if style_section:
|
||||
|
@ -211,7 +211,7 @@ def get_macroassembler_declaration(filename):
|
|||
style_section = False
|
||||
lines = ""
|
||||
signatures = []
|
||||
with open(filename) as f:
|
||||
with open(filename, encoding="utf-8") as f:
|
||||
for line in f:
|
||||
if "//{{{ check_macroassembler_decl_style" in line:
|
||||
style_section = True
|
||||
|
|
|
@ -5880,102 +5880,9 @@ bool CacheIRCompiler::emitCompareBigIntInt32Result(JSOp op,
|
|||
AutoScratchRegisterMaybeOutput scratch1(allocator, masm, output);
|
||||
AutoScratchRegister scratch2(allocator, masm);
|
||||
|
||||
MOZ_ASSERT(IsLooseEqualityOp(op) || IsRelationalOp(op));
|
||||
|
||||
static_assert(std::is_same_v<BigInt::Digit, uintptr_t>,
|
||||
"BigInt digit can be loaded in a pointer-sized register");
|
||||
static_assert(sizeof(BigInt::Digit) >= sizeof(uint32_t),
|
||||
"BigInt digit stores at least an uint32");
|
||||
|
||||
// Test for too large numbers.
|
||||
//
|
||||
// If the absolute value of the BigInt can't be expressed in an uint32/uint64,
|
||||
// the result of the comparison is a constant.
|
||||
Label ifTrue, ifFalse;
|
||||
if (op == JSOp::Eq || op == JSOp::Ne) {
|
||||
Label* tooLarge = op == JSOp::Eq ? &ifFalse : &ifTrue;
|
||||
masm.branch32(Assembler::GreaterThan,
|
||||
Address(bigInt, BigInt::offsetOfDigitLength()), Imm32(1),
|
||||
tooLarge);
|
||||
} else {
|
||||
Label doCompare;
|
||||
masm.branch32(Assembler::LessThanOrEqual,
|
||||
Address(bigInt, BigInt::offsetOfDigitLength()), Imm32(1),
|
||||
&doCompare);
|
||||
|
||||
// Still need to take the sign-bit into account for relational operations.
|
||||
if (op == JSOp::Lt || op == JSOp::Le) {
|
||||
masm.branchIfNegativeBigInt(bigInt, &ifTrue);
|
||||
masm.jump(&ifFalse);
|
||||
} else {
|
||||
masm.branchIfNegativeBigInt(bigInt, &ifFalse);
|
||||
masm.jump(&ifTrue);
|
||||
}
|
||||
|
||||
masm.bind(&doCompare);
|
||||
}
|
||||
|
||||
// Test for mismatched signs and, if the signs are equal, load |abs(x)| in
|
||||
// |scratch1| and |abs(y)| in |scratch2| and then compare the absolute numbers
|
||||
// against each other.
|
||||
{
|
||||
// Jump to |ifTrue| resp. |ifFalse| if the BigInt is strictly less than
|
||||
// resp. strictly greater than the int32 value, depending on the comparison
|
||||
// operator.
|
||||
Label* greaterThan;
|
||||
Label* lessThan;
|
||||
if (op == JSOp::Eq) {
|
||||
greaterThan = &ifFalse;
|
||||
lessThan = &ifFalse;
|
||||
} else if (op == JSOp::Ne) {
|
||||
greaterThan = &ifTrue;
|
||||
lessThan = &ifTrue;
|
||||
} else if (op == JSOp::Lt || op == JSOp::Le) {
|
||||
greaterThan = &ifFalse;
|
||||
lessThan = &ifTrue;
|
||||
} else {
|
||||
MOZ_ASSERT(op == JSOp::Gt || op == JSOp::Ge);
|
||||
greaterThan = &ifTrue;
|
||||
lessThan = &ifFalse;
|
||||
}
|
||||
|
||||
// BigInt digits are always stored as an absolute number.
|
||||
masm.loadFirstBigIntDigitOrZero(bigInt, scratch1);
|
||||
|
||||
// Load the int32 into |scratch2| and negate it for negative numbers.
|
||||
masm.move32(int32, scratch2);
|
||||
|
||||
Label isNegative, doCompare;
|
||||
masm.branchIfNegativeBigInt(bigInt, &isNegative);
|
||||
masm.branch32(Assembler::LessThan, int32, Imm32(0), greaterThan);
|
||||
masm.jump(&doCompare);
|
||||
|
||||
// We rely on |neg32(INT32_MIN)| staying INT32_MIN, because we're using an
|
||||
// unsigned comparison below.
|
||||
masm.bind(&isNegative);
|
||||
masm.branch32(Assembler::GreaterThanOrEqual, int32, Imm32(0), lessThan);
|
||||
masm.neg32(scratch2);
|
||||
|
||||
// Not all supported platforms (e.g. MIPS64) zero-extend 32-bit operations,
|
||||
// so we need to explicitly clear any high 32-bits.
|
||||
masm.move32ZeroExtendToPtr(scratch2, scratch2);
|
||||
|
||||
// Reverse the relational comparator for negative numbers.
|
||||
// |-x < -y| <=> |+x > +y|.
|
||||
// |-x ≤ -y| <=> |+x ≥ +y|.
|
||||
// |-x > -y| <=> |+x < +y|.
|
||||
// |-x ≥ -y| <=> |+x ≤ +y|.
|
||||
JSOp reversed = ReverseCompareOp(op);
|
||||
if (reversed != op) {
|
||||
masm.branchPtr(JSOpToCondition(reversed, /* signed = */ false), scratch1,
|
||||
scratch2, &ifTrue);
|
||||
masm.jump(&ifFalse);
|
||||
}
|
||||
|
||||
masm.bind(&doCompare);
|
||||
masm.branchPtr(JSOpToCondition(op, /* signed = */ false), scratch1,
|
||||
scratch2, &ifTrue);
|
||||
}
|
||||
masm.compareBigIntAndInt32(op, bigInt, int32, scratch1, scratch2, &ifTrue,
|
||||
&ifFalse);
|
||||
|
||||
Label done;
|
||||
masm.bind(&ifFalse);
|
||||
|
|
|
@ -394,7 +394,7 @@ void MacroAssembler::branchTwoByteString(Register string, Label* label) {
|
|||
Imm32(JSString::LATIN1_CHARS_BIT), label);
|
||||
}
|
||||
|
||||
void MacroAssembler::branchIfNegativeBigInt(Register bigInt, Label* label) {
|
||||
void MacroAssembler::branchIfBigIntIsNegative(Register bigInt, Label* label) {
|
||||
branchTest32(Assembler::NonZero, Address(bigInt, BigInt::offsetOfFlags()),
|
||||
Imm32(BigInt::signBitMask()), label);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "jit/ABIFunctionList-inl.h"
|
||||
#include "jit/shared/Lowering-shared-inl.h"
|
||||
#include "jit/TemplateObject-inl.h"
|
||||
#include "vm/BytecodeUtil-inl.h"
|
||||
#include "vm/Interpreter-inl.h"
|
||||
#include "vm/JSObject-inl.h"
|
||||
|
||||
|
@ -1294,6 +1295,107 @@ void MacroAssembler::initializeBigInt64(Scalar::Type type, Register bigInt,
|
|||
bind(&done);
|
||||
}
|
||||
|
||||
void MacroAssembler::compareBigIntAndInt32(JSOp op, Register bigInt,
|
||||
Register int32, Register scratch1,
|
||||
Register scratch2, Label* ifTrue,
|
||||
Label* ifFalse) {
|
||||
MOZ_ASSERT(IsLooseEqualityOp(op) || IsRelationalOp(op));
|
||||
|
||||
static_assert(std::is_same_v<BigInt::Digit, uintptr_t>,
|
||||
"BigInt digit can be loaded in a pointer-sized register");
|
||||
static_assert(sizeof(BigInt::Digit) >= sizeof(uint32_t),
|
||||
"BigInt digit stores at least an uint32");
|
||||
|
||||
// Test for too large numbers.
|
||||
//
|
||||
// If the absolute value of the BigInt can't be expressed in an uint32/uint64,
|
||||
// the result of the comparison is a constant.
|
||||
if (op == JSOp::Eq || op == JSOp::Ne) {
|
||||
Label* tooLarge = op == JSOp::Eq ? ifFalse : ifTrue;
|
||||
branch32(Assembler::GreaterThan,
|
||||
Address(bigInt, BigInt::offsetOfDigitLength()), Imm32(1),
|
||||
tooLarge);
|
||||
} else {
|
||||
Label doCompare;
|
||||
branch32(Assembler::LessThanOrEqual,
|
||||
Address(bigInt, BigInt::offsetOfDigitLength()), Imm32(1),
|
||||
&doCompare);
|
||||
|
||||
// Still need to take the sign-bit into account for relational operations.
|
||||
if (op == JSOp::Lt || op == JSOp::Le) {
|
||||
branchIfBigIntIsNegative(bigInt, ifTrue);
|
||||
jump(ifFalse);
|
||||
} else {
|
||||
branchIfBigIntIsNegative(bigInt, ifFalse);
|
||||
jump(ifTrue);
|
||||
}
|
||||
|
||||
bind(&doCompare);
|
||||
}
|
||||
|
||||
// Test for mismatched signs and, if the signs are equal, load |abs(x)| in
|
||||
// |scratch1| and |abs(y)| in |scratch2| and then compare the absolute numbers
|
||||
// against each other.
|
||||
{
|
||||
// Jump to |ifTrue| resp. |ifFalse| if the BigInt is strictly less than
|
||||
// resp. strictly greater than the int32 value, depending on the comparison
|
||||
// operator.
|
||||
Label* greaterThan;
|
||||
Label* lessThan;
|
||||
if (op == JSOp::Eq) {
|
||||
greaterThan = ifFalse;
|
||||
lessThan = ifFalse;
|
||||
} else if (op == JSOp::Ne) {
|
||||
greaterThan = ifTrue;
|
||||
lessThan = ifTrue;
|
||||
} else if (op == JSOp::Lt || op == JSOp::Le) {
|
||||
greaterThan = ifFalse;
|
||||
lessThan = ifTrue;
|
||||
} else {
|
||||
MOZ_ASSERT(op == JSOp::Gt || op == JSOp::Ge);
|
||||
greaterThan = ifTrue;
|
||||
lessThan = ifFalse;
|
||||
}
|
||||
|
||||
// BigInt digits are always stored as an absolute number.
|
||||
loadFirstBigIntDigitOrZero(bigInt, scratch1);
|
||||
|
||||
// Load the int32 into |scratch2| and negate it for negative numbers.
|
||||
move32(int32, scratch2);
|
||||
|
||||
Label isNegative, doCompare;
|
||||
branchIfBigIntIsNegative(bigInt, &isNegative);
|
||||
branch32(Assembler::LessThan, int32, Imm32(0), greaterThan);
|
||||
jump(&doCompare);
|
||||
|
||||
// We rely on |neg32(INT32_MIN)| staying INT32_MIN, because we're using an
|
||||
// unsigned comparison below.
|
||||
bind(&isNegative);
|
||||
branch32(Assembler::GreaterThanOrEqual, int32, Imm32(0), lessThan);
|
||||
neg32(scratch2);
|
||||
|
||||
// Not all supported platforms (e.g. MIPS64) zero-extend 32-bit operations,
|
||||
// so we need to explicitly clear any high 32-bits.
|
||||
move32ZeroExtendToPtr(scratch2, scratch2);
|
||||
|
||||
// Reverse the relational comparator for negative numbers.
|
||||
// |-x < -y| <=> |+x > +y|.
|
||||
// |-x ≤ -y| <=> |+x ≥ +y|.
|
||||
// |-x > -y| <=> |+x < +y|.
|
||||
// |-x ≥ -y| <=> |+x ≤ +y|.
|
||||
JSOp reversed = ReverseCompareOp(op);
|
||||
if (reversed != op) {
|
||||
branchPtr(JSOpToCondition(reversed, /* isSigned = */ false), scratch1,
|
||||
scratch2, ifTrue);
|
||||
jump(ifFalse);
|
||||
}
|
||||
|
||||
bind(&doCompare);
|
||||
branchPtr(JSOpToCondition(op, /* isSigned = */ false), scratch1, scratch2,
|
||||
ifTrue);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::typeOfObject(Register obj, Register scratch, Label* slow,
|
||||
Label* isObject, Label* isCallable,
|
||||
Label* isUndefined) {
|
||||
|
|
|
@ -1467,7 +1467,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
|
|||
inline void branchLatin1String(Register string, Label* label);
|
||||
inline void branchTwoByteString(Register string, Label* label);
|
||||
|
||||
inline void branchIfNegativeBigInt(Register bigInt, Label* label);
|
||||
inline void branchIfBigIntIsNegative(Register bigInt, Label* label);
|
||||
inline void branchIfBigIntIsNonNegative(Register bigInt, Label* label);
|
||||
|
||||
inline void branchTestFunctionFlags(Register fun, uint32_t flags,
|
||||
|
@ -3700,6 +3700,13 @@ class MacroAssembler : public MacroAssemblerSpecific {
|
|||
*/
|
||||
void initializeBigInt64(Scalar::Type type, Register bigInt, Register64 val);
|
||||
|
||||
/**
|
||||
* Compare a BigInt and an Int32 value. Falls through to the false case.
|
||||
*/
|
||||
void compareBigIntAndInt32(JSOp op, Register bigInt, Register int32,
|
||||
Register scratch1, Register scratch2,
|
||||
Label* ifTrue, Label* ifFalse);
|
||||
|
||||
void loadJSContext(Register dest);
|
||||
|
||||
void switchToRealm(Register realm);
|
||||
|
|
Загрузка…
Ссылка в новой задаче