зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1716529 - Don't create allocation sites until baseline r=jandem
This stops creating allocation sites for IC stubs when running in the baseline interpreter. When a script is compiled in baseline proper this scans the IC chain for ops that could potentially reference allocation sites, and allocates them where necessary. This should result in fewer sites being created and less overhead for code that doesn't reach baseline. Differential Revision: https://phabricator.services.mozilla.com/D117920
This commit is contained in:
Родитель
d8f25eb345
Коммит
5997bc1e3d
|
@ -11,6 +11,7 @@
|
|||
#include "jit/ABIFunctions.h"
|
||||
#include "jit/BaselineIC.h"
|
||||
#include "jit/BaselineJIT.h"
|
||||
#include "jit/CacheIRCompiler.h"
|
||||
#include "jit/CalleeToken.h"
|
||||
#include "jit/FixedList.h"
|
||||
#include "jit/IonAnalysis.h"
|
||||
|
@ -541,6 +542,58 @@ bool BaselineCodeGen<Handler>::emitOutOfLinePostBarrierSlot() {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Scan the a cache IR stub's fields and create an allocation site for any that
|
||||
// refer to the catch-all unknown allocation site. This will be the case for
|
||||
// stubs created when running in the interpreter. This happens on transition to
|
||||
// baseline.
|
||||
static bool CreateAllocSitesForCacheIRStub(JSScript* script,
|
||||
ICCacheIRStub* stub) {
|
||||
const CacheIRStubInfo* stubInfo = stub->stubInfo();
|
||||
uint8_t* stubData = stub->stubDataStart();
|
||||
|
||||
uint32_t field = 0;
|
||||
size_t offset = 0;
|
||||
while (true) {
|
||||
StubField::Type fieldType = stubInfo->fieldType(field);
|
||||
if (fieldType == StubField::Type::Limit) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (fieldType == StubField::Type::AllocSite) {
|
||||
gc::AllocSite* site =
|
||||
stubInfo->getPtrStubField<ICCacheIRStub, gc::AllocSite>(stub, offset);
|
||||
if (site->kind() == gc::AllocSite::Kind::Unknown) {
|
||||
gc::AllocSite* newSite = script->createAllocSite();
|
||||
if (!newSite) {
|
||||
return false;
|
||||
}
|
||||
|
||||
stubInfo->replaceStubRawWord(stubData, offset, uintptr_t(site),
|
||||
uintptr_t(newSite));
|
||||
}
|
||||
}
|
||||
|
||||
field++;
|
||||
offset += StubField::sizeInBytes(fieldType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CreateAllocSitesForICChain(JSScript* script, uint32_t entryIndex) {
|
||||
JitScript* jitScript = script->jitScript();
|
||||
ICStub* stub = jitScript->icEntry(entryIndex).firstStub();
|
||||
|
||||
while (!stub->isFallback()) {
|
||||
if (!CreateAllocSitesForCacheIRStub(script, stub->toCacheIRStub())) {
|
||||
// This is an optimization and safe to skip if we hit OOM or per-zone
|
||||
// limit.
|
||||
return;
|
||||
}
|
||||
stub = stub->toCacheIRStub()->next();
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
bool BaselineCompilerCodeGen::emitNextIC() {
|
||||
// Emit a call to an IC stored in JitScript. Calls to this must match the
|
||||
|
@ -563,6 +616,10 @@ bool BaselineCompilerCodeGen::emitNextIC() {
|
|||
MOZ_ASSERT(stub->pcOffset() == pcOffset);
|
||||
MOZ_ASSERT(BytecodeOpHasIC(JSOp(*handler.pc())));
|
||||
|
||||
if (BytecodeOpCanHaveAllocSite(JSOp(*handler.pc()))) {
|
||||
CreateAllocSitesForICChain(script, entryIndex);
|
||||
}
|
||||
|
||||
// Load stub pointer into ICStubReg.
|
||||
masm.loadPtr(frame.addressOfICScript(), ICStubReg);
|
||||
size_t firstStubOffset = ICScript::offsetOfFirstStub(entryIndex);
|
||||
|
|
|
@ -2384,9 +2384,8 @@ bool DoNewArrayFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return false;
|
||||
}
|
||||
|
||||
JSScript* outerScript = frame->outerScript();
|
||||
TryAttachStub<NewArrayIRGenerator>("NewArray", cx, frame, stub, JSOp(*pc),
|
||||
array, outerScript);
|
||||
array, frame);
|
||||
|
||||
res.setObject(*array);
|
||||
return true;
|
||||
|
@ -2420,9 +2419,8 @@ bool DoNewObjectFallback(JSContext* cx, BaselineFrame* frame,
|
|||
return false;
|
||||
}
|
||||
|
||||
JSScript* outerScript = frame->outerScript();
|
||||
TryAttachStub<NewObjectIRGenerator>("NewObject", cx, frame, stub, JSOp(*pc),
|
||||
obj, outerScript);
|
||||
obj, frame);
|
||||
|
||||
res.setObject(*obj);
|
||||
return true;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "builtin/ModuleObject.h"
|
||||
#include "builtin/Object.h"
|
||||
#include "jit/BaselineCacheIRCompiler.h"
|
||||
#include "jit/BaselineFrame.h"
|
||||
#include "jit/BaselineIC.h"
|
||||
#include "jit/CacheIRSpewer.h"
|
||||
#include "jit/InlinableNatives.h"
|
||||
|
@ -11008,13 +11009,13 @@ AttachDecision BinaryArithIRGenerator::tryAttachStringInt32Arith() {
|
|||
NewArrayIRGenerator::NewArrayIRGenerator(JSContext* cx, HandleScript script,
|
||||
jsbytecode* pc, ICState state, JSOp op,
|
||||
HandleObject templateObj,
|
||||
JSScript* outerScript)
|
||||
BaselineFrame* frame)
|
||||
: IRGenerator(cx, script, pc, CacheKind::NewArray, state),
|
||||
#ifdef JS_CACHEIR_SPEW
|
||||
op_(op),
|
||||
#endif
|
||||
templateObject_(templateObj),
|
||||
outerScript_(outerScript) {
|
||||
frame_(frame) {
|
||||
MOZ_ASSERT(templateObject_);
|
||||
}
|
||||
|
||||
|
@ -11026,6 +11027,24 @@ void NewArrayIRGenerator::trackAttached(const char* name) {
|
|||
#endif
|
||||
}
|
||||
|
||||
// Allocation sites are usually created during baseline compilation, but we also
|
||||
// need to created them when an IC stub is added to a baseline compiled script
|
||||
// and when trial inlining.
|
||||
static gc::AllocSite* MaybeCreateAllocSite(jsbytecode* pc,
|
||||
BaselineFrame* frame) {
|
||||
MOZ_ASSERT(BytecodeOpCanHaveAllocSite(JSOp(*pc)));
|
||||
|
||||
JSScript* outerScript = frame->outerScript();
|
||||
bool inInterpreter = frame->runningInInterpreter();
|
||||
bool isInlined = frame->icScript()->isInlined();
|
||||
|
||||
if (inInterpreter && !isInlined) {
|
||||
return outerScript->zone()->unknownAllocSite();
|
||||
}
|
||||
|
||||
return outerScript->createAllocSite();
|
||||
}
|
||||
|
||||
AttachDecision NewArrayIRGenerator::tryAttachArrayObject() {
|
||||
ArrayObject* arrayObj = &templateObject_->as<ArrayObject>();
|
||||
|
||||
|
@ -11047,7 +11066,7 @@ AttachDecision NewArrayIRGenerator::tryAttachArrayObject() {
|
|||
writer.guardNoAllocationMetadataBuilder(
|
||||
cx_->realm()->addressOfMetadataBuilder());
|
||||
|
||||
gc::AllocSite* site = outerScript_->createAllocSite();
|
||||
gc::AllocSite* site = MaybeCreateAllocSite(pc_, frame_);
|
||||
if (!site) {
|
||||
return AttachDecision::NoAction;
|
||||
}
|
||||
|
@ -11075,13 +11094,13 @@ AttachDecision NewArrayIRGenerator::tryAttachStub() {
|
|||
NewObjectIRGenerator::NewObjectIRGenerator(JSContext* cx, HandleScript script,
|
||||
jsbytecode* pc, ICState state,
|
||||
JSOp op, HandleObject templateObj,
|
||||
JSScript* outerScript)
|
||||
BaselineFrame* frame)
|
||||
: IRGenerator(cx, script, pc, CacheKind::NewObject, state),
|
||||
#ifdef JS_CACHEIR_SPEW
|
||||
op_(op),
|
||||
#endif
|
||||
templateObject_(templateObj),
|
||||
outerScript_(outerScript) {
|
||||
frame_(frame) {
|
||||
MOZ_ASSERT(templateObject_);
|
||||
}
|
||||
|
||||
|
@ -11114,7 +11133,7 @@ AttachDecision NewObjectIRGenerator::tryAttachPlainObject() {
|
|||
MOZ_ASSERT(!nativeObj->hasDynamicElements());
|
||||
MOZ_ASSERT(!nativeObj->isSharedMemory());
|
||||
|
||||
gc::AllocSite* site = outerScript_->createAllocSite();
|
||||
gc::AllocSite* site = MaybeCreateAllocSite(pc_, frame_);
|
||||
if (!site) {
|
||||
return AttachDecision::NoAction;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace jit {
|
|||
enum class BaselineCacheIRStubKind;
|
||||
enum class InlinableNative : uint16_t;
|
||||
|
||||
class BaselineFrame;
|
||||
class ICCacheIRStub;
|
||||
class ICScript;
|
||||
class ICStubSpace;
|
||||
|
@ -1923,14 +1924,14 @@ class MOZ_RAII NewArrayIRGenerator : public IRGenerator {
|
|||
JSOp op_;
|
||||
#endif
|
||||
HandleObject templateObject_;
|
||||
JSScript* outerScript_;
|
||||
BaselineFrame* frame_;
|
||||
|
||||
void trackAttached(const char* name);
|
||||
|
||||
public:
|
||||
NewArrayIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc,
|
||||
ICState state, JSOp op, HandleObject templateObj,
|
||||
JSScript* outerScript);
|
||||
BaselineFrame* frame);
|
||||
|
||||
AttachDecision tryAttachStub();
|
||||
AttachDecision tryAttachArrayObject();
|
||||
|
@ -1941,19 +1942,23 @@ class MOZ_RAII NewObjectIRGenerator : public IRGenerator {
|
|||
JSOp op_;
|
||||
#endif
|
||||
HandleObject templateObject_;
|
||||
JSScript* outerScript_;
|
||||
BaselineFrame* frame_;
|
||||
|
||||
void trackAttached(const char* name);
|
||||
|
||||
public:
|
||||
NewObjectIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc,
|
||||
ICState state, JSOp op, HandleObject templateObj,
|
||||
JSScript* outerScript);
|
||||
BaselineFrame* frame);
|
||||
|
||||
AttachDecision tryAttachStub();
|
||||
AttachDecision tryAttachPlainObject();
|
||||
};
|
||||
|
||||
inline bool BytecodeOpCanHaveAllocSite(JSOp op) {
|
||||
return op == JSOp::NewArray || op == JSOp::NewObject || op == JSOp::NewInit;
|
||||
}
|
||||
|
||||
// Retrieve Xray JIT info set by the embedder.
|
||||
extern JS::XrayJitInfo* GetXrayJitInfo();
|
||||
|
||||
|
|
|
@ -1117,6 +1117,9 @@ T* CacheIRStubInfo::getPtrStubField(Stub* stub, uint32_t offset) const {
|
|||
return *reinterpret_cast<T**>(stubData + offset);
|
||||
}
|
||||
|
||||
template gc::AllocSite* CacheIRStubInfo::getPtrStubField(ICCacheIRStub* stub,
|
||||
uint32_t offset) const;
|
||||
|
||||
template <typename T, typename V>
|
||||
static void InitGCPtr(uintptr_t* ptr, V val) {
|
||||
AsGCPtr<T>(ptr)->init(mozilla::BitwiseCast<T>(val));
|
||||
|
|
Загрузка…
Ссылка в новой задаче