Bug 1334187 - Add CacheIR scaffolding for JSOP_IN. r?jandem draft
authorTed Campbell <tcampbell@mozilla.com>
Wed, 25 Jan 2017 12:08:25 -0500
changeset 469522 19c31140c86f9dca3ede500387df522ecc363872
parent 469521 06b257e86d8943feae24eaf579d23ddf980fecfe
child 469523 b2566fe6f504963c713c116e69f2a399e5c2b29b
push id43751
push userbmo:tcampbell@mozilla.com
push dateThu, 02 Feb 2017 08:03:02 +0000
reviewersjandem
bugs1334187
milestone54.0a1
Bug 1334187 - Add CacheIR scaffolding for JSOP_IN. r?jandem
js/src/jit/BaselineCacheIRCompiler.cpp
js/src/jit/BaselineIC.cpp
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
js/src/jit/CodeGenerator.cpp
js/src/jit/IonIC.cpp
--- a/js/src/jit/BaselineCacheIRCompiler.cpp
+++ b/js/src/jit/BaselineCacheIRCompiler.cpp
@@ -1217,16 +1217,17 @@ BaselineCacheIRCompiler::init(CacheKind 
 
     switch (kind) {
       case CacheKind::GetProp:
         MOZ_ASSERT(numInputs == 1);
         allocator.initInputLocation(0, R0);
         break;
       case CacheKind::GetElem:
       case CacheKind::SetProp:
+      case CacheKind::In:
         MOZ_ASSERT(numInputs == 2);
         allocator.initInputLocation(0, R0);
         allocator.initInputLocation(1, R1);
         break;
       case CacheKind::GetName:
         MOZ_ASSERT(numInputs == 1);
         allocator.initInputLocation(0, R0.scratchReg(), JSVAL_TYPE_OBJECT);
 #if defined(JS_NUNBOX32)
@@ -1260,16 +1261,20 @@ jit::AttachBaselineCacheIRStub(JSContext
     // unlimited number of stubs.
     MOZ_ASSERT(stub->numOptimizedStubs() < MaxOptimizedCacheIRStubs);
 
     enum class CacheIRStubKind { Regular, Monitored, Updated };
 
     uint32_t stubDataOffset;
     CacheIRStubKind stubKind;
     switch (kind) {
+      case CacheKind::In:
+        stubDataOffset = sizeof(ICCacheIR_Regular);
+        stubKind = CacheIRStubKind::Regular;
+        break;
       case CacheKind::GetProp:
       case CacheKind::GetElem:
       case CacheKind::GetName:
         stubDataOffset = sizeof(ICCacheIR_Monitored);
         stubKind = CacheIRStubKind::Monitored;
         break;
       case CacheKind::SetProp:
         stubDataOffset = sizeof(ICCacheIR_Updated);
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -2007,37 +2007,59 @@ TryAttachNativeInDoesNotExistStub(JSCont
     stub->addNewStub(newStub);
     return true;
 }
 
 static bool
 DoInFallback(JSContext* cx, BaselineFrame* frame, ICIn_Fallback* stub_,
              HandleValue key, HandleValue objValue, MutableHandleValue res)
 {
+    SharedStubInfo info(cx, frame, stub_->icEntry());
+
     // This fallback stub may trigger debug mode toggling.
     DebugModeOSRVolatileStub<ICIn_Fallback*> stub(frame, stub_);
 
     FallbackICSpew(cx, stub, "In");
 
     if (!objValue.isObject()) {
         ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, objValue, nullptr);
         return false;
     }
 
+    bool attached = false;
+
+    if (stub->numOptimizedStubs() >= ICIn_Fallback::MAX_OPTIMIZED_STUBS) {
+        attached = true;
+    }
+
     RootedObject obj(cx, &objValue.toObject());
+    jsbytecode* pc = stub->icEntry()->pc(info.script());
+
+    if (!attached && !JitOptions.disableCacheIR) {
+        ICStubEngine engine = ICStubEngine::Baseline;
+        InIRGenerator gen(cx, pc, key, obj);
+        if (gen.tryAttachStub()) {
+            ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
+                                                        engine, info.outerScript(cx), stub);
+            if (newStub) {
+                JitSpew(JitSpew_BaselineIC, "  Attached CacheIR stub");
+                attached = true;
+            }
+        }
+    }
 
     bool cond = false;
     if (!OperatorIn(cx, key, obj, &cond))
         return false;
     res.setBoolean(cond);
 
     if (stub.invalid())
         return true;
 
-    if (stub->numOptimizedStubs() >= ICIn_Fallback::MAX_OPTIMIZED_STUBS)
+    if (attached)
         return true;
 
     if (obj->isNative()) {
         RootedScript script(cx, frame->script());
         bool attached = false;
         if (cond) {
             if (!TryAttachDenseInStub(cx, script, stub, key, obj, &attached))
                 return false;
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -1539,16 +1539,30 @@ GetNameIRGenerator::tryAttachEnvironment
         size_t dynamicSlotOffset = holder->dynamicSlotIndex(shape->slot()) * sizeof(Value);
         writer.loadEnvironmentDynamicSlotResult(lastObjId, dynamicSlotOffset);
     }
 
     writer.typeMonitorResult();
     return true;
 }
 
+InIRGenerator::InIRGenerator(JSContext* cx, jsbytecode* pc,
+                             HandleValue key, HandleObject obj)
+  : IRGenerator(cx, pc, CacheKind::In),
+    key_(key), obj_(obj)
+{ }
+
+bool
+InIRGenerator::tryAttachStub()
+{
+    MOZ_ASSERT(cacheKind_ == CacheKind::In);
+
+    return false;
+}
+
 bool
 IRGenerator::maybeGuardInt32Index(const Value& index, ValOperandId indexId,
                                   uint32_t* int32Index, Int32OperandId* int32IndexId)
 {
     if (index.isNumber()) {
         int32_t indexSigned;
         if (index.isInt32()) {
             indexSigned = index.toInt32();
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -130,16 +130,17 @@ class TypedOperandId : public OperandId
 };
 
 enum class CacheKind : uint8_t
 {
     GetProp,
     GetElem,
     GetName,
     SetProp,
+    In,
 };
 
 #define CACHE_IR_OPS(_)                   \
     _(GuardIsObject)                      \
     _(GuardIsObjectOrNull)                \
     _(GuardIsString)                      \
     _(GuardIsSymbol)                      \
     _(GuardIsInt32Index)                  \
@@ -989,12 +990,25 @@ class MOZ_RAII SetPropIRGenerator : publ
         return updateStubGroup_;
     }
     jsid updateStubId() const {
         MOZ_ASSERT(needUpdateStub_);
         return updateStubId_;
     }
 };
 
+// InIRGenerator generates CacheIR for a In IC.
+class MOZ_RAII InIRGenerator : public IRGenerator
+{
+    HandleValue key_;
+    HandleObject obj_;
+
+  public:
+    InIRGenerator(JSContext* cx, jsbytecode* pc,
+                  HandleValue key, HandleObject obj);
+
+    bool tryAttachStub();
+};
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_CacheIR_h */
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -253,16 +253,17 @@ CodeGenerator::visitOutOfLineICFallback(
         StoreValueTo(getPropIC->output()).generate(this);
         restoreLiveIgnore(lir, StoreValueTo(getPropIC->output()).clobbered());
 
         masm.jump(ool->rejoin());
         return;
       }
       case CacheKind::GetName:
       case CacheKind::SetProp:
+      case CacheKind::In:
         MOZ_CRASH("Baseline-specific for now");
     }
     MOZ_CRASH();
 }
 
 StringObject*
 MNewStringObject::templateObj() const
 {
--- a/js/src/jit/IonIC.cpp
+++ b/js/src/jit/IonIC.cpp
@@ -38,16 +38,17 @@ IonIC::scratchRegisterForEntryJump()
         Register temp = asGetPropertyIC()->maybeTemp();
         if (temp != InvalidReg)
             return temp;
         TypedOrValueRegister output = asGetPropertyIC()->output();
         return output.hasValue() ? output.valueReg().scratchReg() : output.typedReg().gpr();
       }
       case CacheKind::GetName:
       case CacheKind::SetProp:
+      case CacheKind::In:
         MOZ_CRASH("Baseline-specific for now");
     }
 
     MOZ_CRASH("Invalid kind");
 }
 
 void
 IonIC::reset(Zone* zone)