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:
André Bargull 2020-05-06 11:05:07 +00:00
Родитель 2c4fba5ce7
Коммит a926295890
7 изменённых файлов: 140 добавлений и 0 удалений

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

@ -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, &notBigInt);
masm.unboxBigInt(operand, output);
masm.jump(&done);
masm.bind(&notBigInt);
}
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