Issue #1240 - Part 10 - Implement minimal Ion support for BigInt. https://bugzilla.mozilla.org/show_bug.cgi?id=1507484 Implement IC support for BigInt. https://bugzilla.mozilla.org/show_bug.cgi?id=1522431

This commit is contained in:
Brian Smith 2023-07-21 20:25:52 -05:00 committed by roytam1
commit 2d5ee3c457
39 changed files with 448 additions and 43 deletions

View file

@ -1958,6 +1958,7 @@ jit::FinishBailoutToBaseline(BaselineBailoutInfo* bailoutInfo)
case Bailout_NonObjectInput:
case Bailout_NonStringInput:
case Bailout_NonSymbolInput:
case Bailout_NonBigIntInput:
case Bailout_UnexpectedSimdInput:
case Bailout_NonSharedTypedArrayInput:
case Bailout_Debugger:

View file

@ -710,6 +710,9 @@ BaselineCacheIRCompiler::emitGuardType()
case JSVAL_TYPE_SYMBOL:
masm.branchTestSymbol(Assembler::NotEqual, input, failure->label());
break;
case JSVAL_TYPE_BIGINT:
masm.branchTestBigInt(Assembler::NotEqual, input, failure->label());
break;
case JSVAL_TYPE_DOUBLE:
masm.branchTestNumber(Assembler::NotEqual, input, failure->label());
break;

View file

@ -8094,7 +8094,8 @@ ICTypeOf_Typed::Compiler::generateStubCode(MacroAssembler& masm)
break;
case JSTYPE_BIGINT:
return false;
masm.branchTestBigInt(Assembler::NotEqual, R0, &failure);
break;
default:
MOZ_CRASH("Unexpected type");

View file

