Bug 1334187 - Add ICCacheIR_Regular base class. r?jandem draft
authorTed Campbell <tcampbell@mozilla.com>
Thu, 26 Jan 2017 14:00:42 -0500
changeset 479739 194afec5316f77ef455f420f81b228d54bb7496e
parent 479651 af8a2573d0f1e9cc6f2ba0ab67d7a702a197f177
child 479740 a4dc6a52df2909bff8cf48e3892099e0b058f25a
push id44342
push userbmo:tcampbell@mozilla.com
push dateTue, 07 Feb 2017 05:31:18 +0000
reviewersjandem
bugs1334187
milestone54.0a1
Bug 1334187 - Add ICCacheIR_Regular base class. r?jandem
js/src/jit/BaselineCacheIRCompiler.cpp
js/src/jit/SharedIC.cpp
js/src/jit/SharedIC.h
js/src/jit/SharedICList.h
--- a/js/src/jit/BaselineCacheIRCompiler.cpp
+++ b/js/src/jit/BaselineCacheIRCompiler.cpp
@@ -1318,17 +1318,17 @@ jit::AttachBaselineCacheIRStub(JSContext
 
     if (writer.failed())
         return nullptr;
 
     // Just a sanity check: the caller should ensure we don't attach an
     // unlimited number of stubs.
     MOZ_ASSERT(stub->numOptimizedStubs() < MaxOptimizedCacheIRStubs);
 
-    enum class CacheIRStubKind { Monitored, Updated };
+    enum class CacheIRStubKind { Regular, Monitored, Updated };
 
     uint32_t stubDataOffset;
     CacheIRStubKind stubKind;
     switch (kind) {
       case CacheKind::GetProp:
       case CacheKind::GetElem:
       case CacheKind::GetName:
         stubDataOffset = sizeof(ICCacheIR_Monitored);
@@ -1375,16 +1375,26 @@ jit::AttachBaselineCacheIRStub(JSContext
     MOZ_ASSERT(stubInfo);
     MOZ_ASSERT(stubInfo->stubDataSize() == writer.stubDataSize());
 
     // Ensure we don't attach duplicate stubs. This can happen if a stub failed
     // for some reason and the IR generator doesn't check for exactly the same
     // conditions.
     for (ICStubConstIterator iter = stub->beginChainConst(); !iter.atEnd(); iter++) {
         switch (stubKind) {
+          case CacheIRStubKind::Regular: {
+            if (!iter->isCacheIR_Regular())
+                continue;
+            auto otherStub = iter->toCacheIR_Regular();
+            if (otherStub->stubInfo() != stubInfo)
+                continue;
+            if (!writer.stubDataEqualsMaybeUpdate(otherStub->stubDataStart()))
+                continue;
+            break;
+          }
           case CacheIRStubKind::Monitored: {
             if (!iter->isCacheIR_Monitored())
                 continue;
             auto otherStub = iter->toCacheIR_Monitored();
             if (otherStub->stubInfo() != stubInfo)
                 continue;
             if (!writer.stubDataEqualsMaybeUpdate(otherStub->stubDataStart()))
                 continue;
@@ -1414,16 +1424,22 @@ jit::AttachBaselineCacheIRStub(JSContext
 
     ICStubSpace* stubSpace = ICStubCompiler::StubSpaceForStub(stubInfo->makesGCCalls(),
                                                               outerScript, engine);
     void* newStubMem = stubSpace->alloc(bytesNeeded);
     if (!newStubMem)
         return nullptr;
 
     switch (stubKind) {
+      case CacheIRStubKind::Regular: {
+        auto newStub = new(newStubMem) ICCacheIR_Regular(code, stubInfo);
+        writer.copyStubData(newStub->stubDataStart());
+        stub->addNewStub(newStub);
+        return newStub;
+      }
       case CacheIRStubKind::Monitored: {
         ICStub* monitorStub =
             stub->toMonitoredFallbackStub()->fallbackMonitorStub()->firstMonitorStub();
         auto newStub = new(newStubMem) ICCacheIR_Monitored(code, monitorStub, stubInfo);
         writer.copyStubData(newStub->stubDataStart());
         stub->addNewStub(newStub);
         return newStub;
       }
@@ -1438,16 +1454,22 @@ jit::AttachBaselineCacheIRStub(JSContext
         return newStub;
       }
     }
 
     MOZ_CRASH("Invalid kind");
 }
 
 uint8_t*
+ICCacheIR_Regular::stubDataStart()
+{
+    return reinterpret_cast<uint8_t*>(this) + stubInfo_->stubDataOffset();
+}
+
+uint8_t*
 ICCacheIR_Monitored::stubDataStart()
 {
     return reinterpret_cast<uint8_t*>(this) + stubInfo_->stubDataOffset();
 }
 
 uint8_t*
 ICCacheIR_Updated::stubDataStart()
 {
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -187,16 +187,18 @@ ICStub::NonCacheIRStubMakesGCCalls(Kind 
         return false;
     }
 }
 
 bool
 ICStub::makesGCCalls() const
 {
     switch (kind()) {
+      case CacheIR_Regular:
+        return toCacheIR_Regular()->stubInfo()->makesGCCalls();
       case CacheIR_Monitored:
         return toCacheIR_Monitored()->stubInfo()->makesGCCalls();
       case CacheIR_Updated:
         return toCacheIR_Updated()->stubInfo()->makesGCCalls();
       default:
         return NonCacheIRStubMakesGCCalls(kind());
     }
 }
@@ -371,16 +373,19 @@ ICStub::trace(JSTracer* trc)
         TraceNullableEdge(trc, &stub->templateObject(), "baseline-newobject-template");
         break;
       }
       case ICStub::Rest_Fallback: {
         ICRest_Fallback* stub = toRest_Fallback();
         TraceEdge(trc, &stub->templateObject(), "baseline-rest-template");
         break;
       }
+      case ICStub::CacheIR_Regular:
+        TraceCacheIRStub(trc, this, toCacheIR_Regular()->stubInfo());
+        break;
       case ICStub::CacheIR_Monitored:
         TraceCacheIRStub(trc, this, toCacheIR_Monitored()->stubInfo());
         break;
       case ICStub::CacheIR_Updated: {
         ICCacheIR_Updated* stub = toCacheIR_Updated();
         TraceNullableEdge(trc, &stub->updateStubGroup(), "baseline-update-stub-group");
         TraceEdge(trc, &stub->updateStubId(), "baseline-update-stub-id");
         TraceCacheIRStub(trc, this, stub->stubInfo());
@@ -1930,17 +1935,19 @@ StripPreliminaryObjectStubs(JSContext* c
     // Afterwards, the objects (even the preliminary ones) might be changed
     // to reduce the number of fixed slots they have. If we generate stubs for
     // both the old and new number of fixed slots, the stub will look
     // polymorphic to IonBuilder when it is actually monomorphic. To avoid
     // this, strip out any stubs for preliminary objects before attaching a new
     // stub which isn't on a preliminary object.
 
     for (ICStubIterator iter = stub->beginChain(); !iter.atEnd(); iter++) {
-        if (iter->isCacheIR_Monitored() && iter->toCacheIR_Monitored()->hasPreliminaryObject())
+        if (iter->isCacheIR_Regular() && iter->toCacheIR_Regular()->hasPreliminaryObject())
+            iter.unlink(cx);
+        else if (iter->isCacheIR_Monitored() && iter->toCacheIR_Monitored()->hasPreliminaryObject())
             iter.unlink(cx);
         else if (iter->isCacheIR_Updated() && iter->toCacheIR_Updated()->hasPreliminaryObject())
             iter.unlink(cx);
     }
 }
 
 JSObject*
 GetDOMProxyProto(JSObject* obj)
--- a/js/src/jit/SharedIC.h
+++ b/js/src/jit/SharedIC.h
@@ -503,17 +503,17 @@ class ICStub
 #undef DEF_ENUM_KIND
         LIMIT
     };
 
     static bool IsValidKind(Kind k) {
         return (k > INVALID) && (k < LIMIT);
     }
     static bool IsCacheIRKind(Kind k) {
-        return k == CacheIR_Monitored || k == CacheIR_Updated;
+        return k == CacheIR_Regular || k == CacheIR_Monitored || k == CacheIR_Updated;
     }
 
     static const char* KindString(Kind k) {
         switch(k) {
 #define DEF_KIND_STR(kindName) case kindName: return #kindName;
             IC_BASELINE_STUB_KIND_LIST(DEF_KIND_STR)
             IC_SHARED_STUB_KIND_LIST(DEF_KIND_STR)
 #undef DEF_KIND_STR
@@ -828,16 +828,41 @@ class ICFallbackStub : public ICStub
         }
         return count;
     }
 
     void unlinkStub(Zone* zone, ICStub* prev, ICStub* stub);
     void unlinkStubsWithKind(JSContext* cx, ICStub::Kind kind);
 };
 
+// Base class for Trait::Regular CacheIR stubs
+class ICCacheIR_Regular : public ICStub
+{
+    const CacheIRStubInfo* stubInfo_;
+
+  public:
+    ICCacheIR_Regular(JitCode* stubCode, const CacheIRStubInfo* stubInfo)
+      : ICStub(ICStub::CacheIR_Regular, stubCode),
+        stubInfo_(stubInfo)
+    {}
+
+    void notePreliminaryObject() {
+        extra_ = 1;
+    }
+    bool hasPreliminaryObject() const {
+        return extra_;
+    }
+
+    const CacheIRStubInfo* stubInfo() const {
+        return stubInfo_;
+    }
+
+    uint8_t* stubDataStart();
+};
+
 // Monitored stubs are IC stubs that feed a single resulting value out to a
 // type monitor operation.
 class ICMonitoredStub : public ICStub
 {
   protected:
     // Pointer to the start of the type monitoring stub chain.
     ICStub* firstMonitorStub_;
 
--- a/js/src/jit/SharedICList.h
+++ b/js/src/jit/SharedICList.h
@@ -32,16 +32,17 @@ namespace jit {
     _(Compare_Boolean)                           \
     _(Compare_Object)                            \
     _(Compare_ObjectWithUndefined)               \
     _(Compare_Int32WithBoolean)                  \
                                                  \
     _(GetProp_Fallback)                          \
     _(GetProp_Generic)                           \
                                                  \
+    _(CacheIR_Regular)                           \
     _(CacheIR_Monitored)                         \
     _(CacheIR_Updated)                           \
                                                  \
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_SharedICList_h */