Bug 1337773 - Add IonInIC draft
authorTed Campbell <tcampbell@mozilla.com>
Mon, 17 Apr 2017 13:55:27 -0400
changeset 572075 a20334ff0de828cc6179c7a2caa7f9434810ee53
parent 572074 c06620d52d5f60de8e13bbd3628b4b8d23cf7c1b
child 572076 e370015f9ad42b1e99149d510b2e9f960468e9ea
push id56986
push userbmo:tcampbell@mozilla.com
push dateWed, 03 May 2017 17:38:15 +0000
bugs1337773
milestone55.0a1
Bug 1337773 - Add IonInIC MozReview-Commit-ID: BmHPnJnMjVP
js/src/jit/CodeGenerator.cpp
js/src/jit/IonCacheIRCompiler.cpp
js/src/jit/IonIC.cpp
js/src/jit/IonIC.h
--- 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 */