@ -446,6 +446,9 @@ GetPropIRGenerator::tryAttachPrimitive(CacheIRWriter& writer, ValOperandId valId
} else if (val_.isSymbol()) {
primitiveType = JSVAL_TYPE_SYMBOL;
proto = MaybeNativeObject(GetBuiltinPrototypePure(cx_->global(), JSProto_Symbol));
} else if (val_.isBigInt()) {
primitiveType = JSVAL_TYPE_BIGINT;
proto = MaybeNativeObject(GetBuiltinPrototypePure(cx_->global(), JSProto_BigInt));
} else {
MOZ_ASSERT(val_.isNullOrUndefined() || val_.isMagic());
return true;

View file

@ -526,9 +526,11 @@ CodeGenerator::testValueTruthyKernel(const ValueOperand& value,
bool mightBeString = valueMIR->mightBeType(MIRType::String);
bool mightBeSymbol = valueMIR->mightBeType(MIRType::Symbol);
bool mightBeDouble = valueMIR->mightBeType(MIRType::Double);
bool mightBeBigInt = valueMIR->mightBeType(MIRType::BigInt);
int tagCount = int(mightBeUndefined) + int(mightBeNull) +
int(mightBeBoolean) + int(mightBeInt32) + int(mightBeObject) +
int(mightBeString) + int(mightBeSymbol) + int(mightBeDouble);
int(mightBeString) + int(mightBeSymbol) + int(mightBeDouble) +
int(mightBeBigInt);;
MOZ_ASSERT_IF(!valueMIR->emptyResultTypeSet(), tagCount > 0);
@ -618,6 +620,20 @@ CodeGenerator::testValueTruthyKernel(const ValueOperand& value,
--tagCount;
}
if (mightBeBigInt) {
MOZ_ASSERT(tagCount != 0);
Label notBigInt;
if (tagCount != 1) {
masm.branchTestBigInt(Assembler::NotEqual, tag, &notBigInt);
}
masm.branchTestBigIntTruthy(false, value, ifFalsy);
if (tagCount != 1) {
masm.jump(ifTruthy);
}
masm.bind(&notBigInt);
--tagCount;
}
if (mightBeSymbol) {
// All symbols are truthy.
MOZ_ASSERT(tagCount != 0);
@ -954,8 +970,15 @@ CodeGenerator::visitValueToString(LValueToString* lir)
}
// Symbol
if (lir->mir()->input()->mightBeType(MIRType::Symbol))
if (lir->mir()->input()->mightBeType(MIRType::Symbol)) {
masm.branchTestSymbol(Assembler::Equal, tag, ool->entry());
}
// BigInt
if (lir->mir()->input()->mightBeType(MIRType::BigInt)) {
// No fastpath currently implemented.
masm.branchTestBigInt(Assembler::Equal, tag, ool->entry());
}
#ifdef DEBUG
masm.assumeUnreachable("Unexpected type for MValueToString.");
@ -4902,10 +4925,11 @@ CodeGenerator::branchIfInvalidated(Register temp, Label* invalidated)
}
void
CodeGenerator::emitAssertObjectOrStringResult(Register input, MIRType type, const TemporaryTypeSet* typeset)
CodeGenerator::emitAssertGCThingResult(Register input, MIRType type, const TemporaryTypeSet* typeset)
{
MOZ_ASSERT(type == MIRType::Object || type == MIRType::ObjectOrNull ||
type == MIRType::String || type == MIRType::Symbol);
type == MIRType::String || type == MIRType::Symbol ||
type == MIRType::BigInt);
AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
regs.take(input);
@ -4960,6 +4984,9 @@ CodeGenerator::emitAssertObjectOrStringResult(Register input, MIRType type, cons
case MIRType::Symbol:
callee = JS_FUNC_TO_DATA_PTR(void*, AssertValidSymbolPtr);
break;
case MIRType::BigInt:
callee = JS_FUNC_TO_DATA_PTR(void*, AssertValidBigIntPtr);
break;
default:
MOZ_CRASH();
}
@ -5029,7 +5056,7 @@ CodeGenerator::emitAssertResultV(const ValueOperand input, const TemporaryTypeSe
#ifdef DEBUG
void
CodeGenerator::emitObjectOrStringResultChecks(LInstruction* lir, MDefinition* mir)
CodeGenerator::emitGCThingResultChecks(LInstruction* lir, MDefinition* mir)
{
if (lir->numDefs() == 0)
return;
@ -5037,7 +5064,7 @@ CodeGenerator::emitObjectOrStringResultChecks(LInstruction* lir, MDefinition* mi
MOZ_ASSERT(lir->numDefs() == 1);
Register output = ToRegister(lir->getDef(0));
emitAssertObjectOrStringResult(output, mir->type(), mir->resultTypeSet());
emitAssertGCThingResult(output, mir->type(), mir->resultTypeSet());
}
void
@ -5069,7 +5096,8 @@ CodeGenerator::emitDebugResultChecks(LInstruction* ins)
case MIRType::ObjectOrNull:
case MIRType::String:
case MIRType::Symbol:
emitObjectOrStringResultChecks(ins, mir);
case MIRType::BigInt:
emitGCThingResultChecks(ins, mir);
break;
case MIRType::Value:
emitValueResultChecks(ins, mir);
@ -10386,9 +10414,11 @@ CodeGenerator::visitTypeOfV(LTypeOfV* lir)
bool testNull = input->mightBeType(MIRType::Null);
bool testString = input->mightBeType(MIRType::String);
bool testSymbol = input->mightBeType(MIRType::Symbol);
bool testBigInt = input->mightBeType(MIRType::BigInt);
unsigned numTests = unsigned(testObject) + unsigned(testNumber) + unsigned(testBoolean) +
unsigned(testUndefined) + unsigned(testNull) + unsigned(testString) + unsigned(testSymbol);
unsigned(testUndefined) + unsigned(testNull) + unsigned(testString) + unsigned(testSymbol) +
unsigned(testBigInt);
MOZ_ASSERT_IF(!input->emptyResultTypeSet(), numTests > 0);
@ -10484,6 +10514,19 @@ CodeGenerator::visitTypeOfV(LTypeOfV* lir)
numTests--;
}
if (testBigInt) {
Label notBigInt;
if (numTests > 1) {
masm.branchTestBigInt(Assembler::NotEqual, tag, &notBigInt);
}
masm.movePtr(ImmGCPtr(names.bigint), output);
if (numTests > 1) {
masm.jump(&done);
}
masm.bind(&notBigInt);
numTests--;
}
MOZ_ASSERT(numTests == 0);
masm.bind(&done);
@ -11794,7 +11837,7 @@ CodeGenerator::visitAssertResultT(LAssertResultT* ins)
Register input = ToRegister(ins->input());
MDefinition* mir = ins->mirRaw();
emitAssertObjectOrStringResult(input, mir->type(), mir->resultTypeSet());
emitAssertGCThingResult(input, mir->type(), mir->resultTypeSet());
}
void

View file

@ -431,7 +431,7 @@ class CodeGenerator final : public CodeGeneratorSpecific
void visitAssertResultV(LAssertResultV* ins);
void visitAssertResultT(LAssertResultT* ins);
void emitAssertResultV(const ValueOperand output, const TemporaryTypeSet* typeset);
void emitAssertObjectOrStringResult(Register input, MIRType type, const TemporaryTypeSet* typeset);
void emitAssertGCThingResult(Register input, MIRType type, const TemporaryTypeSet* typeset);
void visitInterruptCheck(LInterruptCheck* lir);
void visitOutOfLineInterruptCheckImplicit(OutOfLineInterruptCheckImplicit* ins);
@ -571,7 +571,7 @@ class CodeGenerator final : public CodeGeneratorSpecific
#ifdef DEBUG
void emitDebugResultChecks(LInstruction* ins);
void emitObjectOrStringResultChecks(LInstruction* lir, MDefinition* mir);
void emitGCThingResultChecks(LInstruction* lir, MDefinition* mir);
void emitValueResultChecks(LInstruction* lir, MDefinition* mir);
#endif

View file

@ -2611,6 +2611,7 @@ IsResumableMIRType(MIRType type)
case MIRType::Float32:
case MIRType::String:
case MIRType::Symbol:
case MIRType::BigInt:
case MIRType::Object:
case MIRType::MagicOptimizedArguments:
case MIRType::MagicOptimizedOut:

View file

@ -721,6 +721,9 @@ IonBuilder::analyzeNewLoopTypes(MBasicBlock* entry, jsbytecode* start, jsbytecod
case JSOP_NEG:
type = inspector->expectedResultType(last);
break;
case JSOP_BIGINT:
type = MIRType::BigInt;
break;
default:
break;
}
@ -1347,6 +1350,7 @@ IonBuilder::addOsrValueTypeBarrier(uint32_t slot, MInstruction** def_,
case MIRType::Double:
case MIRType::String:
case MIRType::Symbol:
case MIRType::BigInt:
case MIRType::Object:
if (type != def->type()) {
MUnbox* unbox = MUnbox::New(alloc(), def, type, MUnbox::Fallible);
@ -4761,8 +4765,10 @@ IonBuilder::bitnotTrySpecialized(bool* emitted, MDefinition* input)
// Try to emit a specialized bitnot instruction based on the input type
// of the operand.
if (input->mightBeType(MIRType::Object) || input->mightBeType(MIRType::Symbol))
if (input->mightBeType(MIRType::Object) || input->mightBeType(MIRType::Symbol) ||
input->mightBeType(MIRType::BigInt)) {
return true;
}
MBitNot* ins = MBitNot::New(alloc(), input);
ins->setSpecialization(MIRType::Int32);
@ -7210,6 +7216,7 @@ ObjectOrSimplePrimitive(MDefinition* op)
// Return true if op is either undefined/null/boolean/int32 or an object.
return !op->mightBeType(MIRType::String)
&& !op->mightBeType(MIRType::Symbol)
&& !op->mightBeType(MIRType::BigInt)
&& !op->mightBeType(MIRType::Double)
&& !op->mightBeType(MIRType::Float32)
&& !op->mightBeType(MIRType::MagicOptimizedArguments)
@ -8349,6 +8356,10 @@ IonBuilder::testSingletonPropertyTypes(MDefinition* obj, jsid id)
key = JSProto_Symbol;
break;
case MIRType::BigInt:
key = JSProto_BigInt;
break;
case MIRType::Int32:
case MIRType::Double:
key = JSProto_Number;

View file

@ -103,6 +103,7 @@ enum BailoutKind
Bailout_NonObjectInput,
Bailout_NonStringInput,
Bailout_NonSymbolInput,
Bailout_NonBigIntInput,
// SIMD Unbox expects a given type, bails out if it doesn't match.
Bailout_UnexpectedSimdInput,
@ -212,6 +213,8 @@ BailoutKindString(BailoutKind kind)
return "Bailout_NonStringInput";
case Bailout_NonSymbolInput:
return "Bailout_NonSymbolInput";
case Bailout_NonBigIntInput:
return "Bailout_NonBigIntInput";
case Bailout_UnexpectedSimdInput:
return "Bailout_UnexpectedSimdInput";
case Bailout_NonSharedTypedArrayInput:
@ -412,6 +415,7 @@ enum class MIRType
// Types above have trivial conversion to a number.
String,
Symbol,
BigInt,
// Types above are primitive (including undefined and null).
Object,
MagicOptimizedArguments, // JS_OPTIMIZED_ARGUMENTS magic value.
@ -496,6 +500,8 @@ MIRTypeFromValueType(JSValueType type)
return MIRType::String;
case JSVAL_TYPE_SYMBOL:
return MIRType::Symbol;
case JSVAL_TYPE_BIGINT:
return MIRType::BigInt;
case JSVAL_TYPE_BOOLEAN:
return MIRType::Boolean;
case JSVAL_TYPE_NULL:
@ -528,6 +534,8 @@ ValueTypeFromMIRType(MIRType type)
return JSVAL_TYPE_STRING;
case MIRType::Symbol:
return JSVAL_TYPE_SYMBOL;
case MIRType::BigInt:
return JSVAL_TYPE_BIGINT;
case MIRType::MagicOptimizedArguments:
case MIRType::MagicOptimizedOut:
case MIRType::MagicHole:
@ -568,6 +576,8 @@ StringFromMIRType(MIRType type)
return "String";
case MIRType::Symbol:
return "Symbol";
case MIRType::BigInt:
return "BigInt";
case MIRType::Object:
return "Object";
case MIRType::MagicOptimizedArguments:

View file

@ -599,6 +599,7 @@ class LDefinition
return LDefinition::INT32;
case MIRType::String:
case MIRType::Symbol:
case MIRType::BigInt:
case MIRType::Object:
case MIRType::ObjectOrNull:
return LDefinition::OBJECT;

View file

@ -717,6 +717,10 @@ LIRGenerator::visitTest(MTest* test)
// TestPolicy).
MOZ_ASSERT(opd->type() != MIRType::String);
// BigInt is boxed in type analysis.
MOZ_ASSERT(opd->type() != MIRType::BigInt,
"BigInt should be boxed by TestPolicy");
// Testing a constant.
if (MConstant* constant = opd->maybeConstantValue()) {
bool b;
@ -2149,9 +2153,11 @@ LIRGenerator::visitToInt32(MToInt32* convert)
case MIRType::String:
case MIRType::Symbol:
case MIRType::BigInt:
case MIRType::Object:
case MIRType::Undefined:
// Objects might be effectful. Symbols throw. Undefined coerces to NaN, not int32.
// Objects might be effectful. Symbols and BigInts throw. Undefined
// coerces to NaN, not int32.
MOZ_CRASH("ToInt32 invalid input type");
default:
@ -2939,6 +2945,8 @@ LIRGenerator::visitNot(MNot* ins)
// String is converted to length of string in the type analysis phase (see
// TestPolicy).
MOZ_ASSERT(op->type() != MIRType::String);
MOZ_ASSERT(op->type() != MIRType::BigInt,
"BigInt should be boxed by TestPolicy");
// - boolean: x xor 1
// - int32: LCompare(x, 0)

View file

@ -2894,6 +2894,7 @@ IonBuilder::inlineToInteger(CallInfo& callInfo)
if (input->mightBeType(MIRType::Object) ||
input->mightBeType(MIRType::String) ||
input->mightBeType(MIRType::Symbol) ||
input->mightBeType(MIRType::BigInt) ||
input->mightBeType(MIRType::Undefined) ||
input->mightBeMagicType())
{
@ -3021,12 +3022,16 @@ IonBuilder::inlineAtomicsCompareExchange(CallInfo& callInfo)
// These guards are desirable here and in subsequent atomics to
// avoid bad bailouts with MTruncateToInt32, see https://bugzilla.mozilla.org/show_bug.cgi?id=1141986#c20.
MDefinition* oldval = callInfo.getArg(2);
if (oldval->mightBeType(MIRType::Object) || oldval->mightBeType(MIRType::Symbol))
if (oldval->mightBeType(MIRType::Object) || oldval->mightBeType(MIRType::Symbol) ||
oldval->mightBeType(MIRType::BigInt)) {
return InliningStatus_NotInlined;
}
MDefinition* newval = callInfo.getArg(3);
if (newval->mightBeType(MIRType::Object) || newval->mightBeType(MIRType::Symbol))
if (newval->mightBeType(MIRType::Object) || newval->mightBeType(MIRType::Symbol) ||
newval->mightBeType(MIRType::BigInt)) {
return InliningStatus_NotInlined;
}
Scalar::Type arrayType;
bool requiresCheck = false;
@ -3063,8 +3068,10 @@ IonBuilder::inlineAtomicsExchange(CallInfo& callInfo)
}
MDefinition* value = callInfo.getArg(2);
if (value->mightBeType(MIRType::Object) || value->mightBeType(MIRType::Symbol))
if (value->mightBeType(MIRType::Object) || value->mightBeType(MIRType::Symbol) ||
value->mightBeType(MIRType::BigInt)) {
return InliningStatus_NotInlined;
}
Scalar::Type arrayType;
bool requiresCheck = false;
@ -3151,8 +3158,10 @@ IonBuilder::inlineAtomicsStore(CallInfo& callInfo)
return InliningStatus_NotInlined;
}
if (value->mightBeType(MIRType::Object) || value->mightBeType(MIRType::Symbol))
if (value->mightBeType(MIRType::Object) || value->mightBeType(MIRType::Symbol) ||
value->mightBeType(MIRType::BigInt)) {
return InliningStatus_NotInlined;
}
Scalar::Type arrayType;
bool requiresCheck = false;
@ -3194,8 +3203,10 @@ IonBuilder::inlineAtomicsBinop(CallInfo& callInfo, InlinableNative target)
}
MDefinition* value = callInfo.getArg(2);
if (value->mightBeType(MIRType::Object) || value->mightBeType(MIRType::Symbol))
if (value->mightBeType(MIRType::Object) || value->mightBeType(MIRType::Symbol) ||
value->mightBeType(MIRType::BigInt)) {
return InliningStatus_NotInlined;
}
Scalar::Type arrayType;
bool requiresCheck = false;

View file

@ -935,6 +935,9 @@ MConstant::MConstant(const js::Value& vp, CompilerConstraintList* constraints)
case MIRType::Symbol:
payload_.sym = vp.toSymbol();
break;
case MIRType::BigInt:
payload_.bi = vp.toBigInt();
break;
case MIRType::Object:
payload_.obj = &vp.toObject();
// Create a singleton type set for the object. This isn't necessary for
@ -1014,7 +1017,12 @@ MConstant::assertInitializedPayload() const
case MIRType::String:
case MIRType::Object:
case MIRType::Symbol:
case MIRType::BigInt:
#if MOZ_LITTLE_ENDIAN
MOZ_ASSERT_IF(JS_BITS_PER_WORD == 32, (payload_.asBits >> 32) == 0);
#else
MOZ_ASSERT_IF(JS_BITS_PER_WORD == 32, (payload_.asBits << 32) == 0);
#endif
break;
default:
MOZ_ASSERT(IsNullOrUndefined(type()) || IsMagicType(type()));
@ -1103,6 +1111,9 @@ MConstant::printOpcode(GenericPrinter& out) const
case MIRType::Symbol:
out.printf("symbol at %p", (void*)toSymbol());
break;
case MIRType::BigInt:
out.printf("BigInt at %p", (void*)toBigInt());
break;
case MIRType::String:
out.printf("string %p", (void*)toString());
break;
@ -1164,6 +1175,8 @@ MConstant::toJSValue() const
return StringValue(toString());
case MIRType::Symbol:
return SymbolValue(toSymbol());
case MIRType::BigInt:
return BigIntValue(toBigInt());
case MIRType::Object:
return ObjectValue(toObject());
case MIRType::MagicOptimizedArguments:
@ -1207,6 +1220,9 @@ MConstant::valueToBoolean(bool* res) const
case MIRType::Symbol:
*res = true;
return true;
case MIRType::BigInt:
*res = !toBigInt()->isZero();
return true;
case MIRType::String:
*res = toString()->length() != 0;
return true;
@ -2199,6 +2215,7 @@ MUnbox::printOpcode(GenericPrinter& out) const
case MIRType::Boolean: out.printf("to Boolean"); break;
case MIRType::String: out.printf("to String"); break;
case MIRType::Symbol: out.printf("to Symbol"); break;
case MIRType::BigInt: out.printf("to BigInt"); break;
case MIRType::Object: out.printf("to Object"); break;
default: break;
}
@ -2591,6 +2608,7 @@ jit::TypeSetIncludes(TypeSet* types, MIRType input, TypeSet* inputTypes)
case MIRType::Float32:
case MIRType::String:
case MIRType::Symbol:
case MIRType::BigInt:
case MIRType::MagicOptimizedArguments:
return types->hasType(TypeSet::PrimitiveType(ValueTypeFromMIRType(input)));
@ -2846,7 +2864,8 @@ void
MBinaryBitwiseInstruction::infer(BaselineInspector*, jsbytecode*)
{
if (getOperand(0)->mightBeType(MIRType::Object) || getOperand(0)->mightBeType(MIRType::Symbol) ||
getOperand(1)->mightBeType(MIRType::Object) || getOperand(1)->mightBeType(MIRType::Symbol))
getOperand(1)->mightBeType(MIRType::Object) || getOperand(1)->mightBeType(MIRType::Symbol) ||
getOperand(1)->mightBeType(MIRType::BigInt))
{
specialization_ = MIRType::None;
setResultType(MIRType::Value);
@ -2872,7 +2891,8 @@ void
MShiftInstruction::infer(BaselineInspector*, jsbytecode*)
{
if (getOperand(0)->mightBeType(MIRType::Object) || getOperand(1)->mightBeType(MIRType::Object) ||
getOperand(0)->mightBeType(MIRType::Symbol) || getOperand(1)->mightBeType(MIRType::Symbol))
getOperand(0)->mightBeType(MIRType::Symbol) || getOperand(1)->mightBeType(MIRType::Symbol) ||
getOperand(0)->mightBeType(MIRType::BigInt) || getOperand(1)->mightBeType(MIRType::BigInt))
{
specialization_ = MIRType::None;
setResultType(MIRType::Value);
@ -2886,7 +2906,8 @@ void
MUrsh::infer(BaselineInspector* inspector, jsbytecode* pc)
{
if (getOperand(0)->mightBeType(MIRType::Object) || getOperand(1)->mightBeType(MIRType::Object) ||
getOperand(0)->mightBeType(MIRType::Symbol) || getOperand(1)->mightBeType(MIRType::Symbol))
getOperand(0)->mightBeType(MIRType::Symbol) || getOperand(1)->mightBeType(MIRType::Symbol) ||
getOperand(0)->mightBeType(MIRType::BigInt) || getOperand(1)->mightBeType(MIRType::BigInt))
{
specialization_ = MIRType::None;
setResultType(MIRType::Value);
@ -3880,6 +3901,9 @@ MTypeOf::foldsTo(TempAllocator& alloc)
case MIRType::Symbol:
type = JSTYPE_SYMBOL;
break;
case MIRType::BigInt:
type = JSTYPE_BIGINT;
break;
case MIRType::Null:
type = JSTYPE_OBJECT;
break;
@ -4459,6 +4483,12 @@ MCompare::tryFoldTypeOf(bool* result)
*result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
return true;
}
}
else if (constant->toString() == TypeName(JSTYPE_BIGINT, names)) {
if (!typeOf->input()->mightBeType(MIRType::BigInt)) {
*result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
return true;
}
} else if (constant->toString() == TypeName(JSTYPE_OBJECT, names)) {
if (!typeOf->input()->mightBeType(MIRType::Object) &&
!typeOf->input()->mightBeType(MIRType::Null))
@ -5612,6 +5642,8 @@ MConstant::appendRoots(MRootList& roots) const
return roots.append(toString());
case MIRType::Symbol:
return roots.append(toSymbol());
case MIRType::BigInt:
return roots.append(toBigInt());
case MIRType::Object:
return roots.append(&toObject());
case MIRType::Undefined:

View file

@ -1548,6 +1548,7 @@ class MConstant : public MNullaryInstruction
double d;
JSString* str;
JS::Symbol* sym;
BigInt* bi;
JSObject* obj;
uint64_t asBits;
};
@ -1672,6 +1673,10 @@ class MConstant : public MNullaryInstruction
MOZ_ASSERT(type() == MIRType::Symbol);
return payload_.sym;
}
BigInt* toBigInt() const {
MOZ_ASSERT(type() == MIRType::BigInt);
return payload_.bi;
}
JSObject& toObject() const {
MOZ_ASSERT(type() == MIRType::Object);
return *payload_.obj;
@ -4743,6 +4748,7 @@ class MUnbox final : public MUnaryInstruction, public BoxInputsPolicy::Data
type == MIRType::Double ||
type == MIRType::String ||
type == MIRType::Symbol ||
type == MIRType::BigInt ||
type == MIRType::Object);
TemporaryTypeSet* resultSet = ins->resultTypeSet();
@ -4781,6 +4787,9 @@ class MUnbox final : public MUnaryInstruction, public BoxInputsPolicy::Data
case MIRType::Symbol:
kind = Bailout_NonSymbolInput;
break;
case MIRType::BigInt:
kind = Bailout_NonBigIntInput;
break;
case MIRType::Object:
kind = Bailout_NonObjectInput;
break;
@ -5189,9 +5198,11 @@ class MToDouble
setMovable();
// An object might have "valueOf", which means it is effectful.
// ToNumber(symbol) throws.
if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol))
// ToNumber(symbol) and ToNumber(bigint) throw.
if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol) ||
def->mightBeType(MIRType::BigInt)) {
setGuard();
}
}
public:
@ -5226,11 +5237,15 @@ class MToDouble
MOZ_MUST_USE bool writeRecoverData(CompactBufferWriter& writer) const override;
bool canRecoverOnBailout() const override {
if (input()->type() == MIRType::Value)
if (input()->type() == MIRType::Value) {
return false;
if (input()->type() == MIRType::Symbol)
}
if (input()->type() == MIRType::Symbol) {
return false;
}
if (input()->type() == MIRType::BigInt) {
return false;
}
return true;
}
@ -5253,9 +5268,11 @@ class MToFloat32
setMovable();
// An object might have "valueOf", which means it is effectful.
// ToNumber(symbol) throws.
if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol))
// ToNumber(symbol) and ToNumber(BigInt) throw.
if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol) ||
def->mightBeType(MIRType::BigInt)) {
setGuard();
}
}
explicit MToFloat32(MDefinition* def, bool mustPreserveNaN)
@ -5537,9 +5554,11 @@ class MToInt32
setMovable();
// An object might have "valueOf", which means it is effectful.
// ToNumber(symbol) throws.
if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol))
// ToInt32(symbol) and ToInt32(BigInt) throw.
if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol) ||
def->mightBeType(MIRType::BigInt)) {
setGuard();
}
}
public:
@ -5594,9 +5613,11 @@ class MTruncateToInt32
setMovable();
// An object might have "valueOf", which means it is effectful.
// ToInt32(symbol) throws.
if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol))
// ToInt32(symbol) and ToInt32(BigInt) throw.
if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol) ||
def->mightBeType(MIRType::BigInt)) {
setGuard();
}
}
public:
@ -5639,9 +5660,12 @@ class MToString :
setResultType(MIRType::String);
setMovable();
// Objects might override toString and Symbols throw.
if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol))
// Objects might override toString; Symbol and BigInts throw. We bailout in
// those cases and run side-effects in baseline instead.
if (def->mightBeType(MIRType::Object) || def->mightBeType(MIRType::Symbol) ||
def->mightBeType(MIRType::BigInt)) {
setGuard();
}
}
public:

