diff --git a/js/src/jit/CacheIRHealth.cpp b/js/src/jit/CacheIRHealth.cpp index 2ae30bb707a0a..9514bf2f768c4 100644 --- a/js/src/jit/CacheIRHealth.cpp +++ b/js/src/jit/CacheIRHealth.cpp @@ -12,6 +12,7 @@ # include "gc/Zone.h" # include "jit/CacheIRCompiler.h" # include "jit/JitScript.h" +# include "vm/JSObject-inl.h" using namespace js; using namespace js::jit; @@ -69,8 +70,28 @@ CacheIRHealth::Happiness CacheIRHealth::spewStubHealth( return stubHappiness; } +BaseScript* CacheIRHealth::maybeExtractBaseScript(JSContext* cx, Shape* shape) { + TaggedProto taggedProto = shape->base()->proto(); + if (!taggedProto.isObject()) { + return nullptr; + } + Value cval; + if (!GetPropertyPure(cx, taggedProto.toObject(), + NameToId(cx->names().constructor), &cval)) { + return nullptr; + } + if (!IsFunctionObject(cval)) { + return nullptr; + } + JSFunction& jsfun = cval.toObject().as<JSFunction>(); + if (!jsfun.hasBaseScript()) { + return nullptr; + } + return jsfun.baseScript(); +} + void CacheIRHealth::spewShapeInformation(AutoStructuredSpewer& spew, - ICStub* stub) { + JSContext* cx, ICStub* stub) { bool shapesStarted = false; const CacheIRStubInfo* stubInfo = stub->toCacheIRStub()->stubInfo(); size_t offset = 0; @@ -109,6 +130,16 @@ void CacheIRHealth::spewShapeInformation(AutoStructuredSpewer& spew, } } spew->property("totalKeys", propMap->approximateEntryCount()); + BaseScript* baseScript = maybeExtractBaseScript(cx, shape); + if (baseScript) { + spew->beginObjectProperty("shapeAllocSite"); + { + spew->property("filename", baseScript->filename()); + spew->property("line", baseScript->lineno()); + spew->property("column", baseScript->column()); + } + spew->endObject(); + } } } spew->endObject(); @@ -124,6 +155,7 @@ void CacheIRHealth::spewShapeInformation(AutoStructuredSpewer& spew, } bool CacheIRHealth::spewNonFallbackICInformation(AutoStructuredSpewer& spew, + JSContext* cx, ICStub* firstStub, Happiness* entryHappiness) { const CacheIRStubInfo* stubInfo = firstStub->toCacheIRStub()->stubInfo(); @@ -142,7 +174,7 @@ bool CacheIRHealth::spewNonFallbackICInformation(AutoStructuredSpewer& spew, *entryHappiness = stubHappiness; } - spewShapeInformation(spew, stub); + spewShapeInformation(spew, cx, stub); ICStub* nextStub = stub->toCacheIRStub()->next(); if (!nextStub->isFallback()) { @@ -225,7 +257,7 @@ bool CacheIRHealth::spewNonFallbackICInformation(AutoStructuredSpewer& spew, return true; } -bool CacheIRHealth::spewICEntryHealth(AutoStructuredSpewer& spew, +bool CacheIRHealth::spewICEntryHealth(AutoStructuredSpewer& spew, JSContext* cx, HandleScript script, ICEntry* entry, ICFallbackStub* fallback, jsbytecode* pc, JSOp op, Happiness* entryHappiness) { @@ -239,7 +271,7 @@ bool CacheIRHealth::spewICEntryHealth(AutoStructuredSpewer& spew, ICStub* firstStub = entry->firstStub(); if (!firstStub->isFallback()) { - if (!spewNonFallbackICInformation(spew, firstStub, entryHappiness)) { + if (!spewNonFallbackICInformation(spew, cx, firstStub, entryHappiness)) { return false; } } @@ -321,7 +353,7 @@ void CacheIRHealth::healthReportForIC(JSContext* cx, ICEntry* entry, JSOp jsOp = JSOp(*op); Happiness entryHappiness = Happy; - if (!spewICEntryHealth(spew, script, entry, fallback, op, jsOp, + if (!spewICEntryHealth(spew, cx, script, entry, fallback, op, jsOp, &entryHappiness)) { cx->recoverFromOutOfMemory(); return; @@ -360,7 +392,7 @@ void CacheIRHealth::healthReportForScript(JSContext* cx, HandleScript script, spew->beginObject(); Happiness entryHappiness = Happy; - if (!spewICEntryHealth(spew, script, &entry, fallback, pc, op, + if (!spewICEntryHealth(spew, cx, script, &entry, fallback, pc, op, &entryHappiness)) { cx->recoverFromOutOfMemory(); return; diff --git a/js/src/jit/CacheIRHealth.h b/js/src/jit/CacheIRHealth.h index 6fa0425d8ec66..471720f9fa7d8 100644 --- a/js/src/jit/CacheIRHealth.h +++ b/js/src/jit/CacheIRHealth.h @@ -64,15 +64,20 @@ class CacheIRHealth { Happiness spewStubHealth(AutoStructuredSpewer& spew, ICCacheIRStub* stub); // If there is more than just a fallback stub in an IC Entry, then additional // information about the IC entry. - bool spewNonFallbackICInformation(AutoStructuredSpewer& spew, + bool spewNonFallbackICInformation(AutoStructuredSpewer& spew, JSContext* cx, ICStub* firstStub, Happiness* entryHappiness); // Health of all the stubs in an individual CacheIR Entry. - bool spewICEntryHealth(AutoStructuredSpewer& spew, HandleScript script, - ICEntry* entry, ICFallbackStub* fallback, - jsbytecode* pc, JSOp op, Happiness* entryHappiness); - // Spews information about shapes in an ICStub. - void spewShapeInformation(AutoStructuredSpewer& spew, ICStub* stub); + bool spewICEntryHealth(AutoStructuredSpewer& spew, JSContext* cx, + HandleScript script, ICEntry* entry, + ICFallbackStub* fallback, jsbytecode* pc, JSOp op, + Happiness* entryHappiness); + // Spews first and last property name for each shape checked by + // GuardShape in the stub. + void spewShapeInformation(AutoStructuredSpewer& spew, JSContext* cx, + ICStub* stub); + // Returns the BaseScript of a Shape if available. + BaseScript* maybeExtractBaseScript(JSContext* cx, Shape* shape); public: // Spews the final hit count for scripts where we care about its final hit