Bug 1337773 - Add IonInIC
MozReview-Commit-ID: BmHPnJnMjVP
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -153,16 +153,20 @@ typedef bool (*IonHasOwnICFn)(JSContext*
int32_t*);
static const VMFunction IonHasOwnICInfo =
FunctionInfo<IonHasOwnICFn>(IonHasOwnIC::update, "IonHasOwnIC::update");
typedef JSObject* (*IonBindNameICFn)(JSContext*, HandleScript, IonBindNameIC*, HandleObject);
static const VMFunction IonBindNameICInfo =
FunctionInfo<IonBindNameICFn>(IonBindNameIC::update, "IonBindNameIC::update");
+typedef bool (*IonInICFn)(JSContext*, HandleScript, IonInIC*, HandleValue, HandleObject, bool*);
+static const VMFunction IonInICInfo =
+ FunctionInfo<IonInICFn>(IonInIC::update, "IonInIC::update");
+
void
CodeGenerator::visitOutOfLineICFallback(OutOfLineICFallback* ool)
{
LInstruction* lir = ool->lir();
size_t cacheIndex = ool->cacheIndex();
size_t cacheInfoIndex = ool->cacheInfoIndex();
DataPtr<IonIC> ic(this, cacheIndex);
@@ -238,17 +242,34 @@ CodeGenerator::visitOutOfLineICFallback(
callVM(IonBindNameICInfo, lir);
StoreRegisterTo(bindNameIC->output()).generate(this);
restoreLiveIgnore(lir, StoreRegisterTo(bindNameIC->output()).clobbered());
masm.jump(ool->rejoin());
return;
}
- case CacheKind::In:
+ case CacheKind::In: {
+ IonInIC* inIC = ic->asInIC();
+
+ saveLive(lir);
+
+ pushArg(inIC->object());
+ pushArg(inIC->key());
+ icInfo_[cacheInfoIndex].icOffsetForPush = pushArgWithPatch(ImmWord(-1));
+ pushArg(ImmGCPtr(gen->info().script()));
+
+ callVM(IonInICInfo, lir);
+
+ StoreRegisterTo(inIC->output()).generate(this);
+ restoreLiveIgnore(lir, StoreRegisterTo(inIC->output()).clobbered());
+
+ masm.jump(ool->rejoin());
+ return;
+ }
case CacheKind::TypeOf:
MOZ_CRASH("Baseline-specific for now");
case CacheKind::HasOwn: {
IonHasOwnIC* hasOwnIC = ic->asHasOwnIC();
saveLive(lir);
pushArg(hasOwnIC->id());
--- a/js/src/jit/IonCacheIRCompiler.cpp
+++ b/js/src/jit/IonCacheIRCompiler.cpp
@@ -435,17 +435,31 @@ IonCacheIRCompiler::init()
liveRegs_.emplace(ic->liveRegs());
outputUnchecked_.emplace(TypedOrValueRegister(MIRType::Object, AnyRegister(output)));
MOZ_ASSERT(numInputs == 1);
allocator.initInputLocation(0, ic->environment(), JSVAL_TYPE_OBJECT);
break;
}
- case CacheKind::In:
+ case CacheKind::In: {
+ IonInIC* ic = ic_->asInIC();
+ Register output = ic->output();
+
+ available.add(output);
+
+ liveRegs_.emplace(ic->liveRegs());
+ outputUnchecked_.emplace(TypedOrValueRegister(MIRType::Boolean, AnyRegister(output)));
+
+ MOZ_ASSERT(numInputs == 2);
+ allocator.initInputLocation(0, ic->key());
+ allocator.initInputLocation(1, TypedOrValueRegister(MIRType::Object,
+ AnyRegister(ic->object())));
+ break;
+ }
case CacheKind::TypeOf:
MOZ_CRASH("Invalid cache");
case CacheKind::HasOwn: {
IonHasOwnIC* ic = ic_->asHasOwnIC();
Register output = ic->output();
available.add(output);
--- a/js/src/jit/IonIC.cpp
+++ b/js/src/jit/IonIC.cpp
@@ -44,16 +44,17 @@ IonIC::scratchRegisterForEntryJump()
case CacheKind::SetProp:
case CacheKind::SetElem:
return asSetPropertyIC()->temp();
case CacheKind::GetName:
return asGetNameIC()->temp();
case CacheKind::BindName:
return asBindNameIC()->temp();
case CacheKind::In:
+ return asInIC()->temp();
case CacheKind::TypeOf:
MOZ_CRASH("Baseline-specific for now");
case CacheKind::HasOwn:
return asHasOwnIC()->output();
}
MOZ_CRASH("Invalid kind");
}
@@ -366,16 +367,41 @@ IonHasOwnIC::update(JSContext* cx, Handl
bool found;
if (!HasOwnProperty(cx, val, idVal, &found))
return false;
*res = found;
return true;
}
+/* static */ bool
+IonInIC::update(JSContext* cx, HandleScript outerScript, IonInIC* ic,
+ HandleValue key, HandleObject obj, bool* res)
+{
+ IonScript* ionScript = outerScript->ionScript();
+
+ if (ic->state().maybeTransition())
+ ic->discardStubs(cx->zone());
+
+ if (ic->state().canAttachStub()) {
+ bool attached = false;
+ RootedScript script(cx, ic->script());
+ RootedValue objV(cx, ObjectValue(*obj));
+ jsbytecode* pc = ic->pc();
+ HasPropIRGenerator gen(cx, script, pc, CacheKind::In, ic->state().mode(), key, objV);
+ if (gen.tryAttachStub())
+ ic->attachCacheIRStub(cx, gen.writerRef(), gen.cacheKind(), ionScript, &attached);
+
+ if (!attached)
+ ic->state().trackNotAttached();
+ }
+
+ return OperatorIn(cx, key, obj, res);
+}
+
uint8_t*
IonICStub::stubDataStart()
{
return reinterpret_cast<uint8_t*>(this) + stubInfo_->stubDataOffset();
}
void
IonIC::attachStub(IonICStub* newStub, JitCode* code)
--- a/js/src/jit/IonIC.h
+++ b/js/src/jit/IonIC.h
@@ -56,16 +56,17 @@ class IonICStub
}
};
class IonGetPropertyIC;
class IonSetPropertyIC;
class IonGetNameIC;
class IonBindNameIC;
class IonHasOwnIC;
+class IonInIC;
class IonIC
{
// This either points at the OOL path for the fallback path, or the code for
// the first stub.
uint8_t* codeRaw_;
// The first optimized stub, or nullptr.
@@ -147,16 +148,20 @@ class IonIC
IonBindNameIC* asBindNameIC() {
MOZ_ASSERT(kind_ == CacheKind::BindName);
return (IonBindNameIC*)this;
}
IonHasOwnIC* asHasOwnIC() {
MOZ_ASSERT(kind_ == CacheKind::HasOwn);
return (IonHasOwnIC*)this;
}
+ IonInIC* asInIC() {
+ MOZ_ASSERT(kind_ == CacheKind::In);
+ return (IonInIC*)this;
+ }
void updateBaseAddress(JitCode* code, MacroAssembler& masm);
// Returns the Register to use as scratch when entering IC stubs. This
// should either be an output register or a temp.
Register scratchRegisterForEntryJump();
void trace(JSTracer* trc);
@@ -331,12 +336,42 @@ class IonHasOwnIC : public IonIC
TypedOrValueRegister id() const { return id_; }
Register output() const { return output_; }
LiveRegisterSet liveRegs() const { return liveRegs_; }
static MOZ_MUST_USE bool update(JSContext* cx, HandleScript outerScript, IonHasOwnIC* ic,
HandleValue val, HandleValue idVal, int32_t* res);
};
+class IonInIC : public IonIC
+{
+ LiveRegisterSet liveRegs_;
+
+ ConstantOrRegister key_;
+ Register object_;
+ Register output_;
+ Register temp_;
+
+ public:
+ IonInIC(LiveRegisterSet liveRegs, const ConstantOrRegister& key,
+ Register object, Register output, Register temp)
+ : IonIC(CacheKind::In),
+ liveRegs_(liveRegs),
+ key_(key),
+ object_(object),
+ output_(output),
+ temp_(temp)
+ { }
+
+ ConstantOrRegister key() const { return key_; }
+ Register object() const { return object_; }
+ Register output() const { return output_; }
+ Register temp() const { return temp_; }
+ LiveRegisterSet liveRegs() const { return liveRegs_; }
+
+ static MOZ_MUST_USE bool update(JSContext* cx, HandleScript outerScript, IonInIC* ic,
+ HandleValue key, HandleObject obj, bool* res);
+};
+
} // namespace jit
} // namespace js
#endif /* jit_IonIC_h */