Bug 1337773 - Use IonInIC for MIn and rename to MInCache
MozReview-Commit-ID: 2Nl70H4MpPa
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -11201,26 +11201,28 @@ CodeGenerator::visitClampVToUint8(LClamp
Label fails;
masm.clampValueToUint8(operand, input,
stringEntry, stringRejoin,
output, tempFloat, output, &fails);
bailoutFrom(&fails, lir->snapshot());
}
-typedef bool (*OperatorInFn)(JSContext*, HandleValue, HandleObject, bool*);
-static const VMFunction OperatorInInfo = FunctionInfo<OperatorInFn>(OperatorIn, "OperatorIn");
-
-void
-CodeGenerator::visitIn(LIn* ins)
-{
- pushArg(ToRegister(ins->rhs()));
- pushArg(ToValue(ins, LIn::LHS));
-
- callVM(OperatorInInfo, ins);
+void
+CodeGenerator::visitInCache(LInCache* ins)
+{
+ LiveRegisterSet liveRegs = ins->safepoint()->liveRegs();
+
+ ConstantOrRegister key = toConstantOrRegister(ins, LInCache::LHS, ins->mir()->key()->type());
+ Register object = ToRegister(ins->rhs());
+ Register output = ToRegister(ins->output());
+ Register temp = ToRegister(ins->temp());
+
+ IonInIC cache(liveRegs, key, object, output, temp);
+ addIC(ins, allocateIC(cache));
}
typedef bool (*OperatorInIFn)(JSContext*, uint32_t, HandleObject, bool*);
static const VMFunction OperatorInIInfo = FunctionInfo<OperatorInIFn>(OperatorInI, "OperatorInI");
void
CodeGenerator::visitInArray(LInArray* lir)
{
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -353,17 +353,17 @@ class CodeGenerator final : public CodeG
JSObject* templateObject, bool saveAndRestore, Register resultreg);
void visitRest(LRest* lir);
void visitCallSetProperty(LCallSetProperty* ins);
void visitCallDeleteProperty(LCallDeleteProperty* lir);
void visitCallDeleteElement(LCallDeleteElement* lir);
void visitBitNotV(LBitNotV* lir);
void visitBitOpV(LBitOpV* lir);
void emitInstanceOf(LInstruction* ins, JSObject* prototypeObject);
- void visitIn(LIn* ins);
+ void visitInCache(LInCache* ins);
void visitInArray(LInArray* ins);
void visitInstanceOfO(LInstanceOfO* ins);
void visitInstanceOfV(LInstanceOfV* ins);
void visitCallInstanceOf(LCallInstanceOf* ins);
void visitGetDOMProperty(LGetDOMProperty* lir);
void visitGetDOMMemberV(LGetDOMMemberV* lir);
void visitGetDOMMemberT(LGetDOMMemberT* lir);
void visitSetDOMProperty(LSetDOMProperty* lir);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -12595,27 +12595,29 @@ IonBuilder::jsop_setaliasedvar(Environme
}
AbortReasonOr<Ok>
IonBuilder::jsop_in()
{
MDefinition* obj = convertUnboxedObjects(current->pop());
MDefinition* id = current->pop();
- bool emitted = false;
-
- MOZ_TRY(inTryDense(&emitted, obj, id));
- if (emitted)
- return Ok();
-
- MOZ_TRY(hasTryNotDefined(&emitted, obj, id, /* ownProperty = */ false));
- if (emitted)
- return Ok();
-
- MIn* ins = MIn::New(alloc(), id, obj);
+ if (!forceInlineCaches()) {
+ bool emitted = false;
+
+ MOZ_TRY(inTryDense(&emitted, obj, id));
+ if (emitted)
+ return Ok();
+
+ MOZ_TRY(hasTryNotDefined(&emitted, obj, id, /* ownProperty = */ false));
+ if (emitted)
+ return Ok();
+ }
+
+ MInCache* ins = MInCache::New(alloc(), id, obj);
current->add(ins);
current->push(ins);
return resumeAfter(ins);
}
AbortReasonOr<Ok>
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -4181,26 +4181,29 @@ LIRGenerator::visitThrow(MThrow* ins)
MOZ_ASSERT(value->type() == MIRType::Value);
LThrow* lir = new(alloc()) LThrow(useBoxAtStart(value));
add(lir, ins);
assignSafepoint(lir, ins);
}
void
-LIRGenerator::visitIn(MIn* ins)
+LIRGenerator::visitInCache(MInCache* ins)
{
MDefinition* lhs = ins->lhs();
MDefinition* rhs = ins->rhs();
- MOZ_ASSERT(lhs->type() == MIRType::Value);
+ MOZ_ASSERT(lhs->type() == MIRType::String ||
+ lhs->type() == MIRType::Symbol ||
+ lhs->type() == MIRType::Int32 ||
+ lhs->type() == MIRType::Value);
MOZ_ASSERT(rhs->type() == MIRType::Object);
- LIn* lir = new(alloc()) LIn(useBoxAtStart(lhs), useRegisterAtStart(rhs));
- defineReturn(lir, ins);
+ LInCache* lir = new(alloc()) LInCache(useBoxOrTyped(lhs), useRegister(rhs), temp());
+ define(lir, ins);
assignSafepoint(lir, ins);
}
void
LIRGenerator::visitHasOwnCache(MHasOwnCache* ins)
{
MDefinition* value = ins->value();
MOZ_ASSERT(value->type() == MIRType::Object || value->type() == MIRType::Value);
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -281,17 +281,17 @@ class LIRGenerator : public LIRGenerator
void visitIteratorEnd(MIteratorEnd* ins);
void visitStringLength(MStringLength* ins);
void visitArgumentsLength(MArgumentsLength* ins);
void visitGetFrameArgument(MGetFrameArgument* ins);
void visitSetFrameArgument(MSetFrameArgument* ins);
void visitRunOncePrologue(MRunOncePrologue* ins);
void visitRest(MRest* ins);
void visitThrow(MThrow* ins);
- void visitIn(MIn* ins);
+ void visitInCache(MInCache* ins);
void visitInArray(MInArray* ins);
void visitHasOwnCache(MHasOwnCache* ins);
void visitInstanceOf(MInstanceOf* ins);
void visitCallInstanceOf(MCallInstanceOf* ins);
void visitIsCallable(MIsCallable* ins);
void visitIsConstructor(MIsConstructor* ins);
void visitIsObject(MIsObject* ins);
void visitHasClass(MHasClass* ins);
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -12484,34 +12484,31 @@ class MIteratorEnd
public:
INSTRUCTION_HEADER(IteratorEnd)
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, iterator))
};
-// Implementation for 'in' operator.
-class MIn
+// Implementation for 'in' operator using instruction cache
+class MInCache
: public MBinaryInstruction,
- public MixPolicy<BoxPolicy<0>, ObjectPolicy<1> >::Data
-{
- MIn(MDefinition* key, MDefinition* obj)
+ public MixPolicy<CacheIdPolicy<0>, ObjectPolicy<1> >::Data
+{
+ MInCache(MDefinition* key, MDefinition* obj)
: MBinaryInstruction(key, obj)
{
setResultType(MIRType::Boolean);
}
public:
- INSTRUCTION_HEADER(In)
- TRIVIAL_NEW_WRAPPERS
-
- bool possiblyCalls() const override {
- return true;
- }
+ INSTRUCTION_HEADER(InCache)
+ TRIVIAL_NEW_WRAPPERS
+ NAMED_OPERANDS((0, key), (1, object))
};
// Test whether the index is in the array bounds or a hole.
class MInArray
: public MQuaternaryInstruction,
public ObjectPolicy<3>::Data
{
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -261,17 +261,17 @@ namespace jit {
_(GetFrameArgument) \
_(SetFrameArgument) \
_(RunOncePrologue) \
_(Rest) \
_(Floor) \
_(Ceil) \
_(Round) \
_(NearbyInt) \
- _(In) \
+ _(InCache) \
_(HasOwnCache) \
_(InstanceOf) \
_(CallInstanceOf) \
_(InterruptCheck) \
_(GetDOMProperty) \
_(GetDOMMember) \
_(SetDOMProperty) \
_(IsConstructor) \
--- a/js/src/jit/TypePolicy.cpp
+++ b/js/src/jit/TypePolicy.cpp
@@ -668,16 +668,17 @@ CacheIdPolicy<Op>::staticAdjustInputs(Te
case MIRType::String:
case MIRType::Symbol:
return true;
default:
return BoxPolicy<Op>::staticAdjustInputs(alloc, ins);
}
}
+template bool CacheIdPolicy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
template bool CacheIdPolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
bool
ToDoublePolicy::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
{
MOZ_ASSERT(ins->isToDouble() || ins->isToFloat32());
MDefinition* in = ins->getOperand(0);
@@ -1245,16 +1246,17 @@ FilterTypeSetPolicy::adjustInputs(TempAl
_(Mix4Policy<SimdScalarPolicy<0>, SimdScalarPolicy<1>, SimdScalarPolicy<2>, SimdScalarPolicy<3> >) \
_(MixPolicy<BoxPolicy<0>, ObjectPolicy<1> >) \
_(MixPolicy<ConvertToStringPolicy<0>, ConvertToStringPolicy<1> >) \
_(MixPolicy<ConvertToStringPolicy<0>, ObjectPolicy<1> >) \
_(MixPolicy<DoublePolicy<0>, DoublePolicy<1> >) \
_(MixPolicy<IntPolicy<0>, IntPolicy<1> >) \
_(MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >) \
_(MixPolicy<BoxExceptPolicy<0, MIRType::Object>, CacheIdPolicy<1>>) \
+ _(MixPolicy<CacheIdPolicy<0>, ObjectPolicy<1> >) \
_(MixPolicy<ObjectPolicy<0>, ConvertToStringPolicy<1> >) \
_(MixPolicy<ObjectPolicy<0>, IntPolicy<1> >) \
_(MixPolicy<ObjectPolicy<0>, IntPolicy<2> >) \
_(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<1> >) \
_(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<2> >) \
_(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<3> >) \
_(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1> >) \
_(MixPolicy<ObjectPolicy<0>, StringPolicy<1> >) \
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -7848,31 +7848,38 @@ class LGuardSharedTypedArray : public LI
const MGuardSharedTypedArray* mir() const {
return mir_->toGuardSharedTypedArray();
}
const LDefinition* tempInt() {
return getTemp(0);
}
};
-class LIn : public LCallInstructionHelper<1, BOX_PIECES+1, 0>
-{
- public:
- LIR_HEADER(In)
- LIn(const LBoxAllocation& lhs, const LAllocation& rhs) {
+class LInCache : public LInstructionHelper<1, BOX_PIECES+1, 1>
+{
+ public:
+ LIR_HEADER(InCache)
+ LInCache(const LBoxAllocation& lhs, const LAllocation& rhs, const LDefinition& temp) {
setBoxOperand(LHS, lhs);
setOperand(RHS, rhs);
+ setTemp(0, temp);
}
const LAllocation* lhs() {
return getOperand(LHS);
}
const LAllocation* rhs() {
return getOperand(RHS);
}
+ const LDefinition* temp() {
+ return getTemp(0);
+ }
+ const MInCache* mir() const {
+ return mir_->toInCache();
+ }
static const size_t LHS = 0;
static const size_t RHS = BOX_PIECES;
};
class LHasOwnCache : public LInstructionHelper<1, 2 * BOX_PIECES, 0>
{
public:
--- a/js/src/jit/shared/LOpcodes-shared.h
+++ b/js/src/jit/shared/LOpcodes-shared.h
@@ -370,17 +370,17 @@
_(Floor) \
_(FloorF) \
_(Ceil) \
_(CeilF) \
_(Round) \
_(RoundF) \
_(NearbyInt) \
_(NearbyIntF) \
- _(In) \
+ _(InCache) \
_(InArray) \
_(HasOwnCache) \
_(InstanceOfO) \
_(InstanceOfV) \
_(CallInstanceOf) \
_(InterruptCheck) \
_(Rotate) \
_(RotateI64) \