mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-28 01:57:30 +09:00
Change inlining of intrinsics.
This commit is contained in:
parent
dca3b936bf
commit
8f16d02c34
16 changed files with 206 additions and 40 deletions
|
|
@ -711,13 +711,14 @@ function CreateArrayIterator(obj, kind) {
|
||||||
// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%.next
|
// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%.next
|
||||||
function ArrayIteratorNext() {
|
function ArrayIteratorNext() {
|
||||||
// Step 1-3.
|
// Step 1-3.
|
||||||
if (!IsObject(this) || !IsArrayIterator(this)) {
|
var obj;
|
||||||
|
if (!IsObject(this) || (obj = GuardToArrayIterator(this)) === null) {
|
||||||
return callFunction(CallArrayIteratorMethodIfWrapped, this,
|
return callFunction(CallArrayIteratorMethodIfWrapped, this,
|
||||||
"ArrayIteratorNext");
|
"ArrayIteratorNext");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4.
|
// Step 4.
|
||||||
var a = UnsafeGetReservedSlot(this, ITERATOR_SLOT_TARGET);
|
var a = UnsafeGetReservedSlot(obj, ITERATOR_SLOT_TARGET);
|
||||||
var result = { value: undefined, done: false };
|
var result = { value: undefined, done: false };
|
||||||
|
|
||||||
// Step 5.
|
// Step 5.
|
||||||
|
|
@ -728,10 +729,10 @@ function ArrayIteratorNext() {
|
||||||
|
|
||||||
// Step 6.
|
// Step 6.
|
||||||
// The index might not be an integer, so we have to do a generic get here.
|
// The index might not be an integer, so we have to do a generic get here.
|
||||||
var index = UnsafeGetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX);
|
var index = UnsafeGetReservedSlot(obj, ITERATOR_SLOT_NEXT_INDEX);
|
||||||
|
|
||||||
// Step 7.
|
// Step 7.
|
||||||
var itemKind = UnsafeGetInt32FromReservedSlot(this, ITERATOR_SLOT_ITEM_KIND);
|
var itemKind = UnsafeGetInt32FromReservedSlot(obj, ITERATOR_SLOT_ITEM_KIND);
|
||||||
|
|
||||||
// Step 8-9.
|
// Step 8-9.
|
||||||
var len = IsPossiblyWrappedTypedArray(a)
|
var len = IsPossiblyWrappedTypedArray(a)
|
||||||
|
|
@ -740,13 +741,13 @@ function ArrayIteratorNext() {
|
||||||
|
|
||||||
// Step 10.
|
// Step 10.
|
||||||
if (index >= len) {
|
if (index >= len) {
|
||||||
UnsafeSetReservedSlot(this, ITERATOR_SLOT_TARGET, null);
|
UnsafeSetReservedSlot(obj, ITERATOR_SLOT_TARGET, null);
|
||||||
result.done = true;
|
result.done = true;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 11.
|
// Step 11.
|
||||||
UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, index + 1);
|
UnsafeSetReservedSlot(obj, ITERATOR_SLOT_NEXT_INDEX, index + 1);
|
||||||
|
|
||||||
// Step 16.
|
// Step 16.
|
||||||
if (itemKind === ITEM_KIND_VALUE) {
|
if (itemKind === ITEM_KIND_VALUE) {
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,8 @@ function MapIteratorNext() {
|
||||||
var O = this;
|
var O = this;
|
||||||
|
|
||||||
// Steps 2-3.
|
// Steps 2-3.
|
||||||
if (!IsObject(O) || !IsMapIterator(O))
|
if (!IsObject(O) || (O = GuardToMapIterator(O)) === null)
|
||||||
return callFunction(CallMapIteratorMethodIfWrapped, O, "MapIteratorNext");
|
return callFunction(CallMapIteratorMethodIfWrapped, this, "MapIteratorNext");
|
||||||
|
|
||||||
// Steps 4-5 (implemented in _GetNextMapEntryForIterator).
|
// Steps 4-5 (implemented in _GetNextMapEntryForIterator).
|
||||||
// Steps 8-9 (omitted).
|
// Steps 8-9 (omitted).
|
||||||
|
|
@ -82,7 +82,7 @@ function MapIteratorNext() {
|
||||||
// Steps 10.b-c (omitted).
|
// Steps 10.b-c (omitted).
|
||||||
|
|
||||||
// Step 6.
|
// Step 6.
|
||||||
var itemKind = UnsafeGetInt32FromReservedSlot(this, ITERATOR_SLOT_ITEM_KIND);
|
var itemKind = UnsafeGetInt32FromReservedSlot(O, ITERATOR_SLOT_ITEM_KIND);
|
||||||
|
|
||||||
var result;
|
var result;
|
||||||
if (itemKind === ITEM_KIND_KEY) {
|
if (itemKind === ITEM_KIND_KEY) {
|
||||||
|
|
|
||||||
|
|
@ -64,8 +64,8 @@ function SetIteratorNext() {
|
||||||
var O = this;
|
var O = this;
|
||||||
|
|
||||||
// Steps 2-3.
|
// Steps 2-3.
|
||||||
if (!IsObject(O) || !IsSetIterator(O))
|
if (!IsObject(O) || (O = GuardToSetIterator(O)) === null)
|
||||||
return callFunction(CallSetIteratorMethodIfWrapped, O, "SetIteratorNext");
|
return callFunction(CallSetIteratorMethodIfWrapped, this, "SetIteratorNext");
|
||||||
|
|
||||||
// Steps 4-5 (implemented in _GetNextSetEntryForIterator).
|
// Steps 4-5 (implemented in _GetNextSetEntryForIterator).
|
||||||
// Steps 8-9 (omitted).
|
// Steps 8-9 (omitted).
|
||||||
|
|
@ -83,7 +83,7 @@ function SetIteratorNext() {
|
||||||
// Steps 10.b-c (omitted).
|
// Steps 10.b-c (omitted).
|
||||||
|
|
||||||
// Step 6.
|
// Step 6.
|
||||||
var itemKind = UnsafeGetInt32FromReservedSlot(this, ITERATOR_SLOT_ITEM_KIND);
|
var itemKind = UnsafeGetInt32FromReservedSlot(O, ITERATOR_SLOT_ITEM_KIND);
|
||||||
|
|
||||||
var result;
|
var result;
|
||||||
if (itemKind === ITEM_KIND_VALUE) {
|
if (itemKind === ITEM_KIND_VALUE) {
|
||||||
|
|
|
||||||
|
|
@ -529,16 +529,17 @@ function String_iterator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function StringIteratorNext() {
|
function StringIteratorNext() {
|
||||||
if (!IsObject(this) || !IsStringIterator(this)) {
|
var obj;
|
||||||
|
if (!IsObject(this) || (obj = GuardToStringIterator(this)) === null) {
|
||||||
return callFunction(CallStringIteratorMethodIfWrapped, this,
|
return callFunction(CallStringIteratorMethodIfWrapped, this,
|
||||||
"StringIteratorNext");
|
"StringIteratorNext");
|
||||||
}
|
}
|
||||||
|
|
||||||
var S = UnsafeGetStringFromReservedSlot(this, ITERATOR_SLOT_TARGET);
|
var S = UnsafeGetStringFromReservedSlot(obj, ITERATOR_SLOT_TARGET);
|
||||||
// We know that JSString::MAX_LENGTH <= INT32_MAX (and assert this in
|
// We know that JSString::MAX_LENGTH <= INT32_MAX (and assert this in
|
||||||
// SelfHostring.cpp) so our current index can never be anything other than
|
// SelfHostring.cpp) so our current index can never be anything other than
|
||||||
// an Int32Value.
|
// an Int32Value.
|
||||||
var index = UnsafeGetInt32FromReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX);
|
var index = UnsafeGetInt32FromReservedSlot(obj, ITERATOR_SLOT_NEXT_INDEX);
|
||||||
var size = S.length;
|
var size = S.length;
|
||||||
var result = { value: undefined, done: false };
|
var result = { value: undefined, done: false };
|
||||||
|
|
||||||
|
|
@ -556,7 +557,7 @@ function StringIteratorNext() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, index + charCount);
|
UnsafeSetReservedSlot(obj, ITERATOR_SLOT_NEXT_INDEX, index + charCount);
|
||||||
result.value = callFunction(String_substring, S, index, index + charCount);
|
result.value = callFunction(String_substring, S, index, index + charCount);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -11528,6 +11528,32 @@ CodeGenerator::visitHasClass(LHasClass* ins)
|
||||||
masm.cmpPtrSet(Assembler::Equal, output, ImmPtr(ins->mir()->getClass()), output);
|
masm.cmpPtrSet(Assembler::Equal, output, ImmPtr(ins->mir()->getClass()), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CodeGenerator::visitGuardToClass(LGuardToClass* ins)
|
||||||
|
{
|
||||||
|
Register lhs = ToRegister(ins->lhs());
|
||||||
|
Register output = ToRegister(ins->output());
|
||||||
|
Register temp = ToRegister(ins->temp());
|
||||||
|
|
||||||
|
Label notEqual;
|
||||||
|
|
||||||
|
masm.branchTestObjClass(Assembler::NotEqual, lhs, temp, ins->mir()->getClass(), ¬Equal);
|
||||||
|
masm.mov(lhs, output);
|
||||||
|
|
||||||
|
if (ins->mir()->type() == MIRType::Object) {
|
||||||
|
// Can't return null-return here, so bail
|
||||||
|
bailoutFrom(¬Equal, ins->snapshot());
|
||||||
|
} else {
|
||||||
|
Label done;
|
||||||
|
masm.jump(&done);
|
||||||
|
|
||||||
|
masm.bind(¬Equal);
|
||||||
|
masm.mov(ImmPtr(0), output);
|
||||||
|
|
||||||
|
masm.bind(&done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CodeGenerator::visitWasmParameter(LWasmParameter* lir)
|
CodeGenerator::visitWasmParameter(LWasmParameter* lir)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -377,6 +377,7 @@ class CodeGenerator final : public CodeGeneratorSpecific
|
||||||
void visitIsObject(LIsObject* lir);
|
void visitIsObject(LIsObject* lir);
|
||||||
void visitIsObjectAndBranch(LIsObjectAndBranch* lir);
|
void visitIsObjectAndBranch(LIsObjectAndBranch* lir);
|
||||||
void visitHasClass(LHasClass* lir);
|
void visitHasClass(LHasClass* lir);
|
||||||
|
void visitGuardToClass(LGuardToClass* lir);
|
||||||
void visitWasmParameter(LWasmParameter* lir);
|
void visitWasmParameter(LWasmParameter* lir);
|
||||||
void visitWasmParameterI64(LWasmParameterI64* lir);
|
void visitWasmParameterI64(LWasmParameterI64* lir);
|
||||||
void visitWasmReturn(LWasmReturn* ret);
|
void visitWasmReturn(LWasmReturn* ret);
|
||||||
|
|
|
||||||
|
|
@ -117,14 +117,16 @@
|
||||||
_(IntrinsicDefineDataProperty) \
|
_(IntrinsicDefineDataProperty) \
|
||||||
_(IntrinsicObjectHasPrototype) \
|
_(IntrinsicObjectHasPrototype) \
|
||||||
\
|
\
|
||||||
_(IntrinsicIsArrayIterator) \
|
_(IntrinsicGuardToArrayIterator) \
|
||||||
_(IntrinsicIsMapIterator) \
|
_(IntrinsicGuardToMapIterator) \
|
||||||
_(IntrinsicIsSetIterator) \
|
_(IntrinsicGuardToSetIterator) \
|
||||||
_(IntrinsicIsStringIterator) \
|
|
||||||
_(IntrinsicIsListIterator) \
|
_(IntrinsicIsListIterator) \
|
||||||
|
_(IntrinsicGuardToStringIterator) \
|
||||||
\
|
\
|
||||||
|
_(IntrinsicGuardToMapObject) \
|
||||||
_(IntrinsicGetNextMapEntryForIterator) \
|
_(IntrinsicGetNextMapEntryForIterator) \
|
||||||
\
|
\
|
||||||
|
_(IntrinsicGuardToSetObject) \
|
||||||
_(IntrinsicGetNextSetEntryForIterator) \
|
_(IntrinsicGetNextSetEntryForIterator) \
|
||||||
\
|
\
|
||||||
_(IntrinsicArrayBufferByteLength) \
|
_(IntrinsicArrayBufferByteLength) \
|
||||||
|
|
|
||||||
|
|
@ -969,6 +969,7 @@ class IonBuilder
|
||||||
const Class* clasp2 = nullptr,
|
const Class* clasp2 = nullptr,
|
||||||
const Class* clasp3 = nullptr,
|
const Class* clasp3 = nullptr,
|
||||||
const Class* clasp4 = nullptr);
|
const Class* clasp4 = nullptr);
|
||||||
|
InliningStatus inlineGuardToClass(CallInfo& callInfo, const Class* clasp);
|
||||||
InliningStatus inlineIsConstructing(CallInfo& callInfo);
|
InliningStatus inlineIsConstructing(CallInfo& callInfo);
|
||||||
InliningStatus inlineSubstringKernel(CallInfo& callInfo);
|
InliningStatus inlineSubstringKernel(CallInfo& callInfo);
|
||||||
InliningStatus inlineObjectHasPrototype(CallInfo& callInfo);
|
InliningStatus inlineObjectHasPrototype(CallInfo& callInfo);
|
||||||
|
|
|
||||||
|
|
@ -4170,6 +4170,16 @@ LIRGenerator::visitHasClass(MHasClass* ins)
|
||||||
define(new(alloc()) LHasClass(useRegister(ins->object())), ins);
|
define(new(alloc()) LHasClass(useRegister(ins->object())), ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LIRGenerator::visitGuardToClass(MGuardToClass* ins)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
|
||||||
|
MOZ_ASSERT(ins->type() == MIRType::ObjectOrNull|| ins->type() == MIRType::Object);
|
||||||
|
LGuardToClass* lir = new(alloc()) LGuardToClass(useRegister(ins->object()), temp());
|
||||||
|
assignSnapshot(lir, Bailout_TypeBarrierO);
|
||||||
|
define(lir, ins);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LIRGenerator::visitWasmAddOffset(MWasmAddOffset* ins)
|
LIRGenerator::visitWasmAddOffset(MWasmAddOffset* ins)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -289,6 +289,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||||
void visitIsConstructor(MIsConstructor* ins);
|
void visitIsConstructor(MIsConstructor* ins);
|
||||||
void visitIsObject(MIsObject* ins);
|
void visitIsObject(MIsObject* ins);
|
||||||
void visitHasClass(MHasClass* ins);
|
void visitHasClass(MHasClass* ins);
|
||||||
|
void visitGuardToClass(MGuardToClass* ins);
|
||||||
void visitWasmAddOffset(MWasmAddOffset* ins);
|
void visitWasmAddOffset(MWasmAddOffset* ins);
|
||||||
void visitWasmBoundsCheck(MWasmBoundsCheck* ins);
|
void visitWasmBoundsCheck(MWasmBoundsCheck* ins);
|
||||||
void visitWasmLoadGlobalVar(MWasmLoadGlobalVar* ins);
|
void visitWasmLoadGlobalVar(MWasmLoadGlobalVar* ins);
|
||||||
|
|
|
||||||
|
|
@ -280,14 +280,14 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
|
||||||
return inlineIsConstructing(callInfo);
|
return inlineIsConstructing(callInfo);
|
||||||
case InlinableNative::IntrinsicSubstringKernel:
|
case InlinableNative::IntrinsicSubstringKernel:
|
||||||
return inlineSubstringKernel(callInfo);
|
return inlineSubstringKernel(callInfo);
|
||||||
case InlinableNative::IntrinsicIsArrayIterator:
|
case InlinableNative::IntrinsicGuardToArrayIterator:
|
||||||
return inlineHasClass(callInfo, &ArrayIteratorObject::class_);
|
return inlineGuardToClass(callInfo, &ArrayIteratorObject::class_);
|
||||||
case InlinableNative::IntrinsicIsMapIterator:
|
case InlinableNative::IntrinsicGuardToMapIterator:
|
||||||
return inlineHasClass(callInfo, &MapIteratorObject::class_);
|
return inlineGuardToClass(callInfo, &MapIteratorObject::class_);
|
||||||
case InlinableNative::IntrinsicIsSetIterator:
|
case InlinableNative::IntrinsicGuardToSetIterator:
|
||||||
return inlineHasClass(callInfo, &SetIteratorObject::class_);
|
return inlineGuardToClass(callInfo, &SetIteratorObject::class_);
|
||||||
case InlinableNative::IntrinsicIsStringIterator:
|
case InlinableNative::IntrinsicGuardToStringIterator:
|
||||||
return inlineHasClass(callInfo, &StringIteratorObject::class_);
|
return inlineGuardToClass(callInfo, &StringIteratorObject::class_);
|
||||||
case InlinableNative::IntrinsicIsListIterator:
|
case InlinableNative::IntrinsicIsListIterator:
|
||||||
return inlineHasClass(callInfo, &ListIteratorObject::class_);
|
return inlineHasClass(callInfo, &ListIteratorObject::class_);
|
||||||
case InlinableNative::IntrinsicDefineDataProperty:
|
case InlinableNative::IntrinsicDefineDataProperty:
|
||||||
|
|
@ -296,10 +296,14 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
|
||||||
return inlineObjectHasPrototype(callInfo);
|
return inlineObjectHasPrototype(callInfo);
|
||||||
|
|
||||||
// Map intrinsics.
|
// Map intrinsics.
|
||||||
|
case InlinableNative::IntrinsicGuardToMapObject:
|
||||||
|
return inlineGuardToClass(callInfo, &MapObject::class_);
|
||||||
case InlinableNative::IntrinsicGetNextMapEntryForIterator:
|
case InlinableNative::IntrinsicGetNextMapEntryForIterator:
|
||||||
return inlineGetNextEntryForIterator(callInfo, MGetNextEntryForIterator::Map);
|
return inlineGetNextEntryForIterator(callInfo, MGetNextEntryForIterator::Map);
|
||||||
|
|
||||||
// Set intrinsics.
|
// Set intrinsics.
|
||||||
|
case InlinableNative::IntrinsicGuardToSetObject:
|
||||||
|
return inlineGuardToClass(callInfo, &SetObject::class_);
|
||||||
case InlinableNative::IntrinsicGetNextSetEntryForIterator:
|
case InlinableNative::IntrinsicGetNextSetEntryForIterator:
|
||||||
return inlineGetNextEntryForIterator(callInfo, MGetNextEntryForIterator::Set);
|
return inlineGetNextEntryForIterator(callInfo, MGetNextEntryForIterator::Set);
|
||||||
|
|
||||||
|
|
@ -2219,6 +2223,37 @@ IonBuilder::inlineHasClass(CallInfo& callInfo,
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IonBuilder::InliningStatus
|
||||||
|
IonBuilder::inlineGuardToClass(CallInfo& callInfo, const Class* clasp)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!callInfo.constructing());
|
||||||
|
MOZ_ASSERT(callInfo.argc() == 1);
|
||||||
|
|
||||||
|
if (callInfo.getArg(0)->type() != MIRType::Object)
|
||||||
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
|
if (getInlineReturnType() != MIRType::ObjectOrNull &&
|
||||||
|
getInlineReturnType() != MIRType::Object)
|
||||||
|
{
|
||||||
|
return InliningStatus_NotInlined;
|
||||||
|
}
|
||||||
|
|
||||||
|
TemporaryTypeSet* types = callInfo.getArg(0)->resultTypeSet();
|
||||||
|
const Class* knownClass = types ? types->getKnownClass(constraints()) : nullptr;
|
||||||
|
|
||||||
|
if (knownClass && knownClass == clasp) {
|
||||||
|
current->push(callInfo.getArg(0));
|
||||||
|
} else {
|
||||||
|
MGuardToClass* guardToClass = MGuardToClass::New(alloc(), callInfo.getArg(0),
|
||||||
|
clasp, getInlineReturnType());
|
||||||
|
current->add(guardToClass);
|
||||||
|
current->push(guardToClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
callInfo.setImplicitlyUsedUnchecked();
|
||||||
|
return InliningStatus_Inlined;
|
||||||
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineGetNextEntryForIterator(CallInfo& callInfo, MGetNextEntryForIterator::Mode mode)
|
IonBuilder::inlineGetNextEntryForIterator(CallInfo& callInfo, MGetNextEntryForIterator::Mode mode)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13192,6 +13192,48 @@ class MHasClass
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MGuardToClass
|
||||||
|
: public MUnaryInstruction,
|
||||||
|
public SingleObjectPolicy::Data
|
||||||
|
{
|
||||||
|
const Class* class_;
|
||||||
|
|
||||||
|
MGuardToClass(MDefinition* object, const Class* clasp, MIRType resultType)
|
||||||
|
: MUnaryInstruction(object)
|
||||||
|
, class_(clasp)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(object->type() == MIRType::Object ||
|
||||||
|
(object->type() == MIRType::Value && object->mightBeType(MIRType::Object)));
|
||||||
|
MOZ_ASSERT(resultType == MIRType::Object || resultType == MIRType::ObjectOrNull);
|
||||||
|
setResultType(resultType);
|
||||||
|
setMovable();
|
||||||
|
if (resultType == MIRType::Object) {
|
||||||
|
// We will bail out if the class type is incorrect,
|
||||||
|
// so we need to ensure we don't eliminate this instruction
|
||||||
|
setGuard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
INSTRUCTION_HEADER(GuardToClass)
|
||||||
|
TRIVIAL_NEW_WRAPPERS
|
||||||
|
NAMED_OPERANDS((0, object))
|
||||||
|
|
||||||
|
const Class* getClass() const {
|
||||||
|
return class_;
|
||||||
|
}
|
||||||
|
AliasSet getAliasSet() const override {
|
||||||
|
return AliasSet::None();
|
||||||
|
}
|
||||||
|
bool congruentTo(const MDefinition* ins) const override {
|
||||||
|
if (!ins->isGuardToClass())
|
||||||
|
return false;
|
||||||
|
if (getClass() != ins->toGuardToClass()->getClass())
|
||||||
|
return false;
|
||||||
|
return congruentIfOperandsEqual(ins);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class MCheckReturn
|
class MCheckReturn
|
||||||
: public MBinaryInstruction,
|
: public MBinaryInstruction,
|
||||||
public BoxInputsPolicy::Data
|
public BoxInputsPolicy::Data
|
||||||
|
|
|
||||||
|
|
@ -272,6 +272,7 @@ namespace jit {
|
||||||
_(IsCallable) \
|
_(IsCallable) \
|
||||||
_(IsObject) \
|
_(IsObject) \
|
||||||
_(HasClass) \
|
_(HasClass) \
|
||||||
|
_(GuardToClass) \
|
||||||
_(CopySign) \
|
_(CopySign) \
|
||||||
_(Rotate) \
|
_(Rotate) \
|
||||||
_(NewDerivedTypedObject) \
|
_(NewDerivedTypedObject) \
|
||||||
|
|
|
||||||
|
|
@ -7867,6 +7867,29 @@ class LHasClass : public LInstructionHelper<1, 1, 0>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LGuardToClass : public LInstructionHelper<1, 1, 1>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LIR_HEADER(GuardToClass);
|
||||||
|
explicit LGuardToClass(const LAllocation& lhs, const LDefinition& temp)
|
||||||
|
{
|
||||||
|
setOperand(0, lhs);
|
||||||
|
setTemp(0, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
const LAllocation* lhs() {
|
||||||
|
return getOperand(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const LDefinition* temp() {
|
||||||
|
return getTemp(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
MGuardToClass* mir() const {
|
||||||
|
return mir_->toGuardToClass();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<size_t Defs, size_t Ops>
|
template<size_t Defs, size_t Ops>
|
||||||
class LWasmSelectBase : public LInstructionHelper<Defs, Ops, 0>
|
class LWasmSelectBase : public LInstructionHelper<Defs, Ops, 0>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -386,6 +386,7 @@
|
||||||
_(IsObject) \
|
_(IsObject) \
|
||||||
_(IsObjectAndBranch) \
|
_(IsObjectAndBranch) \
|
||||||
_(HasClass) \
|
_(HasClass) \
|
||||||
|
_(GuardToClass) \
|
||||||
_(RecompileCheck) \
|
_(RecompileCheck) \
|
||||||
_(MemoryBarrier) \
|
_(MemoryBarrier) \
|
||||||
_(AssertRangeI) \
|
_(AssertRangeI) \
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,22 @@ intrinsic_IsInstanceOfBuiltin(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static bool
|
||||||
|
intrinsic_GuardToBuiltin(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
{
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
MOZ_ASSERT(args.length() == 1);
|
||||||
|
MOZ_ASSERT(args[0].isObject());
|
||||||
|
|
||||||
|
if (args[0].toObject().is<T>()) {
|
||||||
|
args.rval().setObject(args[0].toObject());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
args.rval().setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Self-hosting intrinsic returning the original constructor for a builtin
|
* Self-hosting intrinsic returning the original constructor for a builtin
|
||||||
* the name of which is the first and only argument.
|
* the name of which is the first and only argument.
|
||||||
|
|
@ -2297,18 +2313,18 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||||
|
|
||||||
JS_FN("_SetCanonicalName", intrinsic_SetCanonicalName, 2,0),
|
JS_FN("_SetCanonicalName", intrinsic_SetCanonicalName, 2,0),
|
||||||
|
|
||||||
JS_INLINABLE_FN("IsArrayIterator",
|
JS_INLINABLE_FN("GuardToArrayIterator",
|
||||||
intrinsic_IsInstanceOfBuiltin<ArrayIteratorObject>, 1,0,
|
intrinsic_GuardToBuiltin<ArrayIteratorObject>, 1,0,
|
||||||
IntrinsicIsArrayIterator),
|
IntrinsicGuardToArrayIterator),
|
||||||
JS_INLINABLE_FN("IsMapIterator",
|
JS_INLINABLE_FN("GuardToMapIterator",
|
||||||
intrinsic_IsInstanceOfBuiltin<MapIteratorObject>, 1,0,
|
intrinsic_GuardToBuiltin<MapIteratorObject>, 1,0,
|
||||||
IntrinsicIsMapIterator),
|
IntrinsicGuardToMapIterator),
|
||||||
JS_INLINABLE_FN("IsSetIterator",
|
JS_INLINABLE_FN("GuardToSetIterator",
|
||||||
intrinsic_IsInstanceOfBuiltin<SetIteratorObject>, 1,0,
|
intrinsic_GuardToBuiltin<SetIteratorObject>, 1,0,
|
||||||
IntrinsicIsSetIterator),
|
IntrinsicGuardToSetIterator),
|
||||||
JS_INLINABLE_FN("IsStringIterator",
|
JS_INLINABLE_FN("GuardToStringIterator",
|
||||||
intrinsic_IsInstanceOfBuiltin<StringIteratorObject>, 1,0,
|
intrinsic_GuardToBuiltin<StringIteratorObject>, 1,0,
|
||||||
IntrinsicIsStringIterator),
|
IntrinsicGuardToStringIterator),
|
||||||
JS_INLINABLE_FN("IsListIterator",
|
JS_INLINABLE_FN("IsListIterator",
|
||||||
intrinsic_IsInstanceOfBuiltin<ListIteratorObject>, 1,0,
|
intrinsic_IsInstanceOfBuiltin<ListIteratorObject>, 1,0,
|
||||||
IntrinsicIsListIterator),
|
IntrinsicIsListIterator),
|
||||||
|
|
@ -2412,7 +2428,12 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||||
JS_FN("CallStarGeneratorMethodIfWrapped",
|
JS_FN("CallStarGeneratorMethodIfWrapped",
|
||||||
CallNonGenericSelfhostedMethod<Is<StarGeneratorObject>>, 2, 0),
|
CallNonGenericSelfhostedMethod<Is<StarGeneratorObject>>, 2, 0),
|
||||||
|
|
||||||
|
JS_INLINABLE_FN("GuardToMapObject", intrinsic_GuardToBuiltin<MapObject>, 1, 0,
|
||||||
|
IntrinsicGuardToMapObject),
|
||||||
JS_FN("IsWeakSet", intrinsic_IsInstanceOfBuiltin<WeakSetObject>, 1,0),
|
JS_FN("IsWeakSet", intrinsic_IsInstanceOfBuiltin<WeakSetObject>, 1,0),
|
||||||
|
|
||||||
|
JS_INLINABLE_FN("GuardToSetObject", intrinsic_GuardToBuiltin<SetObject>, 1, 0,
|
||||||
|
IntrinsicGuardToSetObject),
|
||||||
JS_FN("CallWeakSetMethodIfWrapped",
|
JS_FN("CallWeakSetMethodIfWrapped",
|
||||||
CallNonGenericSelfhostedMethod<Is<WeakSetObject>>, 2, 0),
|
CallNonGenericSelfhostedMethod<Is<WeakSetObject>>, 2, 0),
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue