зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1536699 - Part 3: Add MToBigInt and ToBigIntPolicy. r=jandem
The next part needs `ToBigIntPolicy` when storing BigInts into a typed array. `MToBigInt` is currently only used as part of `ToBigIntPolicy`, therefore we have to bailout for effectful operations, like `ToBigInt(object)`. Only strings and booleans can be handled without a bailout. Differential Revision: https://phabricator.services.mozilla.com/D72641
This commit is contained in:
Родитель
2c4fba5ce7
Коммит
a926295890
|
@ -1096,6 +1096,49 @@ void CodeGenerator::visitValueToFloat32(LValueToFloat32* lir) {
|
|||
masm.bind(&done);
|
||||
}
|
||||
|
||||
void CodeGenerator::visitValueToBigInt(LValueToBigInt* lir) {
|
||||
ValueOperand operand = ToValue(lir, LValueToBigInt::Input);
|
||||
Register output = ToRegister(lir->output());
|
||||
|
||||
bool maybeBigInt = lir->mir()->input()->mightBeType(MIRType::BigInt);
|
||||
bool maybeBool = lir->mir()->input()->mightBeType(MIRType::Boolean);
|
||||
bool maybeString = lir->mir()->input()->mightBeType(MIRType::String);
|
||||
|
||||
Maybe<OutOfLineCode*> ool;
|
||||
if (maybeBool || maybeString) {
|
||||
using Fn = BigInt* (*)(JSContext*, HandleValue);
|
||||
ool = mozilla::Some(oolCallVM<Fn, ToBigInt>(lir, ArgList(operand),
|
||||
StoreRegisterTo(output)));
|
||||
}
|
||||
|
||||
Register tag = masm.extractTag(operand, output);
|
||||
|
||||
Label done;
|
||||
if (maybeBigInt) {
|
||||
Label notBigInt;
|
||||
masm.branchTestBigInt(Assembler::NotEqual, tag, ¬BigInt);
|
||||
masm.unboxBigInt(operand, output);
|
||||
masm.jump(&done);
|
||||
masm.bind(¬BigInt);
|
||||
}
|
||||
if (maybeBool) {
|
||||
masm.branchTestBoolean(Assembler::Equal, tag, (*ool)->entry());
|
||||
}
|
||||
if (maybeString) {
|
||||
masm.branchTestString(Assembler::Equal, tag, (*ool)->entry());
|
||||
}
|
||||
|
||||
// ToBigInt(object) can have side-effects; all other types throw a TypeError.
|
||||
bailout(lir->snapshot());
|
||||
|
||||
if (ool) {
|
||||
masm.bind((*ool)->rejoin());
|
||||
}
|
||||
if (maybeBigInt) {
|
||||
masm.bind(&done);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenerator::visitInt32ToDouble(LInt32ToDouble* lir) {
|
||||
masm.convertInt32ToDouble(ToRegister(lir->input()),
|
||||
ToFloatRegister(lir->output()));
|
||||
|
|
|
@ -2193,6 +2193,27 @@ void LIRGenerator::visitTruncateToInt32(MTruncateToInt32* truncate) {
|
|||
}
|
||||
}
|
||||
|
||||
void LIRGenerator::visitToBigInt(MToBigInt* ins) {
|
||||
MDefinition* opd = ins->input();
|
||||
|
||||
switch (opd->type()) {
|
||||
case MIRType::Value: {
|
||||
auto* lir = new (alloc()) LValueToBigInt(useBox(opd));
|
||||
assignSnapshot(lir, Bailout_NonPrimitiveInput);
|
||||
define(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
break;
|
||||
}
|
||||
|
||||
case MIRType::BigInt:
|
||||
redefine(ins, opd);
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("unexpected type");
|
||||
}
|
||||
}
|
||||
|
||||
void LIRGenerator::visitWasmTruncateToInt32(MWasmTruncateToInt32* ins) {
|
||||
MDefinition* input = ins->input();
|
||||
switch (input->type()) {
|
||||
|
|
|
@ -4193,6 +4193,33 @@ class MTruncateToInt32 : public MUnaryInstruction, public ToInt32Policy::Data {
|
|||
ALLOW_CLONE(MTruncateToInt32)
|
||||
};
|
||||
|
||||
// Converts a primitive (either typed or untyped) to a BigInt. If the input is
|
||||
// not primitive at runtime, a bailout occurs.
|
||||
class MToBigInt : public MUnaryInstruction, public ToBigIntPolicy::Data {
|
||||
private:
|
||||
explicit MToBigInt(MDefinition* def) : MUnaryInstruction(classOpcode, def) {
|
||||
setResultType(MIRType::BigInt);
|
||||
setMovable();
|
||||
|
||||
// Guard unless the conversion is known to be non-effectful & non-throwing.
|
||||
if (!def->definitelyType(
|
||||
{MIRType::Boolean, MIRType::String, MIRType::BigInt})) {
|
||||
setGuard();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(ToBigInt)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
AliasSet getAliasSet() const override { return AliasSet::None(); }
|
||||
|
||||
ALLOW_CLONE(MToBigInt)
|
||||
};
|
||||
|
||||
// Converts any type to a string
|
||||
class MToString : public MUnaryInstruction, public ToStringPolicy::Data {
|
||||
public:
|
||||
|
|
|
@ -813,6 +813,26 @@ bool ToInt32Policy::staticAdjustInputs(TempAllocator& alloc,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ToBigIntPolicy::staticAdjustInputs(TempAllocator& alloc,
|
||||
MInstruction* ins) {
|
||||
MOZ_ASSERT(ins->isToBigInt());
|
||||
|
||||
MDefinition* in = ins->getOperand(0);
|
||||
switch (in->type()) {
|
||||
case MIRType::BigInt:
|
||||
case MIRType::Value:
|
||||
// No need for boxing for these types.
|
||||
return true;
|
||||
default:
|
||||
// Any other types need to be boxed.
|
||||
break;
|
||||
}
|
||||
|
||||
in = BoxAt(alloc, ins, in);
|
||||
ins->replaceOperand(0, in);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ToStringPolicy::staticAdjustInputs(TempAllocator& alloc,
|
||||
MInstruction* ins) {
|
||||
MOZ_ASSERT(ins->isToString());
|
||||
|
@ -1151,6 +1171,7 @@ bool TypedArrayIndexPolicy::adjustInputs(TempAllocator& alloc,
|
|||
_(TestPolicy) \
|
||||
_(ToDoublePolicy) \
|
||||
_(ToInt32Policy) \
|
||||
_(ToBigIntPolicy) \
|
||||
_(ToStringPolicy) \
|
||||
_(TypeBarrierPolicy) \
|
||||
_(TypedArrayIndexPolicy)
|
||||
|
|
|
@ -323,6 +323,19 @@ class ToInt32Policy final : public TypePolicy {
|
|||
}
|
||||
};
|
||||
|
||||
// Box any non-BigInts as input to a ToBigInt instruction.
|
||||
class ToBigIntPolicy final : public TypePolicy {
|
||||
public:
|
||||
constexpr ToBigIntPolicy() = default;
|
||||
EMPTY_DATA_;
|
||||
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc,
|
||||
MInstruction* def);
|
||||
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc,
|
||||
MInstruction* def) const override {
|
||||
return staticAdjustInputs(alloc, def);
|
||||
}
|
||||
};
|
||||
|
||||
// Box objects as input to a ToString instruction.
|
||||
class ToStringPolicy final : public TypePolicy {
|
||||
public:
|
||||
|
|
|
@ -267,6 +267,7 @@ namespace jit {
|
|||
_(ThrowOperation, js::ThrowOperation) \
|
||||
_(ThrowRuntimeLexicalError, js::jit::ThrowRuntimeLexicalError) \
|
||||
_(ThrowUninitializedThis, js::ThrowUninitializedThis) \
|
||||
_(ToBigInt, js::ToBigInt) \
|
||||
_(ToIdOperation, js::ToIdOperation) \
|
||||
_(ToObjectSlow, js::ToObjectSlow) \
|
||||
_(ToStringSlow, js::ToStringSlow<CanGC>) \
|
||||
|
|
|
@ -2941,6 +2941,20 @@ class LValueToInt32 : public LInstructionHelper<1, BOX_PIECES, 2> {
|
|||
MInstruction* mir() const { return mir_->toInstruction(); }
|
||||
};
|
||||
|
||||
// Convert a value to a BigInt.
|
||||
class LValueToBigInt : public LInstructionHelper<1, BOX_PIECES, 0> {
|
||||
public:
|
||||
LIR_HEADER(ValueToBigInt)
|
||||
static const size_t Input = 0;
|
||||
|
||||
explicit LValueToBigInt(const LBoxAllocation& input)
|
||||
: LInstructionHelper(classOpcode) {
|
||||
setBoxOperand(Input, input);
|
||||
}
|
||||
|
||||
MToBigInt* mir() const { return mir_->toToBigInt(); }
|
||||
};
|
||||
|
||||
// Convert a double to an int32.
|
||||
// Input: floating-point register
|
||||
// Output: 32-bit integer
|
||||
|
|
Загрузка…
Ссылка в новой задаче