зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1608771 - Part 1, BigInt<>I64 conversion for inlined calls r=wingo,lth
This is part 1 of implementing the Wasm BigInt<>I64 conversion proposal for inlined Ion to Wasm calls. This part implements Ion MIR and LIR instructions that are needed for conversion between BigInts and I64. Differential Revision: https://phabricator.services.mozilla.com/D65233
This commit is contained in:
Родитель
ebf7dd1da8
Коммит
fb18e7c404
|
@ -4626,6 +4626,126 @@ void CodeGenerator::visitToNumeric(LToNumeric* lir) {
|
|||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitBooleanToInt64(LBooleanToInt64* lir) {
|
||||
Register input = ToRegister(lir->input());
|
||||
Register64 output = ToOutRegister64(lir);
|
||||
|
||||
masm.move32To64ZeroExtend(input, output);
|
||||
}
|
||||
|
||||
void CodeGenerator::emitStringToInt64(LInstruction* lir, Register input,
|
||||
Register temp, Register64 output) {
|
||||
masm.reserveStack(sizeof(uint64_t));
|
||||
masm.moveStackPtrTo(temp);
|
||||
pushArg(temp);
|
||||
pushArg(input);
|
||||
|
||||
using Fn = bool (*)(JSContext*, HandleString, uint64_t*, bool*);
|
||||
callVM<Fn, DoStringToInt64>(lir);
|
||||
|
||||
masm.load64(Address(masm.getStackPointer(), 0), output);
|
||||
masm.freeStack(sizeof(uint64_t));
|
||||
bailoutIfFalseBool(ReturnReg, lir->snapshot());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitStringToInt64(LStringToInt64* lir) {
|
||||
Register input = ToRegister(lir->input());
|
||||
Register temp = ToTempRegisterOrInvalid(lir->temp());
|
||||
Register64 output = ToOutRegister64(lir);
|
||||
MOZ_ASSERT(lir->mir()->input()->type() == MIRType::String);
|
||||
|
||||
emitStringToInt64(lir, input, temp, output);
|
||||
}
|
||||
|
||||
void CodeGenerator::visitValueToInt64(LValueToInt64* lir) {
|
||||
ValueOperand input = ToValue(lir, LValueToInt64::Input);
|
||||
Register64 output = ToOutRegister64(lir);
|
||||
Register scratch = ToTempRegisterOrInvalid(lir->temp());
|
||||
Register tag = masm.extractTag(input, scratch);
|
||||
Label fail, done;
|
||||
|
||||
bool maybeBigInt = lir->mir()->input()->mightBeType(MIRType::BigInt);
|
||||
bool maybeBool = lir->mir()->input()->mightBeType(MIRType::Boolean);
|
||||
bool maybeString = lir->mir()->input()->mightBeType(MIRType::String);
|
||||
int checks = int(maybeBigInt) + int(maybeBool) + int(maybeString);
|
||||
|
||||
if (checks == 0) {
|
||||
// Bail on other types.
|
||||
masm.jump(&fail);
|
||||
} else {
|
||||
// BigInt.
|
||||
if (maybeBigInt) {
|
||||
Label notBigInt;
|
||||
masm.branchTestBigInt(Assembler::NotEqual, tag, ¬BigInt);
|
||||
masm.unboxBigInt(input, scratch);
|
||||
Register bigint = input.scratchReg();
|
||||
masm.movePtr(scratch, bigint);
|
||||
masm.loadBigInt64(bigint, output);
|
||||
masm.jump(&done);
|
||||
masm.bind(¬BigInt);
|
||||
}
|
||||
|
||||
// Boolean
|
||||
if (maybeBool) {
|
||||
Label notBoolean;
|
||||
masm.branchTestBoolean(Assembler::NotEqual, tag, ¬Boolean);
|
||||
Register unboxed = ToTempUnboxRegister(lir->tempToUnbox());
|
||||
unboxed = masm.extractBoolean(input, unboxed);
|
||||
masm.move32To64ZeroExtend(unboxed, output);
|
||||
masm.jump(&done);
|
||||
masm.bind(¬Boolean);
|
||||
}
|
||||
|
||||
// String
|
||||
if (maybeString) {
|
||||
masm.branchTestString(Assembler::NotEqual, tag, &fail);
|
||||
#ifdef JS_NUNBOX32
|
||||
Register unboxed = input.payloadReg();
|
||||
#else
|
||||
Register unboxed = ToTempUnboxRegister(lir->tempToUnbox());
|
||||
#endif
|
||||
masm.unboxString(input, unboxed);
|
||||
emitStringToInt64(lir, unboxed, scratch, output);
|
||||
masm.jump(&done);
|
||||
}
|
||||
}
|
||||
|
||||
bailoutFrom(&fail, lir->snapshot());
|
||||
masm.bind(&done);
|
||||
}
|
||||
|
||||
void CodeGenerator::visitTruncateBigIntToInt64(LTruncateBigIntToInt64* lir) {
|
||||
Register operand = ToRegister(lir->input());
|
||||
Register64 output = ToOutRegister64(lir);
|
||||
MOZ_ASSERT(lir->mir()->input()->type() == MIRType::BigInt);
|
||||
|
||||
masm.loadBigInt64(operand, output);
|
||||
}
|
||||
|
||||
void CodeGenerator::visitInt64ToBigInt(LInt64ToBigInt* lir) {
|
||||
MOZ_ASSERT(lir->mir()->input()->type() == MIRType::Int64);
|
||||
|
||||
Register64 input = ToRegister64(lir->getInt64Operand(LInt64ToBigInt::Input));
|
||||
Register temp = ToTempRegisterOrInvalid(lir->temp1());
|
||||
Register bigint = ToTempRegisterOrInvalid(lir->temp2());
|
||||
Register output = ToRegister(lir->getDef(0));
|
||||
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
using Fn = BigInt* (*)(JSContext*, uint32_t, uint32_t);
|
||||
OutOfLineCode* ool = oolCallVM<Fn, jit::CreateBigIntFromInt64>(
|
||||
lir, ArgList(input.low, input.high), StoreRegisterTo(output));
|
||||
#else
|
||||
using Fn = BigInt* (*)(JSContext*, uint64_t);
|
||||
OutOfLineCode* ool = oolCallVM<Fn, jit::CreateBigIntFromInt64>(
|
||||
lir, ArgList(input), StoreRegisterTo(output));
|
||||
#endif
|
||||
|
||||
masm.newGCBigInt(bigint, temp, ool->entry(), true);
|
||||
masm.initializeBigInt64(Scalar::BigInt64, bigint, input);
|
||||
masm.movePtr(bigint, output);
|
||||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitTypeBarrierV(LTypeBarrierV* lir) {
|
||||
ValueOperand operand = ToValue(lir, LTypeBarrierV::Input);
|
||||
Register unboxScratch = ToTempRegisterOrInvalid(lir->unboxTemp());
|
||||
|
|
|
@ -265,6 +265,9 @@ class CodeGenerator final : public CodeGeneratorSpecific {
|
|||
template <class OrderedHashTable>
|
||||
void emitLoadIteratorValues(Register result, Register temp, Register front);
|
||||
|
||||
void emitStringToInt64(LInstruction* lir, Register input, Register temp,
|
||||
Register64 output);
|
||||
|
||||
template <size_t NumDefs>
|
||||
void emitIonToWasmCallBase(LIonToWasmCallBase<NumDefs>* lir);
|
||||
|
||||
|
|
|
@ -2200,6 +2200,66 @@ void LIRGenerator::visitTruncateToInt32(MTruncateToInt32* truncate) {
|
|||
}
|
||||
}
|
||||
|
||||
void LIRGenerator::visitToInt64(MToInt64* ins) {
|
||||
MDefinition* opd = ins->input();
|
||||
|
||||
switch (opd->type()) {
|
||||
case MIRType::Value: {
|
||||
LValueToInt64* lir =
|
||||
new (alloc()) LValueToInt64(useBox(opd), temp(), tempToUnbox());
|
||||
assignSnapshot(lir, Bailout_NonPrimitiveInput);
|
||||
defineInt64(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
break;
|
||||
}
|
||||
|
||||
case MIRType::Boolean: {
|
||||
LBooleanToInt64* lir =
|
||||
new (alloc()) LBooleanToInt64(useRegisterAtStart(opd));
|
||||
defineInt64(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
break;
|
||||
}
|
||||
|
||||
case MIRType::String: {
|
||||
LStringToInt64* lir =
|
||||
new (alloc()) LStringToInt64(useRegister(opd), temp());
|
||||
// May bail out on parse failure.
|
||||
assignSnapshot(lir, Bailout_NonPrimitiveInput);
|
||||
defineInt64(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
break;
|
||||
}
|
||||
|
||||
// An Int64 may be passed here from a BigInt to Int64 conversion.
|
||||
case MIRType::Int64: {
|
||||
redefine(ins, opd);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Undefined, Null, Number, and Symbol throw.
|
||||
// Objects may be effectful.
|
||||
// BigInt operands are eliminated by the type policy.
|
||||
MOZ_CRASH("unexpected type");
|
||||
}
|
||||
}
|
||||
|
||||
void LIRGenerator::visitTruncateBigIntToInt64(MTruncateBigIntToInt64* ins) {
|
||||
MOZ_ASSERT(ins->input()->type() == MIRType::BigInt);
|
||||
LTruncateBigIntToInt64* lir =
|
||||
new (alloc()) LTruncateBigIntToInt64(useRegister(ins->input()));
|
||||
defineInt64(lir, ins);
|
||||
}
|
||||
|
||||
void LIRGenerator::visitInt64ToBigInt(MInt64ToBigInt* ins) {
|
||||
MOZ_ASSERT(ins->input()->type() == MIRType::Int64);
|
||||
LInt64ToBigInt* lir =
|
||||
new (alloc()) LInt64ToBigInt(useInt64(ins->input()), temp(), temp());
|
||||
define(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void LIRGenerator::visitWasmTruncateToInt32(MWasmTruncateToInt32* ins) {
|
||||
MDefinition* input = ins->input();
|
||||
switch (input->type()) {
|
||||
|
|
|
@ -3725,6 +3725,52 @@ MDefinition* MToNumeric::foldsTo(TempAllocator& alloc) {
|
|||
return this;
|
||||
}
|
||||
|
||||
MDefinition* MTruncateBigIntToInt64::foldsTo(TempAllocator& alloc) {
|
||||
MDefinition* input = getOperand(0);
|
||||
|
||||
if (input->isBox()) {
|
||||
input = input->getOperand(0);
|
||||
}
|
||||
|
||||
// If the operand converts an I64 to BigInt, drop both conversions.
|
||||
if (input->isInt64ToBigInt()) {
|
||||
return input->getOperand(0);
|
||||
}
|
||||
|
||||
// Fold this operation if the input operand is constant.
|
||||
if (input->isConstant()) {
|
||||
return MConstant::NewInt64(
|
||||
alloc, BigInt::toInt64(input->toConstant()->toBigInt()));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
MDefinition* MToInt64::foldsTo(TempAllocator& alloc) {
|
||||
MDefinition* input = getOperand(0);
|
||||
|
||||
if (input->isBox()) {
|
||||
input = input->getOperand(0);
|
||||
}
|
||||
|
||||
// When the input is an Int64 already, just return it.
|
||||
if (input->type() == MIRType::Int64) {
|
||||
return input;
|
||||
}
|
||||
|
||||
// Fold this operation if the input operand is constant.
|
||||
if (input->isConstant()) {
|
||||
switch (input->type()) {
|
||||
case MIRType::Boolean:
|
||||
return MConstant::NewInt64(alloc, input->toConstant()->toBoolean());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
MDefinition* MToNumberInt32::foldsTo(TempAllocator& alloc) {
|
||||
MDefinition* input = getOperand(0);
|
||||
|
||||
|
|
|
@ -4224,6 +4224,74 @@ class MTruncateToInt32 : public MUnaryInstruction, public ToInt32Policy::Data {
|
|||
ALLOW_CLONE(MTruncateToInt32)
|
||||
};
|
||||
|
||||
// Takes a Value or typed input and returns a suitable Int64 using the
|
||||
// ToBigInt algorithm, possibly calling out to the VM for string, etc inputs.
|
||||
class MToInt64 : public MUnaryInstruction, public ToInt64Policy::Data {
|
||||
explicit MToInt64(MDefinition* arg) : MUnaryInstruction(classOpcode, arg) {
|
||||
setResultType(MIRType::Int64);
|
||||
setGuard(); // May bail on non-Bool, non-BigInt, or invalid Strings.
|
||||
setMovable();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(ToInt64)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
void computeRange(TempAllocator& alloc) override;
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override { return AliasSet::None(); }
|
||||
|
||||
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||
|
||||
ALLOW_CLONE(MToInt64)
|
||||
};
|
||||
|
||||
// Takes a BigInt pointer and returns its toInt64 value.
|
||||
class MTruncateBigIntToInt64 : public MUnaryInstruction,
|
||||
public NoTypePolicy::Data {
|
||||
explicit MTruncateBigIntToInt64(MDefinition* arg)
|
||||
: MUnaryInstruction(classOpcode, arg) {
|
||||
MOZ_ASSERT(arg->type() == MIRType::BigInt);
|
||||
setResultType(MIRType::Int64);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(TruncateBigIntToInt64)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||
|
||||
ALLOW_CLONE(MTruncateBigIntToInt64)
|
||||
};
|
||||
|
||||
// Takes an Int64 and returns a fresh BigInt pointer.
|
||||
class MInt64ToBigInt : public MUnaryInstruction, public NoTypePolicy::Data {
|
||||
explicit MInt64ToBigInt(MDefinition* arg)
|
||||
: MUnaryInstruction(classOpcode, arg) {
|
||||
MOZ_ASSERT(arg->type() == MIRType::Int64);
|
||||
setResultType(MIRType::BigInt);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(Int64ToBigInt)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override { return AliasSet::None(); }
|
||||
|
||||
ALLOW_CLONE(MInt64ToBigInt)
|
||||
};
|
||||
|
||||
// Converts any type to a string
|
||||
class MToString : public MUnaryInstruction, public ToStringPolicy::Data {
|
||||
public:
|
||||
|
|
|
@ -2631,6 +2631,16 @@ void MacroAssembler::Push(JSValueType type, Register reg) {
|
|||
framePushed_ += sizeof(Value);
|
||||
}
|
||||
|
||||
void MacroAssembler::Push(const Register64 reg) {
|
||||
#if JS_BITS_PER_WORD == 64
|
||||
Push(reg.reg);
|
||||
#else
|
||||
MOZ_ASSERT(MOZ_LITTLE_ENDIAN(), "Big-endian not supported.");
|
||||
Push(reg.high);
|
||||
Push(reg.low);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MacroAssembler::PushValue(const Address& addr) {
|
||||
MOZ_ASSERT(addr.base != getStackPointer());
|
||||
pushValue(addr);
|
||||
|
|
|
@ -387,6 +387,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
|
|||
void Push(const ValueOperand& val);
|
||||
void Push(const Value& val);
|
||||
void Push(JSValueType type, Register reg);
|
||||
void Push(const Register64 reg);
|
||||
void PushValue(const Address& addr);
|
||||
void PushEmptyRooted(VMFunctionData::RootType rootType);
|
||||
inline CodeOffset PushWithPatch(ImmWord word);
|
||||
|
|
|
@ -1707,6 +1707,10 @@ void MTruncateToInt32::computeRange(TempAllocator& alloc) {
|
|||
setRange(output);
|
||||
}
|
||||
|
||||
void MToInt64::computeRange(TempAllocator& alloc) {
|
||||
setRange(new (alloc) Range(getOperand(0)));
|
||||
}
|
||||
|
||||
void MToNumeric::computeRange(TempAllocator& alloc) {
|
||||
setRange(new (alloc) Range(getOperand(0)));
|
||||
}
|
||||
|
|
|
@ -830,6 +830,35 @@ bool ToStringPolicy::staticAdjustInputs(TempAllocator& alloc,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ToInt64Policy::staticAdjustInputs(TempAllocator& alloc,
|
||||
MInstruction* ins) {
|
||||
MOZ_ASSERT(ins->isToInt64());
|
||||
|
||||
MDefinition* input = ins->getOperand(0);
|
||||
MIRType type = input->type();
|
||||
|
||||
switch (type) {
|
||||
case MIRType::BigInt: {
|
||||
auto* replace = MTruncateBigIntToInt64::New(alloc, input);
|
||||
ins->block()->insertBefore(ins, replace);
|
||||
ins->replaceOperand(0, replace);
|
||||
break;
|
||||
}
|
||||
// No need for boxing for these types, because they are handled specially
|
||||
// when this instruction is lowered to LIR.
|
||||
case MIRType::Boolean:
|
||||
case MIRType::String:
|
||||
case MIRType::Int64:
|
||||
case MIRType::Value:
|
||||
break;
|
||||
default:
|
||||
ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <unsigned Op>
|
||||
bool ObjectPolicy<Op>::staticAdjustInputs(TempAllocator& alloc,
|
||||
MInstruction* ins) {
|
||||
|
@ -1152,6 +1181,7 @@ bool TypedArrayIndexPolicy::adjustInputs(TempAllocator& alloc,
|
|||
_(ToDoublePolicy) \
|
||||
_(ToInt32Policy) \
|
||||
_(ToStringPolicy) \
|
||||
_(ToInt64Policy) \
|
||||
_(TypeBarrierPolicy) \
|
||||
_(TypedArrayIndexPolicy)
|
||||
|
||||
|
|
|
@ -336,6 +336,19 @@ class ToStringPolicy final : public TypePolicy {
|
|||
}
|
||||
};
|
||||
|
||||
// Box non-Boolean, non-String, non-BigInt as input to a ToInt64 instruction.
|
||||
class ToInt64Policy final : public TypePolicy {
|
||||
public:
|
||||
constexpr ToInt64Policy() = default;
|
||||
EMPTY_DATA_;
|
||||
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc,
|
||||
MInstruction* ins);
|
||||
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc,
|
||||
MInstruction* ins) const override {
|
||||
return staticAdjustInputs(alloc, ins);
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned Op>
|
||||
class ObjectPolicy final : public TypePolicy {
|
||||
public:
|
||||
|
|
|
@ -89,6 +89,7 @@ namespace jit {
|
|||
_(CopyElementsForWrite, js::NativeObject::CopyElementsForWrite) \
|
||||
_(CopyLexicalEnvironmentObject, js::jit::CopyLexicalEnvironmentObject) \
|
||||
_(CreateAsyncFromSyncIterator, js::CreateAsyncFromSyncIterator) \
|
||||
_(CreateBigIntFromInt64, js::jit::CreateBigIntFromInt64) \
|
||||
_(CreateGenerator, js::jit::CreateGenerator) \
|
||||
_(CreateThisForFunctionWithProto, js::CreateThisForFunctionWithProto) \
|
||||
_(CreateThisFromIC, js::jit::CreateThisFromIC) \
|
||||
|
@ -115,6 +116,7 @@ namespace jit {
|
|||
_(DoCallFallback, js::jit::DoCallFallback) \
|
||||
_(DoConcatStringObject, js::jit::DoConcatStringObject) \
|
||||
_(DoSpreadCallFallback, js::jit::DoSpreadCallFallback) \
|
||||
_(DoStringToInt64, js::jit::DoStringToInt64) \
|
||||
_(DoToNumeric, js::jit::DoToNumeric) \
|
||||
_(DoTypeUpdateFallback, js::jit::DoTypeUpdateFallback) \
|
||||
_(EnterWith, js::jit::EnterWith) \
|
||||
|
|
|
@ -2004,6 +2004,32 @@ void* AllocateBigIntNoGC(JSContext* cx, bool requestMinorGC) {
|
|||
return js::AllocateBigInt<NoGC>(cx, gc::TenuredHeap);
|
||||
}
|
||||
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
BigInt* CreateBigIntFromInt64(JSContext* cx, uint32_t low, uint32_t high) {
|
||||
int64_t n = ((uint64_t)high << 32) + low;
|
||||
return js::BigInt::createFromInt64(cx, n);
|
||||
}
|
||||
#else
|
||||
BigInt* CreateBigIntFromInt64(JSContext* cx, uint64_t i64) {
|
||||
return js::BigInt::createFromInt64(cx, i64);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool DoStringToInt64(JSContext* cx, HandleString str, uint64_t* res,
|
||||
bool* parseSuccess) {
|
||||
BigInt* bi;
|
||||
*parseSuccess = true;
|
||||
JS_TRY_VAR_OR_RETURN_FALSE(cx, bi, js::StringToBigInt(cx, str));
|
||||
|
||||
if (!bi) {
|
||||
*parseSuccess = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
*res = js::BigInt::toUint64(bi);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <EqualityKind Kind>
|
||||
bool BigIntEqual(BigInt* x, BigInt* y) {
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
|
|
|
@ -715,6 +715,10 @@ struct OutParamToDataType<uint32_t*> {
|
|||
static const DataType result = Type_Int32;
|
||||
};
|
||||
template <>
|
||||
struct OutParamToDataType<uint64_t*> {
|
||||
static const DataType result = Type_Pointer;
|
||||
};
|
||||
template <>
|
||||
struct OutParamToDataType<uint8_t**> {
|
||||
static const DataType result = Type_Pointer;
|
||||
};
|
||||
|
@ -1128,6 +1132,13 @@ bool IsPossiblyWrappedTypedArray(JSContext* cx, JSObject* obj, bool* result);
|
|||
bool DoToNumeric(JSContext* cx, HandleValue arg, MutableHandleValue ret);
|
||||
|
||||
void* AllocateBigIntNoGC(JSContext* cx, bool requestMinorGC);
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
BigInt* CreateBigIntFromInt64(JSContext* cx, uint32_t low, uint32_t high);
|
||||
#else
|
||||
BigInt* CreateBigIntFromInt64(JSContext* cx, uint64_t i64);
|
||||
#endif
|
||||
bool DoStringToInt64(JSContext* cx, HandleString str, uint64_t* res,
|
||||
bool* parseSuccess);
|
||||
|
||||
template <EqualityKind Kind>
|
||||
bool BigIntEqual(BigInt* x, BigInt* y);
|
||||
|
|
|
@ -5493,6 +5493,96 @@ class LToNumeric : public LInstructionHelper<BOX_PIECES, BOX_PIECES, 0> {
|
|||
static const size_t Input = 0;
|
||||
|
||||
const MToNumeric* mir() const { return mir_->toToNumeric(); }
|
||||
const LDefinition* temp() { return getTemp(0); }
|
||||
};
|
||||
|
||||
// Convert a Boolean to an Int64, following ToBigInt.
|
||||
class LBooleanToInt64 : public LInstructionHelper<INT64_PIECES, 1, 0> {
|
||||
public:
|
||||
LIR_HEADER(BooleanToInt64)
|
||||
|
||||
explicit LBooleanToInt64(const LAllocation& input)
|
||||
: LInstructionHelper(classOpcode) {
|
||||
setOperand(Input, input);
|
||||
}
|
||||
|
||||
static const size_t Input = 0;
|
||||
|
||||
const MToInt64* mir() const { return mir_->toToInt64(); }
|
||||
};
|
||||
|
||||
// Convert a String to an Int64, following ToBigInt.
|
||||
class LStringToInt64 : public LInstructionHelper<INT64_PIECES, 1, 1> {
|
||||
public:
|
||||
LIR_HEADER(StringToInt64)
|
||||
|
||||
explicit LStringToInt64(const LAllocation& input, const LDefinition& temp)
|
||||
: LInstructionHelper(classOpcode) {
|
||||
setOperand(Input, input);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
static const size_t Input = 0;
|
||||
|
||||
const MToInt64* mir() const { return mir_->toToInt64(); }
|
||||
const LDefinition* temp() { return getTemp(0); }
|
||||
};
|
||||
|
||||
// Simulate ToBigInt on a Value and produce a matching Int64.
|
||||
class LValueToInt64 : public LInstructionHelper<INT64_PIECES, BOX_PIECES, 2> {
|
||||
public:
|
||||
LIR_HEADER(ValueToInt64)
|
||||
|
||||
explicit LValueToInt64(const LBoxAllocation& input, const LDefinition& temp,
|
||||
const LDefinition& tempToUnbox)
|
||||
: LInstructionHelper(classOpcode) {
|
||||
setBoxOperand(Input, input);
|
||||
setTemp(0, temp);
|
||||
setTemp(1, tempToUnbox);
|
||||
}
|
||||
|
||||
static const size_t Input = 0;
|
||||
|
||||
const MToInt64* mir() const { return mir_->toToInt64(); }
|
||||
const LDefinition* temp() { return getTemp(0); }
|
||||
const LDefinition* tempToUnbox() { return getTemp(1); }
|
||||
};
|
||||
|
||||
// Truncate a BigInt to an unboxed int64.
|
||||
class LTruncateBigIntToInt64 : public LInstructionHelper<INT64_PIECES, 1, 0> {
|
||||
public:
|
||||
LIR_HEADER(TruncateBigIntToInt64)
|
||||
|
||||
explicit LTruncateBigIntToInt64(const LAllocation& input)
|
||||
: LInstructionHelper(classOpcode) {
|
||||
setOperand(Input, input);
|
||||
}
|
||||
|
||||
static const size_t Input = 0;
|
||||
|
||||
const MTruncateBigIntToInt64* mir() const {
|
||||
return mir_->toTruncateBigIntToInt64();
|
||||
}
|
||||
};
|
||||
|
||||
// Create a new BigInt* from an unboxed int64.
|
||||
class LInt64ToBigInt : public LInstructionHelper<1, INT64_PIECES, 2> {
|
||||
public:
|
||||
LIR_HEADER(Int64ToBigInt)
|
||||
|
||||
explicit LInt64ToBigInt(const LInt64Allocation& input,
|
||||
const LDefinition& temp1, const LDefinition& temp2)
|
||||
: LInstructionHelper(classOpcode) {
|
||||
setInt64Operand(Input, input);
|
||||
setTemp(0, temp1);
|
||||
setTemp(1, temp2);
|
||||
}
|
||||
|
||||
static const size_t Input = 0;
|
||||
|
||||
const MInt64ToBigInt* mir() const { return mir_->toInt64ToBigInt(); }
|
||||
const LDefinition* temp1() { return getTemp(0); }
|
||||
const LDefinition* temp2() { return getTemp(1); }
|
||||
};
|
||||
|
||||
// Guard that a value is in a TypeSet.
|
||||
|
|
Загрузка…
Ссылка в новой задаче