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 479740 a4dc6a52df2909bff8cf48e3892099e0b058f25a
parent 479739 194afec5316f77ef455f420f81b228d54bb7496e
child 479741 1c6c54ee868f32e89bab7dd1978e476380869716
push id44342
push userbmo:tcampbell@mozilla.com
push dateTue, 07 Feb 2017 05:31:18 +0000
reviewersjandem
bugs1334187
milestone54.0a1
Bug 1334187 - Add CacheIR scaffolding for JSOP_IN. r?jandem MozReview-Commit-ID: C7WHxYqJXmZ
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
@@ -1274,16 +1274,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::SetElem:
         MOZ_ASSERT(numInputs == 3);
         allocator.initInputLocation(0, R0);
         allocator.initInputLocation(1, R1);
@@ -1323,16 +1324,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:
       case CacheKind::SetElem:
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -2073,27 +2073,46 @@ DoInFallback(JSContext* cx, BaselineFram
 
     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(frame->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, frame->script(), 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
@@ -1558,16 +1558,29 @@ 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
@@ -131,16 +131,17 @@ class TypedOperandId : public OperandId
 
 enum class CacheKind : uint8_t
 {
     GetProp,
     GetElem,
     GetName,
     SetProp,
     SetElem,
+    In,
 };
 
 #define CACHE_IR_OPS(_)                   \
     _(GuardIsObject)                      \
     _(GuardIsObjectOrNull)                \
     _(GuardIsString)                      \
     _(GuardIsSymbol)                      \
     _(GuardIsInt32Index)                  \
@@ -1020,12 +1021,24 @@ 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
@@ -254,16 +254,17 @@ CodeGenerator::visitOutOfLineICFallback(
         restoreLiveIgnore(lir, StoreValueTo(getPropIC->output()).clobbered());
 
         masm.jump(ool->rejoin());
         return;
       }
       case CacheKind::GetName:
       case CacheKind::SetProp:
       case CacheKind::SetElem:
+      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
@@ -39,16 +39,17 @@ IonIC::scratchRegisterForEntryJump()
         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::SetElem:
+      case CacheKind::In:
         MOZ_CRASH("Baseline-specific for now");
     }
 
     MOZ_CRASH("Invalid kind");
 }
 
 void
 IonIC::reset(Zone* zone)