View file

@ -545,6 +545,7 @@ MacroAssembler::branchTestMIRType(Condition cond, const Value& val, MIRType type
case MIRType::Int32: return branchTestInt32(cond, val, label);
case MIRType::String: return branchTestString(cond, val, label);
case MIRType::Symbol: return branchTestSymbol(cond, val, label);
case MIRType::BigInt: return branchTestBigInt(cond, val, label);
case MIRType::Object: return branchTestObject(cond, val, label);
case MIRType::Double: return branchTestDouble(cond, val, label);
case MIRType::MagicOptimizedArguments: // Fall through.

View file

@ -45,12 +45,13 @@ MacroAssembler::guardTypeSet(const Source& address, const TypeSet* types, Barrie
MOZ_ASSERT(!types->unknown());
Label matched;
TypeSet::Type tests[8] = {
TypeSet::Type tests[9] = {
TypeSet::Int32Type(),
TypeSet::UndefinedType(),
TypeSet::BooleanType(),
TypeSet::StringType(),
TypeSet::SymbolType(),
TypeSet::BigIntType(),
TypeSet::NullType(),
TypeSet::MagicArgType(),
TypeSet::AnyObjectType()
@ -2736,6 +2737,9 @@ MacroAssembler::maybeBranchTestType(MIRType type, MDefinition* maybeDef, Registe
case MIRType::Symbol:
branchTestSymbol(Equal, tag, label);
break;
case MIRType::BigInt:
branchTestBigInt(Equal, tag, label);
break;
case MIRType::Object:
branchTestObject(Equal, tag, label);
break;

View file

@ -1137,6 +1137,7 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void branchTestBoolean(Condition cond, Register tag, Label* label) PER_SHARED_ARCH;
inline void branchTestString(Condition cond, Register tag, Label* label) PER_SHARED_ARCH;
inline void branchTestSymbol(Condition cond, Register tag, Label* label) PER_SHARED_ARCH;
inline void branchTestBigInt(Condition cond, Register tag, Label* label) PER_SHARED_ARCH;
inline void branchTestNull(Condition cond, Register tag, Label* label) PER_SHARED_ARCH;
inline void branchTestObject(Condition cond, Register tag, Label* label) PER_SHARED_ARCH;
inline void branchTestPrimitive(Condition cond, Register tag, Label* label) PER_SHARED_ARCH;
@ -1177,6 +1178,10 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void branchTestSymbol(Condition cond, const ValueOperand& value, Label* label)
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
inline void branchTestBigInt(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH;
inline void branchTestBigInt(Condition cond, const ValueOperand& value, Label* label)
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
inline void branchTestNull(Condition cond, const Address& address, Label* label) PER_SHARED_ARCH;
inline void branchTestNull(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH;
inline void branchTestNull(Condition cond, const ValueOperand& value, Label* label)
@ -1216,6 +1221,8 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void branchTestBooleanTruthy(bool truthy, const ValueOperand& value, Label* label) PER_ARCH;
inline void branchTestStringTruthy(bool truthy, const ValueOperand& value, Label* label)
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
inline void branchTestBigIntTruthy(bool truthy, const ValueOperand& value, Label* label)
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
private:
@ -1256,6 +1263,9 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void branchTestSymbolImpl(Condition cond, const T& t, Label* label)
DEFINED_ON(arm, arm64, x86_shared);
template <typename T>
inline void branchTestBigIntImpl(Condition cond, const T& t, Label* label)
DEFINED_ON(arm, arm64, x86_shared);
template <typename T>
inline void branchTestNullImpl(Condition cond, const T& t, Label* label)
DEFINED_ON(arm, arm64, x86_shared);
template <typename T>

View file

@ -409,6 +409,8 @@ ValTypeToString(JSValueType type)
return "string";
case JSVAL_TYPE_SYMBOL:
return "symbol";
case JSVAL_TYPE_BIGINT:
return "BigInt";
case JSVAL_TYPE_BOOLEAN:
return "boolean";
case JSVAL_TYPE_OBJECT:

View file

@ -700,7 +700,8 @@ ToDoublePolicy::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
case MIRType::Object:
case MIRType::String:
case MIRType::Symbol:
// Objects might be effectful. Symbols give TypeError.
case MIRType::BigInt:
// Objects might be effectful. Symbols and BigInts give TypeError.
break;
default:
break;
@ -748,7 +749,8 @@ ToInt32Policy::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
case MIRType::Object:
case MIRType::String:
case MIRType::Symbol:
// Objects might be effectful. Symbols give TypeError.
case MIRType::BigInt:
// Objects might be effectful. Symbols and BigInts give TypeError.
break;
default:
break;
@ -765,7 +767,8 @@ ToStringPolicy::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
MOZ_ASSERT(ins->isToString());
MIRType type = ins->getOperand(0)->type();
if (type == MIRType::Object || type == MIRType::Symbol) {
if (type == MIRType::Object || type == MIRType::Symbol ||
type == MIRType::BigInt) {
ins->replaceOperand(0, BoxAt(alloc, ins, ins->getOperand(0)));
return true;
}
@ -955,6 +958,7 @@ StoreUnboxedScalarPolicy::adjustValueInput(TempAllocator& alloc, MInstruction* i
case MIRType::Object:
case MIRType::String:
case MIRType::Symbol:
case MIRType::BigInt:
value = BoxAt(alloc, ins, value);
break;
default:

View file

@ -1236,15 +1236,27 @@ AssertValidSymbolPtr(JSContext* cx, JS::Symbol* sym)
MOZ_ASSERT(sym->getAllocKind() == gc::AllocKind::SYMBOL);
}
void
AssertValidBigIntPtr(JSContext* cx, JS::BigInt* bi) {
// FIXME: check runtime?
MOZ_ASSERT(cx->zone() == bi->zone());
MOZ_ASSERT(bi->isAligned());
MOZ_ASSERT(bi->isTenured());
MOZ_ASSERT(bi->getAllocKind() == gc::AllocKind::BIGINT);
}
void
AssertValidValue(JSContext* cx, Value* v)
{
if (v->isObject())
if (v->isObject()) {
AssertValidObjectPtr(cx, &v->toObject());
else if (v->isString())
} else if (v->isString()) {
AssertValidStringPtr(cx, v->toString());
else if (v->isSymbol())
} else if (v->isSymbol()) {
AssertValidSymbolPtr(cx, v->toSymbol());
} else if (v->isBigInt()) {
AssertValidBigIntPtr(cx, v->toBigInt());
}
}
bool

View file

@ -751,6 +751,7 @@ void AssertValidObjectPtr(JSContext* cx, JSObject* obj);
void AssertValidObjectOrNullPtr(JSContext* cx, JSObject* obj);
void AssertValidStringPtr(JSContext* cx, JSString* str);
void AssertValidSymbolPtr(JSContext* cx, JS::Symbol* sym);
void AssertValidBigIntPtr(JSContext* cx, JS::BigInt* bi);
void AssertValidValue(JSContext* cx, Value* v);
void MarkValueFromIon(JSRuntime* rt, Value* vp);

View file

@ -1880,6 +1880,29 @@ MacroAssembler::branchTestSymbolImpl(Condition cond, const T& t, Label* label)
ma_b(label, c);
}
void MacroAssembler::branchTestBigInt(Condition cond, Register tag, Label* label) {
branchTestBigIntImpl(cond, tag, label);
}
void MacroAssembler::branchTestBigInt(Condition cond, const BaseIndex& address, Label* label) {
branchTestBigIntImpl(cond, address, label);
}
void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value, Label* label) {
branchTestBigIntImpl(cond, value, label);
}
template <typename T>
void MacroAssembler::branchTestBigIntImpl(Condition cond, const T& t, Label* label) {
Condition c = testBigInt(cond, t);
ma_b(label, c);
}
void MacroAssembler::branchTestBigIntTruthy(bool truthy, const ValueOperand& value, Label* label) {
Condition c = testBigIntTruthy(truthy, value);
ma_b(label, c);
}
void
MacroAssembler::branchTestNull(Condition cond, Register tag, Label* label)
{

View file

@ -2717,6 +2717,11 @@ MacroAssemblerARMCompat::testSymbol(Assembler::Condition cond, const ValueOperan
return testSymbol(cond, value.typeReg());
}
Assembler::Condition MacroAssemblerARMCompat::testBigInt(Assembler::Condition cond, const ValueOperand& value)
{
return testBigInt(cond, value.typeReg());
}
Assembler::Condition
MacroAssemblerARMCompat::testObject(Assembler::Condition cond, const ValueOperand& value)
{
@ -2790,6 +2795,13 @@ MacroAssemblerARMCompat::testSymbol(Assembler::Condition cond, Register tag)
return cond;
}
Assembler::Condition MacroAssemblerARMCompat::testBigInt(Assembler::Condition cond, Register tag)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
ma_cmp(tag, ImmTag(JSVAL_TAG_BIGINT));
return cond;
}
Assembler::Condition
MacroAssemblerARMCompat::testObject(Assembler::Condition cond, Register tag)
{
@ -2907,6 +2919,14 @@ MacroAssemblerARMCompat::testObject(Condition cond, const Address& address)
return testObject(cond, scratch);
}
Assembler::Condition MacroAssemblerARMCompat::testBigInt(Condition cond, const Address& address)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
ScratchRegisterScope scratch(asMasm());
Register tag = extractTag(address, scratch);
return testBigInt(cond, tag);
}
Assembler::Condition
MacroAssemblerARMCompat::testNumber(Condition cond, const Address& address)
{
@ -2993,6 +3013,16 @@ MacroAssemblerARMCompat::testInt32(Condition cond, const BaseIndex& src)
return cond;
}
+Assembler::Condition
MacroAssemblerARMCompat::testBigInt(Condition cond,const BaseIndex& src)
{
MOZ_ASSERT(cond == Equal || cond == NotEqual);
ScratchRegisterScope scratch(asMasm());
Register tag = extractTag(src, scratch);
ma_cmp(tag, ImmTag(JSVAL_TAG_BIGINT));
return cond;
}
Assembler::Condition
MacroAssemblerARMCompat::testObject(Condition cond, const BaseIndex& src)
{
@ -3736,6 +3766,19 @@ MacroAssemblerARMCompat::testStringTruthy(bool truthy, const ValueOperand& value
return truthy ? Assembler::NotEqual : Assembler::Equal;
}
+Assembler::Condition
MacroAssemblerARMCompat::testBigIntTruthy(bool truthy, const ValueOperand& value)
{
Register bi = value.payloadReg();
ScratchRegisterScope scratch(asMasm());
SecondScratchRegisterScope scratch2(asMasm());
ma_dtr(IsLoad, bi, Imm32(BigInt::offsetOfLengthSignAndReservedBits()),
scratch, scratch2);
as_cmp(scratch, Imm8(0));
return truthy ? Assembler::NotEqual : Assembler::Equal;
}
void
MacroAssemblerARMCompat::floor(FloatRegister input, Register output, Label* bail)
{

View file

@ -695,6 +695,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
Condition testUndefined(Condition cond, const ValueOperand& value);
Condition testString(Condition cond, const ValueOperand& value);
Condition testSymbol(Condition cond, const ValueOperand& value);
Condition testBigInt(Condition cond, const ValueOperand& value);
Condition testObject(Condition cond, const ValueOperand& value);
Condition testNumber(Condition cond, const ValueOperand& value);
Condition testMagic(Condition cond, const ValueOperand& value);
@ -708,6 +709,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
Condition testUndefined(Condition cond, Register tag);
Condition testString(Condition cond, Register tag);
Condition testSymbol(Condition cond, Register tag);
Condition testBigInt(Condition cond, Register tag);
Condition testObject(Condition cond, Register tag);
Condition testDouble(Condition cond, Register tag);
Condition testNumber(Condition cond, Register tag);
@ -723,6 +725,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
Condition testUndefined(Condition cond, const Address& address);
Condition testString(Condition cond, const Address& address);
Condition testSymbol(Condition cond, const Address& address);
Condition testBigInt(Condition cond, const Address& address);
Condition testObject(Condition cond, const Address& address);
Condition testNumber(Condition cond, const Address& address);
@ -731,6 +734,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
Condition testBoolean(Condition cond, const BaseIndex& src);
Condition testString(Condition cond, const BaseIndex& src);
Condition testSymbol(Condition cond, const BaseIndex& src);
Condition testBigInt(Condition cond, const BaseIndex& src);
Condition testInt32(Condition cond, const BaseIndex& src);
Condition testObject(Condition cond, const BaseIndex& src);
Condition testDouble(Condition cond, const BaseIndex& src);
@ -749,6 +753,8 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
void unboxString(const Address& src, Register dest) { unboxNonDouble(src, dest); }
void unboxSymbol(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxSymbol(const Address& src, Register dest) { unboxNonDouble(src, dest); }
void unboxBigInt(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxBigInt(const Address& src, Register dest) { unboxNonDouble(src, dest); }
void unboxObject(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxObject(const Address& src, Register dest) { unboxNonDouble(src, dest); }
void unboxObject(const BaseIndex& src, Register dest) { unboxNonDouble(src, dest); }
@ -797,6 +803,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
Condition testBooleanTruthy(bool truthy, const ValueOperand& operand);
Condition testDoubleTruthy(bool truthy, FloatRegister reg);
Condition testStringTruthy(bool truthy, const ValueOperand& value);
Condition testBigIntTruthy(bool truthy, const ValueOperand& value);
void boolValueToFloat32(const ValueOperand& operand, FloatRegister dest);
void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest);

View file

@ -963,6 +963,19 @@ MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value, Labe
branchTestSymbol(cond, value.typeReg(), label);
}
void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value, Label* label)
{
branchTestBigInt(cond, value.typeReg(), label);
}
void MacroAssembler::branchTestBigIntTruthy(bool b, const ValueOperand& value, Label* label)
{
Register bi = value.payloadReg();
SecondScratchRegisterScope scratch2(*this);
ma_lw(scratch2, Address(bi, BigInt::offsetOfLengthSignAndReservedBits()));
ma_b(scratch2, Imm32(0), label, b ? NotEqual : Equal);
}
void
MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value, Label* label)
{

View file

@ -196,6 +196,9 @@ CodeGeneratorMIPS64::visitUnbox(LUnbox* unbox)
case MIRType::Symbol:
masm.unboxSymbol(inputReg, result);
break;
case MIRType::BigInt:
masm.unboxBigInt(inputReg, result);
break;
default:
MOZ_CRASH("Given MIRType cannot be unboxed.");
}
@ -219,6 +222,9 @@ CodeGeneratorMIPS64::visitUnbox(LUnbox* unbox)
case MIRType::Symbol:
masm.unboxSymbol(inputAddr, result);
break;
case MIRType::BigInt:
masm.unboxBigInt(inputAddr, result);
break;
default:
MOZ_CRASH("Given MIRType cannot be unboxed.");
}

View file

@ -622,6 +622,21 @@ MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value, Labe
branchTestSymbol(cond, scratch2, label);
}
void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value, Label* label)
{
SecondScratchRegisterScope scratch2(*this);
splitTag(value, scratch2);
branchTestBigInt(cond, scratch2, label);
}
void MacroAssembler::branchTestBigIntTruthy(bool b, const ValueOperand& value, Label* label)
{
SecondScratchRegisterScope scratch2(*this);
unboxBigInt(value, scratch2);
loadPtr(Address(scratch2, BigInt::offsetOfLengthSignAndReservedBits()), scratch2);
ma_b(scratch2, ImmWord(0), label, b ? NotEqual : Equal);
}
void
MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value, Label* label)
{

View file

@ -1495,6 +1495,21 @@ MacroAssemblerMIPS64Compat::unboxSymbol(Register src, Register dest)
ma_dext(dest, src, Imm32(0), Imm32(JSVAL_TAG_SHIFT));
}
void MacroAssemblerMIPS64Compat::unboxBigInt(const ValueOperand& operand, Register dest)
{
unboxNonDouble(operand, dest, JSVAL_TYPE_BIGINT);
}
void MacroAssemblerMIPS64Compat::unboxBigInt(Register src, Register dest)
{
unboxNonDouble(src, dest, JSVAL_TYPE_BIGINT);
}
void MacroAssemblerMIPS64Compat::unboxBigInt(const Address& src, Register dest)
{
unboxNonDouble(src, dest, JSVAL_TYPE_BIGINT);
}
void
MacroAssemblerMIPS64Compat::unboxSymbol(const Address& src, Register dest)
{

View file

@ -361,6 +361,9 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64
void unboxSymbol(const ValueOperand& src, Register dest);
void unboxSymbol(Register src, Register dest);
void unboxSymbol(const Address& src, Register dest);
void unboxBigInt(const ValueOperand& operand, Register dest);
void unboxBigInt(Register src, Register dest);
void unboxBigInt(const Address& src, Register dest);
void unboxObject(const ValueOperand& src, Register dest);
void unboxObject(Register src, Register dest);
void unboxObject(const Address& src, Register dest);

View file

@ -359,6 +359,7 @@ class MacroAssemblerNone : public Assembler
template <typename T> void unboxBoolean(T, Register) { MOZ_CRASH(); }
template <typename T> void unboxString(T, Register) { MOZ_CRASH(); }
template <typename T> void unboxSymbol(T, Register) { MOZ_CRASH(); }
template <typename T> void unboxBigInt(T, Register) { MOZ_CRASH(); }
template <typename T> void unboxObject(T, Register) { MOZ_CRASH(); }
template <typename T> void unboxDouble(T, FloatRegister) { MOZ_CRASH(); }
void unboxValue(const ValueOperand&, AnyRegister) { MOZ_CRASH(); }
@ -393,6 +394,7 @@ class MacroAssemblerNone : public Assembler
void loadConstantFloat32(wasm::RawF32, FloatRegister) { MOZ_CRASH(); }
Condition testInt32Truthy(bool, ValueOperand) { MOZ_CRASH(); }
Condition testStringTruthy(bool, ValueOperand) { MOZ_CRASH(); }
Condition testBigIntTruthy(bool, ValueOperand) { MOZ_CRASH(); }
template <typename T> void loadUnboxedValue(T, MIRType, AnyRegister) { MOZ_CRASH(); }
template <typename T> void storeUnboxedValue(const ConstantOrRegister&, MIRType, T, MIRType) { MOZ_CRASH(); }

View file

@ -431,6 +431,7 @@ CodeGeneratorShared::encodeAllocation(LSnapshot* snapshot, MDefinition* mir,
case MIRType::Int32:
case MIRType::String:
case MIRType::Symbol:
case MIRType::BigInt:
case MIRType::Object:
case MIRType::ObjectOrNull:
case MIRType::Boolean:

View file

@ -402,7 +402,8 @@ LIRGeneratorShared::redefine(MDefinition* def, MDefinition* as)
case MIRType::Object:
case MIRType::ObjectOrNull:
case MIRType::String:
case MIRType::Symbol: {
case MIRType::Symbol:
case MIRType::BigInt: {
LAssertResultT* check = new(alloc()) LAssertResultT(useRegister(def));
add(check, def->toInstruction());
break;

View file

@ -100,6 +100,9 @@ LIRGeneratorShared::visitConstant(MConstant* ins)
case MIRType::Symbol:
define(new(alloc()) LPointer(ins->toSymbol()), ins);
break;
case MIRType::BigInt:
define(new (alloc()) LPointer(ins->toBigInt()), ins);
break;
case MIRType::Object:
define(new(alloc()) LPointer(&ins->toObject()), ins);
break;

View file

@ -121,6 +121,9 @@ CodeGeneratorX64::visitUnbox(LUnbox* unbox)
case MIRType::Symbol:
cond = masm.testSymbol(Assembler::NotEqual, value);
break;
case MIRType::BigInt:
cond = masm.testBigInt(Assembler::NotEqual, value);
break;
default:
MOZ_CRASH("Given MIRType cannot be unboxed.");
}
@ -145,6 +148,9 @@ CodeGeneratorX64::visitUnbox(LUnbox* unbox)
case MIRType::Symbol:
masm.unboxSymbol(input, result);
break;
case MIRType::BigInt:
masm.unboxBigInt(input, result);
break;
default:
MOZ_CRASH("Given MIRType cannot be unboxed.");
}

View file

@ -231,6 +231,11 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
cmp32(tag, ImmTag(JSVAL_TAG_SYMBOL));
return cond;
}
Condition testBigInt(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmp32(tag, ImmTag(JSVAL_TAG_BIGINT));
return cond;
}
Condition testObject(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmp32(tag, ImmTag(JSVAL_TAG_OBJECT));
@ -306,6 +311,11 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
splitTag(src, scratch);
return testSymbol(cond, scratch);
}
Condition testBigInt(Condition cond, const ValueOperand& src) {
ScratchRegisterScope scratch(asMasm());
splitTag(src, scratch);
return testBigInt(cond, scratch);
}
Condition testObject(Condition cond, const ValueOperand& src) {
ScratchRegisterScope scratch(asMasm());
splitTag(src, scratch);
@ -359,6 +369,11 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
splitTag(src, scratch);
return testSymbol(cond, scratch);
}
Condition testBigInt(Condition cond, const Address& src) {
ScratchRegisterScope scratch(asMasm());
splitTag(src, scratch);
return testBigInt(cond, scratch);
}
Condition testObject(Condition cond, const Address& src) {
ScratchRegisterScope scratch(asMasm());
splitTag(src, scratch);
@ -406,6 +421,11 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
splitTag(src, scratch);
return testSymbol(cond, scratch);
}
Condition testBigInt(Condition cond, const BaseIndex& src) {
ScratchRegisterScope scratch(asMasm());
splitTag(src, scratch);
return testBigInt(cond, scratch);
}
Condition testInt32(Condition cond, const BaseIndex& src) {
ScratchRegisterScope scratch(asMasm());
splitTag(src, scratch);
@ -794,6 +814,9 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
void unboxSymbol(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxSymbol(const Operand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxBigInt(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxBigInt(const Operand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxObject(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxObject(const Operand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxObject(const Address& src, Register dest) { unboxNonDouble(Operand(src), dest); }
@ -894,6 +917,13 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
cmp32(Operand(scratch, JSString::offsetOfLength()), Imm32(0));
return truthy ? Assembler::NotEqual : Assembler::Equal;
}
Condition testBigIntTruthy(bool truthy, const ValueOperand& value) {
ScratchRegisterScope scratch(asMasm());
unboxBigInt(value, scratch);
cmpPtr(Operand(scratch, BigInt::offsetOfLengthSignAndReservedBits()),
ImmWord(0));
return truthy ? Assembler::NotEqual : Assembler::Equal;
}
template <typename T>
inline void loadInt32OrDouble(const T& src, FloatRegister dest);

View file

@ -944,6 +944,30 @@ MacroAssembler::branchTestSymbolImpl(Condition cond, const T& t, Label* label)
j(cond, label);
}
void MacroAssembler::branchTestBigInt(Condition cond, Register tag, Label* label) {
branchTestBigIntImpl(cond, tag, label);
}
void MacroAssembler::branchTestBigInt(Condition cond, const BaseIndex& address, Label* label) {
branchTestBigIntImpl(cond, address, label);
}
void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value, Label* label) {
branchTestBigIntImpl(cond, value, label);
}
template <typename T>
void MacroAssembler::branchTestBigIntImpl(Condition cond, const T& t, Label* label) {
cond = testBigInt(cond, t);
j(cond, label);
}
void MacroAssembler::branchTestBigIntTruthy(bool truthy, const ValueOperand& value, Label* label)
{
Condition cond = testBigIntTruthy(truthy, value);
j(cond, label);
}
void
MacroAssembler::branchTestNull(Condition cond, Register tag, Label* label)
{

View file

@ -294,6 +294,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
cmp32(tag, ImmTag(JSVAL_TAG_SYMBOL));
return cond;
}
Condition testBigInt(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmp32(tag, ImmTag(JSVAL_TAG_BIGINT));
return cond;
}
Condition testObject(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmp32(tag, ImmTag(JSVAL_TAG_OBJECT));
@ -410,6 +415,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
Condition testSymbol(Condition cond, const ValueOperand& value) {
return testSymbol(cond, value.typeReg());
}
Condition testBigInt(Condition cond, const ValueOperand& value) {
return testBigInt(cond, value.typeReg());
}
Condition testObject(Condition cond, const ValueOperand& value) {
return testObject(cond, value.typeReg());
}
@ -455,6 +463,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
cmp32(tagOf(address), ImmTag(JSVAL_TAG_SYMBOL));
return cond;
}
Condition testBigInt(Condition cond, const BaseIndex& address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmp32(tagOf(address), ImmTag(JSVAL_TAG_BIGINT));
return cond;
}
Condition testInt32(Condition cond, const BaseIndex& address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmp32(tagOf(address), ImmTag(JSVAL_TAG_INT32));
@ -696,6 +709,8 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
void unboxString(const Address& src, Register dest) { unboxNonDouble(src, dest); }
void unboxSymbol(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxSymbol(const Address& src, Register dest) { unboxNonDouble(src, dest); }
void unboxBigInt(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxBigInt(const Address& src, Register dest) { unboxNonDouble(src, dest); }
void unboxObject(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxObject(const Address& src, Register dest) { unboxNonDouble(src, dest); }
void unboxObject(const BaseIndex& src, Register dest) { unboxNonDouble(src, dest); }
@ -793,6 +808,12 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
cmp32(Operand(string, JSString::offsetOfLength()), Imm32(0));
return truthy ? Assembler::NotEqual : Assembler::Equal;
}
Condition testBigIntTruthy(bool truthy, const ValueOperand& value) {
Register bi = value.payloadReg();
cmpPtr(Operand(bi, BigInt::offsetOfLengthSignAndReservedBits()),
ImmWord(0));
return truthy ? Assembler::NotEqual : Assembler::Equal;
}
template <typename T>
inline void loadInt32OrDouble(const T& src, FloatRegister dest);

View file

@ -80,6 +80,11 @@ class BigInt final : public js::gc::TenuredCell {
bool isZero() const { return digitLength() == 0; }
bool isNegative() const { return lengthSignAndReservedBits_ & SignBit; }
// Offset for direct access from JIT code.
static constexpr size_t offsetOfLengthSignAndReservedBits() {
return offsetof(BigInt, lengthSignAndReservedBits_);
}
void initializeDigitsToZero();
void traceChildren(JSTracer* trc);

View file

@ -368,6 +368,8 @@ TypeSet::mightBeMIRType(jit::MIRType type) const
return baseFlags() & TYPE_FLAG_STRING;
case jit::MIRType::Symbol:
return baseFlags() & TYPE_FLAG_SYMBOL;
case jit::MIRType::BigInt:
return baseFlags() & TYPE_FLAG_BIGINT;
case jit::MIRType::MagicOptimizedArguments:
return baseFlags() & TYPE_FLAG_LAZYARGS;
case jit::MIRType::MagicHole:
@ -1635,6 +1637,8 @@ GetMIRTypeFromTypeFlags(TypeFlags flags)
return jit::MIRType::String;
case TYPE_FLAG_SYMBOL:
return jit::MIRType::Symbol;
case TYPE_FLAG_BIGINT:
return jit::MIRType::BigInt;
case TYPE_FLAG_LAZYARGS:
return jit::MIRType::MagicOptimizedArguments;
case TYPE_FLAG_ANYOBJECT: