Bug 1334187 - Add ICCacheIR_Regular base class. r?jandem
--- 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 */