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:
André Bargull 2020-12-22 13:25:32 +00:00
Родитель 45143b9147
Коммит 89a89bb951
5 изменённых файлов: 115 добавлений и 99 удалений

Просмотреть файл

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