mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 01:05:45 +00:00
Bug 1551796 part 3 - Merge ICScript into JitScript. r=tcampbell
ICScript and JitScript had the same lifetime already, but this eliminates a malloc/free and some extra dereferences (especially for accessing ICEntries from Baseline Interpreter code). This is just the minimal set of changes to make it easier to review. Follow-up changes should: * Move (now) JitScript methods to JitScript.cpp * Merge FillBytecodeTypeMap with JitScript::initICEntries so we do just a single bytecode walk. * Move JitScript from the js namespace to js::jit. Differential Revision: https://phabricator.services.mozilla.com/D32103 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
d68e697c37
commit
932197282d
@ -255,16 +255,14 @@ void Zone::discardJitCode(FreeOp* fop,
|
||||
script->maybeReleaseJitScript();
|
||||
}
|
||||
|
||||
// The optimizedStubSpace will be purged below so make sure ICScript
|
||||
// doesn't point into it. We do this after (potentially) releasing types
|
||||
// because JitScript contains the ICScript* and there's no need to
|
||||
// purge stubs if we just destroyed the Typescript.
|
||||
if (discardBaselineCode && script->hasICScript()) {
|
||||
script->icScript()->purgeOptimizedStubs(script);
|
||||
}
|
||||
|
||||
// Finally, reset the active flag.
|
||||
if (JitScript* jitScript = script->jitScript()) {
|
||||
// If we did not release the JitScript, we need to purge optimized IC
|
||||
// stubs because the optimizedStubSpace will be purged below.
|
||||
if (discardBaselineCode) {
|
||||
jitScript->purgeOptimizedStubs(script);
|
||||
}
|
||||
|
||||
// Finally, reset the active flag.
|
||||
jitScript->resetActive();
|
||||
}
|
||||
}
|
||||
@ -527,10 +525,11 @@ void MemoryTracker::adopt(MemoryTracker& other) {
|
||||
|
||||
static const char* MemoryUseName(MemoryUse use) {
|
||||
switch (use) {
|
||||
#define DEFINE_CASE(Name) \
|
||||
case MemoryUse::Name: return #Name;
|
||||
JS_FOR_EACH_MEMORY_USE(DEFINE_CASE)
|
||||
#undef DEFINE_CASE
|
||||
# define DEFINE_CASE(Name) \
|
||||
case MemoryUse::Name: \
|
||||
return #Name;
|
||||
JS_FOR_EACH_MEMORY_USE(DEFINE_CASE)
|
||||
# undef DEFINE_CASE
|
||||
}
|
||||
|
||||
MOZ_CRASH("Unknown memory use");
|
||||
@ -551,8 +550,7 @@ MemoryTracker::~MemoryTracker() {
|
||||
|
||||
fprintf(stderr, "Missing calls to JS::RemoveAssociatedMemory:\n");
|
||||
for (auto r = map.all(); !r.empty(); r.popFront()) {
|
||||
fprintf(stderr, " %p 0x%zx %s\n", r.front().key().cell,
|
||||
r.front().value(),
|
||||
fprintf(stderr, " %p 0x%zx %s\n", r.front().key().cell, r.front().value(),
|
||||
MemoryUseName(r.front().key().use));
|
||||
}
|
||||
|
||||
|
@ -1073,7 +1073,7 @@ static bool InitFromBailout(JSContext* cx, size_t frameNo, HandleFunction fun,
|
||||
|
||||
const uint32_t pcOff = script->pcToOffset(pc);
|
||||
BaselineScript* baselineScript = script->baselineScript();
|
||||
ICScript* icScript = script->icScript();
|
||||
JitScript* jitScript = script->jitScript();
|
||||
|
||||
#ifdef DEBUG
|
||||
uint32_t expectedDepth;
|
||||
@ -1136,7 +1136,7 @@ static bool InitFromBailout(JSContext* cx, size_t frameNo, HandleFunction fun,
|
||||
// Not every monitored op has a monitored fallback stub, e.g.
|
||||
// JSOP_NEWOBJECT, which always returns the same type for a
|
||||
// particular script/pc location.
|
||||
ICEntry& icEntry = icScript->icEntryFromPCOffset(pcOff);
|
||||
ICEntry& icEntry = jitScript->icEntryFromPCOffset(pcOff);
|
||||
ICFallbackStub* fallbackStub = icEntry.firstStub()->getChainFallback();
|
||||
if (fallbackStub->isMonitoredFallback()) {
|
||||
enterMonitorChain = true;
|
||||
@ -1153,7 +1153,7 @@ static bool InitFromBailout(JSContext* cx, size_t frameNo, HandleFunction fun,
|
||||
builder.setResumeFramePtr(prevFramePtr);
|
||||
|
||||
if (enterMonitorChain) {
|
||||
ICEntry& icEntry = icScript->icEntryFromPCOffset(pcOff);
|
||||
ICEntry& icEntry = jitScript->icEntryFromPCOffset(pcOff);
|
||||
ICFallbackStub* fallbackStub = icEntry.firstStub()->getChainFallback();
|
||||
MOZ_ASSERT(fallbackStub->isMonitoredFallback());
|
||||
JitSpew(JitSpew_BaselineBailouts, " [TYPE-MONITOR CHAIN]");
|
||||
@ -1337,7 +1337,7 @@ static bool InitFromBailout(JSContext* cx, size_t frameNo, HandleFunction fun,
|
||||
|
||||
// Calculate and write out return address.
|
||||
// The icEntry in question MUST have an inlinable fallback stub.
|
||||
ICEntry& icEntry = icScript->icEntryFromPCOffset(pcOff);
|
||||
ICEntry& icEntry = jitScript->icEntryFromPCOffset(pcOff);
|
||||
MOZ_ASSERT(IsInlinableFallback(icEntry.firstStub()->getChainFallback()));
|
||||
|
||||
RetAddrEntry& retAddrEntry =
|
||||
|
@ -542,8 +542,8 @@ bool BaselineCodeGen<Handler>::emitOutOfLinePostBarrierSlot() {
|
||||
|
||||
template <>
|
||||
bool BaselineCompilerCodeGen::emitNextIC() {
|
||||
// Emit a call to an IC stored in ICScript. Calls to this must match the
|
||||
// ICEntry order in ICScript: first the non-op IC entries for |this| and
|
||||
// Emit a call to an IC stored in JitScript. Calls to this must match the
|
||||
// ICEntry order in JitScript: first the non-op IC entries for |this| and
|
||||
// formal arguments, then the for-op IC entries for JOF_IC ops.
|
||||
|
||||
JSScript* script = handler.script();
|
||||
@ -553,7 +553,7 @@ bool BaselineCompilerCodeGen::emitNextIC() {
|
||||
// to loop until we find an ICEntry for the current pc.
|
||||
const ICEntry* entry;
|
||||
do {
|
||||
entry = &script->icScript()->icEntry(handler.icEntryIndex());
|
||||
entry = &script->jitScript()->icEntry(handler.icEntryIndex());
|
||||
handler.moveToNextICEntry();
|
||||
} while (entry->pcOffset() < pcOffset);
|
||||
|
||||
@ -1112,9 +1112,8 @@ void BaselineInterpreterCodeGen::emitInitFrameFields() {
|
||||
|
||||
// Initialize interpreterICEntry.
|
||||
masm.loadPtr(Address(scratch1, JSScript::offsetOfJitScript()), scratch2);
|
||||
masm.loadPtr(Address(scratch2, JitScript::offsetOfICScript()), scratch2);
|
||||
masm.computeEffectiveAddress(Address(scratch2, ICScript::offsetOfICEntries()),
|
||||
scratch2);
|
||||
masm.computeEffectiveAddress(
|
||||
Address(scratch2, JitScript::offsetOfICEntries()), scratch2);
|
||||
masm.storePtr(scratch2, frame.addressOfInterpreterICEntry());
|
||||
|
||||
// Initialize interpreterPC.
|
||||
@ -6266,9 +6265,8 @@ bool BaselineInterpreterCodeGen::emit_JSOP_JUMPTARGET() {
|
||||
// Compute ICEntry* and store to frame->interpreterICEntry.
|
||||
loadScript(scratch2);
|
||||
masm.loadPtr(Address(scratch2, JSScript::offsetOfJitScript()), scratch2);
|
||||
masm.loadPtr(Address(scratch2, JitScript::offsetOfICScript()), scratch2);
|
||||
masm.computeEffectiveAddress(
|
||||
BaseIndex(scratch2, scratch1, TimesOne, ICScript::offsetOfICEntries()),
|
||||
BaseIndex(scratch2, scratch1, TimesOne, JitScript::offsetOfICEntries()),
|
||||
scratch2);
|
||||
masm.storePtr(scratch2, frame.addressOfInterpreterICEntry());
|
||||
return true;
|
||||
|
@ -526,7 +526,7 @@ class BaselineCompilerHandler {
|
||||
JSScript* script_;
|
||||
jsbytecode* pc_;
|
||||
|
||||
// Index of the current ICEntry in the script's ICScript.
|
||||
// Index of the current ICEntry in the script's JitScript.
|
||||
uint32_t icEntryIndex_;
|
||||
|
||||
bool compileDebugInstrumentation_;
|
||||
|
@ -110,9 +110,9 @@ bool BaselineFrame::pushVarEnvironment(JSContext* cx, HandleScope scope) {
|
||||
|
||||
void BaselineFrame::setInterpreterPC(jsbytecode* pc) {
|
||||
uint32_t pcOffset = script()->pcToOffset(pc);
|
||||
ICScript* icScript = script()->icScript();
|
||||
JitScript* jitScript = script()->jitScript();
|
||||
interpreterPC_ = pc;
|
||||
interpreterICEntry_ = icScript->interpreterICEntryFromPCOffset(pcOffset);
|
||||
interpreterICEntry_ = jitScript->interpreterICEntryFromPCOffset(pcOffset);
|
||||
}
|
||||
|
||||
bool BaselineFrame::initForOsr(InterpreterFrame* fp, uint32_t numStackValues) {
|
||||
|
@ -156,36 +156,25 @@ class MOZ_RAII FallbackStubAllocator {
|
||||
}
|
||||
};
|
||||
|
||||
/* static */
|
||||
UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
} // namespace jit
|
||||
|
||||
bool JitScript::initICEntries(JSContext* cx, JSScript* script) {
|
||||
MOZ_ASSERT(cx->realm()->jitRealm());
|
||||
MOZ_ASSERT(jit::IsBaselineEnabled(cx));
|
||||
|
||||
const uint32_t numICEntries = script->numICEntries();
|
||||
MOZ_ASSERT(numICEntries() == script->numICEntries());
|
||||
|
||||
// Allocate the ICScript.
|
||||
UniquePtr<ICScript> icScript(
|
||||
script->zone()->pod_malloc_with_extra<ICScript, ICEntry>(numICEntries));
|
||||
if (!icScript) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
new (icScript.get()) ICScript(numICEntries);
|
||||
// TODO(bug 1551796): move JitScript into jit namespace so we don't need this.
|
||||
using namespace js::jit;
|
||||
|
||||
// We need to call prepareForDestruction on ICScript before we |delete| it.
|
||||
auto prepareForDestruction = mozilla::MakeScopeExit(
|
||||
[&] { icScript->prepareForDestruction(cx->zone()); });
|
||||
|
||||
FallbackStubAllocator alloc(cx, icScript->fallbackStubSpace_);
|
||||
FallbackStubAllocator alloc(cx, fallbackStubSpace_);
|
||||
|
||||
// Index of the next ICEntry to initialize.
|
||||
uint32_t icEntryIndex = 0;
|
||||
|
||||
using Kind = BaselineICFallbackKind;
|
||||
|
||||
ICScript* icScriptPtr = icScript.get();
|
||||
auto addIC = [cx, icScriptPtr, &icEntryIndex, script](jsbytecode* pc,
|
||||
ICStub* stub) {
|
||||
auto addIC = [cx, this, &icEntryIndex, script](jsbytecode* pc, ICStub* stub) {
|
||||
if (!stub) {
|
||||
MOZ_ASSERT(cx->isExceptionPending());
|
||||
mozilla::Unused << cx; // Silence -Wunused-lambda-capture in opt builds.
|
||||
@ -194,7 +183,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
|
||||
// Initialize the ICEntry.
|
||||
uint32_t offset = pc ? script->pcToOffset(pc) : ICEntry::ProloguePCOffset;
|
||||
ICEntry& entryRef = icScriptPtr->icEntry(icEntryIndex);
|
||||
ICEntry& entryRef = icEntry(icEntryIndex);
|
||||
icEntryIndex++;
|
||||
new (&entryRef) ICEntry(stub, offset);
|
||||
|
||||
@ -215,14 +204,14 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor, nullptr, 0);
|
||||
if (!addIC(nullptr, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < fun->nargs(); i++) {
|
||||
ICStub* stub = alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor,
|
||||
nullptr, i + 1);
|
||||
if (!addIC(nullptr, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -248,7 +237,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_IFNE: {
|
||||
ICStub* stub = alloc.newStub<ICToBool_Fallback>(Kind::ToBool);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -258,7 +247,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_DEC: {
|
||||
ICStub* stub = alloc.newStub<ICUnaryArith_Fallback>(Kind::UnaryArith);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -276,7 +265,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_POW: {
|
||||
ICStub* stub = alloc.newStub<ICBinaryArith_Fallback>(Kind::BinaryArith);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -290,7 +279,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_STRICTNE: {
|
||||
ICStub* stub = alloc.newStub<ICCompare_Fallback>(Kind::Compare);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -298,7 +287,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICWarmUpCounter_Fallback>(Kind::WarmUpCounter);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -306,12 +295,12 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
ObjectGroup* group =
|
||||
ObjectGroup::allocationSiteGroup(cx, script, pc, JSProto_Array);
|
||||
if (!group) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICNewArray_Fallback>(Kind::NewArray, group);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -319,7 +308,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_NEWINIT: {
|
||||
ICStub* stub = alloc.newStub<ICNewObject_Fallback>(Kind::NewObject);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -331,7 +320,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_STRICTSETELEM: {
|
||||
ICStub* stub = alloc.newStub<ICSetElem_Fallback>(Kind::SetElem);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -347,7 +336,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_STRICTSETGNAME: {
|
||||
ICStub* stub = alloc.newStub<ICSetProp_Fallback>(Kind::SetProp);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -357,14 +346,14 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_GETBOUNDNAME: {
|
||||
ICStub* stub = alloc.newStub<ICGetProp_Fallback>(Kind::GetProp);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_GETPROP_SUPER: {
|
||||
ICStub* stub = alloc.newStub<ICGetProp_Fallback>(Kind::GetPropSuper);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -372,28 +361,28 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_CALLELEM: {
|
||||
ICStub* stub = alloc.newStub<ICGetElem_Fallback>(Kind::GetElem);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_GETELEM_SUPER: {
|
||||
ICStub* stub = alloc.newStub<ICGetElem_Fallback>(Kind::GetElemSuper);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_IN: {
|
||||
ICStub* stub = alloc.newStub<ICIn_Fallback>(Kind::In);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_HASOWN: {
|
||||
ICStub* stub = alloc.newStub<ICHasOwn_Fallback>(Kind::HasOwn);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -401,7 +390,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_GETGNAME: {
|
||||
ICStub* stub = alloc.newStub<ICGetName_Fallback>(Kind::GetName);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -409,7 +398,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_BINDGNAME: {
|
||||
ICStub* stub = alloc.newStub<ICBindName_Fallback>(Kind::BindName);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -418,7 +407,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICTypeMonitor_Fallback>(Kind::TypeMonitor, nullptr);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -426,7 +415,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICGetIntrinsic_Fallback>(Kind::GetIntrinsic);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -439,7 +428,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_STRICTEVAL: {
|
||||
ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::Call);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -447,7 +436,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_NEW: {
|
||||
ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::CallConstructing);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -456,7 +445,7 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_STRICTSPREADEVAL: {
|
||||
ICStub* stub = alloc.newStub<ICCall_Fallback>(Kind::SpreadCall);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -465,14 +454,14 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICCall_Fallback>(Kind::SpreadCallConstructing);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_INSTANCEOF: {
|
||||
ICStub* stub = alloc.newStub<ICInstanceOf_Fallback>(Kind::InstanceOf);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -480,14 +469,14 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
case JSOP_TYPEOFEXPR: {
|
||||
ICStub* stub = alloc.newStub<ICTypeOf_Fallback>(Kind::TypeOf);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_ITER: {
|
||||
ICStub* stub = alloc.newStub<ICGetIterator_Fallback>(Kind::GetIterator);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -496,12 +485,12 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
cx, nullptr, 0, TenuredObject,
|
||||
ObjectGroup::NewArrayKind::UnknownIndex);
|
||||
if (!templateObject) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
ICStub* stub =
|
||||
alloc.newStub<ICRest_Fallback>(Kind::Rest, templateObject);
|
||||
if (!addIC(pc, stub)) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -511,13 +500,13 @@ UniquePtr<ICScript> ICScript::create(JSContext* cx, JSScript* script) {
|
||||
}
|
||||
|
||||
// Assert all ICEntries have been initialized.
|
||||
MOZ_ASSERT(icEntryIndex == numICEntries);
|
||||
MOZ_ASSERT(icEntryIndex == numICEntries());
|
||||
|
||||
prepareForDestruction.release();
|
||||
|
||||
return icScript;
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace jit {
|
||||
|
||||
ICStubConstIterator& ICStubConstIterator::operator++() {
|
||||
MOZ_ASSERT(currentStub_ != nullptr);
|
||||
currentStub_ = currentStub_->next();
|
||||
@ -1098,7 +1087,7 @@ bool ICMonitoredFallbackStub::initMonitoringChain(JSContext* cx,
|
||||
JSScript* script) {
|
||||
MOZ_ASSERT(fallbackMonitorStub_ == nullptr);
|
||||
|
||||
ICStubSpace* space = script->icScript()->fallbackStubSpace();
|
||||
ICStubSpace* space = script->jitScript()->fallbackStubSpace();
|
||||
FallbackStubAllocator alloc(cx, *space);
|
||||
auto* stub = alloc.newStub<ICTypeMonitor_Fallback>(
|
||||
BaselineICFallbackKind::TypeMonitor, this);
|
||||
@ -1152,7 +1141,7 @@ bool ICCacheIR_Updated::initUpdatingChain(JSContext* cx, ICStubSpace* space) {
|
||||
ICStubSpace* ICStubCompiler::StubSpaceForStub(bool makesGCCalls,
|
||||
JSScript* script) {
|
||||
if (makesGCCalls) {
|
||||
return script->icScript()->fallbackStubSpace();
|
||||
return script->jitScript()->fallbackStubSpace();
|
||||
}
|
||||
return script->zone()->jitZone()->optimizedStubSpace();
|
||||
}
|
||||
@ -1297,15 +1286,19 @@ void ICStubCompilerBase::PushStubPayload(MacroAssembler& masm,
|
||||
masm.adjustFrame(sizeof(intptr_t));
|
||||
}
|
||||
|
||||
void ICScript::noteAccessedGetter(uint32_t pcOffset) {
|
||||
ICEntry& entry = icEntryFromPCOffset(pcOffset);
|
||||
ICFallbackStub* stub = entry.fallbackStub();
|
||||
} // namespace jit
|
||||
|
||||
void JitScript::noteAccessedGetter(uint32_t pcOffset) {
|
||||
jit::ICEntry& entry = icEntryFromPCOffset(pcOffset);
|
||||
jit::ICFallbackStub* stub = entry.fallbackStub();
|
||||
|
||||
if (stub->isGetProp_Fallback()) {
|
||||
stub->toGetProp_Fallback()->noteAccessedGetter();
|
||||
}
|
||||
}
|
||||
|
||||
namespace jit {
|
||||
|
||||
// TypeMonitor_Fallback
|
||||
//
|
||||
|
||||
@ -2493,15 +2486,19 @@ bool FallbackICCodeCompiler::emit_SetElem() {
|
||||
return tailCallVM<Fn, DoSetElemFallback>(masm);
|
||||
}
|
||||
|
||||
void ICScript::noteHasDenseAdd(uint32_t pcOffset) {
|
||||
ICEntry& entry = icEntryFromPCOffset(pcOffset);
|
||||
ICFallbackStub* stub = entry.fallbackStub();
|
||||
} // namespace jit
|
||||
|
||||
void JitScript::noteHasDenseAdd(uint32_t pcOffset) {
|
||||
jit::ICEntry& entry = icEntryFromPCOffset(pcOffset);
|
||||
jit::ICFallbackStub* stub = entry.fallbackStub();
|
||||
|
||||
if (stub->isSetElem_Fallback()) {
|
||||
stub->toSetElem_Fallback()->noteHasDenseAdd();
|
||||
}
|
||||
}
|
||||
|
||||
namespace jit {
|
||||
|
||||
template <typename T>
|
||||
void StoreToTypedArray(JSContext* cx, MacroAssembler& masm, Scalar::Type type,
|
||||
const ValueOperand& value, const T& dest,
|
||||
|
@ -269,102 +269,6 @@ class ICEntry {
|
||||
void trace(JSTracer* trc);
|
||||
};
|
||||
|
||||
// [SMDOC] ICScript
|
||||
//
|
||||
// ICScript contains IC data used by Baseline (Ion has its own IC chains, stored
|
||||
// in IonScript).
|
||||
//
|
||||
// For each IC we store an ICEntry, which points to the first ICStub in the
|
||||
// chain. Note that multiple stubs in the same zone can share Baseline IC code.
|
||||
// This works because the stub data is stored in the ICStub instead of baked in
|
||||
// in the stub code.
|
||||
//
|
||||
// Storing this separate from BaselineScript simplifies debug mode OSR because
|
||||
// the ICScript can be reused when we replace the BaselineScript. It also makes
|
||||
// it easier to experiment with interpreter ICs in the future because the
|
||||
// interpreter and Baseline JIT will be able to use exactly the same IC data.
|
||||
//
|
||||
// ICScript contains the following:
|
||||
//
|
||||
// * Fallback stub space: this stores all fallback stubs and the "can GC" stubs.
|
||||
// These stubs are never purged before destroying the ICScript. (Other stubs
|
||||
// are stored in the optimized stub space stored in JitZone and can be
|
||||
// discarded more eagerly. See ICScript::purgeOptimizedStubs.)
|
||||
//
|
||||
// * List of IC entries, in the following order:
|
||||
//
|
||||
// - Type monitor IC for |this|.
|
||||
// - Type monitor IC for each formal argument.
|
||||
// - IC for each JOF_IC bytecode op.
|
||||
//
|
||||
// ICScript is stored in JitScript and allocated/destroyed at the same time.
|
||||
class ICScript {
|
||||
// Allocated space for fallback stubs.
|
||||
FallbackICStubSpace fallbackStubSpace_ = {};
|
||||
|
||||
uint32_t numICEntries_;
|
||||
|
||||
explicit ICScript(uint32_t numICEntries) : numICEntries_(numICEntries) {}
|
||||
|
||||
ICEntry* icEntryList() {
|
||||
return (ICEntry*)(reinterpret_cast<uint8_t*>(this) + sizeof(ICScript));
|
||||
}
|
||||
|
||||
public:
|
||||
static MOZ_MUST_USE js::UniquePtr<ICScript> create(JSContext* cx,
|
||||
JSScript* script);
|
||||
|
||||
~ICScript() {
|
||||
// The contents of the fallback stub space are removed and freed
|
||||
// separately after the next minor GC. See prepareForDestruction.
|
||||
MOZ_ASSERT(fallbackStubSpace_.isEmpty());
|
||||
}
|
||||
void prepareForDestruction(Zone* zone) {
|
||||
// When the script contains pointers to nursery things, the store buffer can
|
||||
// contain entries that point into the fallback stub space. Since we can
|
||||
// destroy scripts outside the context of a GC, this situation could result
|
||||
// in us trying to mark invalid store buffer entries.
|
||||
//
|
||||
// Defer freeing any allocated blocks until after the next minor GC.
|
||||
fallbackStubSpace_.freeAllAfterMinorGC(zone);
|
||||
}
|
||||
|
||||
FallbackICStubSpace* fallbackStubSpace() { return &fallbackStubSpace_; }
|
||||
|
||||
void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t* data,
|
||||
size_t* fallbackStubs) const {
|
||||
*data += mallocSizeOf(this);
|
||||
|
||||
// |data| already includes the ICStubSpace itself, so use
|
||||
// sizeOfExcludingThis.
|
||||
*fallbackStubs += fallbackStubSpace_.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
size_t numICEntries() const { return numICEntries_; }
|
||||
|
||||
ICEntry& icEntry(size_t index) {
|
||||
MOZ_ASSERT(index < numICEntries());
|
||||
return icEntryList()[index];
|
||||
}
|
||||
|
||||
void noteAccessedGetter(uint32_t pcOffset);
|
||||
void noteHasDenseAdd(uint32_t pcOffset);
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
void purgeOptimizedStubs(JSScript* script);
|
||||
|
||||
ICEntry* interpreterICEntryFromPCOffset(uint32_t pcOffset);
|
||||
|
||||
ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset);
|
||||
ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset,
|
||||
ICEntry* prevLookedUpEntry);
|
||||
|
||||
ICEntry& icEntryFromPCOffset(uint32_t pcOffset);
|
||||
ICEntry& icEntryFromPCOffset(uint32_t pcOffset, ICEntry* prevLookedUpEntry);
|
||||
|
||||
static constexpr size_t offsetOfICEntries() { return sizeof(ICScript); }
|
||||
};
|
||||
|
||||
class ICMonitoredStub;
|
||||
class ICMonitoredFallbackStub;
|
||||
|
||||
|
@ -127,7 +127,10 @@ static bool GetCacheIRReceiverForNativeSetSlot(ICCacheIR_Updated* stub,
|
||||
return true;
|
||||
}
|
||||
|
||||
ICScript* BaselineInspector::icScript() const { return script->icScript(); }
|
||||
JitScript* BaselineInspector::jitScript() const {
|
||||
MOZ_ASSERT(script->hasJitScript());
|
||||
return script->jitScript();
|
||||
}
|
||||
|
||||
ICEntry& BaselineInspector::icEntryFromPC(jsbytecode* pc) {
|
||||
ICEntry* entry = maybeICEntryFromPC(pc);
|
||||
@ -136,10 +139,10 @@ ICEntry& BaselineInspector::icEntryFromPC(jsbytecode* pc) {
|
||||
}
|
||||
|
||||
ICEntry* BaselineInspector::maybeICEntryFromPC(jsbytecode* pc) {
|
||||
MOZ_ASSERT(hasICScript());
|
||||
MOZ_ASSERT(hasJitScript());
|
||||
MOZ_ASSERT(isValidPC(pc));
|
||||
ICEntry* ent = icScript()->maybeICEntryFromPCOffset(script->pcToOffset(pc),
|
||||
prevLookedUpEntry);
|
||||
ICEntry* ent = jitScript()->maybeICEntryFromPCOffset(script->pcToOffset(pc),
|
||||
prevLookedUpEntry);
|
||||
if (!ent) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -156,7 +159,7 @@ bool BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc,
|
||||
// uncacheable access.
|
||||
MOZ_ASSERT(receivers.empty());
|
||||
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -203,7 +206,7 @@ bool BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc,
|
||||
}
|
||||
|
||||
ICStub* BaselineInspector::monomorphicStub(jsbytecode* pc) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -227,7 +230,7 @@ ICStub* BaselineInspector::monomorphicStub(jsbytecode* pc) {
|
||||
|
||||
bool BaselineInspector::dimorphicStub(jsbytecode* pc, ICStub** pfirst,
|
||||
ICStub** psecond) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -575,7 +578,7 @@ static bool TryToSpecializeBinaryArithOp(ICStub** stubs, uint32_t nstubs,
|
||||
}
|
||||
|
||||
MIRType BaselineInspector::expectedBinaryArithSpecialization(jsbytecode* pc) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return MIRType::None;
|
||||
}
|
||||
|
||||
@ -610,7 +613,7 @@ MIRType BaselineInspector::expectedBinaryArithSpecialization(jsbytecode* pc) {
|
||||
}
|
||||
|
||||
bool BaselineInspector::hasSeenNonIntegerIndex(jsbytecode* pc) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -623,7 +626,7 @@ bool BaselineInspector::hasSeenNonIntegerIndex(jsbytecode* pc) {
|
||||
}
|
||||
|
||||
bool BaselineInspector::hasSeenNegativeIndexGetElement(jsbytecode* pc) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -637,7 +640,7 @@ bool BaselineInspector::hasSeenNegativeIndexGetElement(jsbytecode* pc) {
|
||||
}
|
||||
|
||||
bool BaselineInspector::hasSeenAccessedGetter(jsbytecode* pc) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -651,7 +654,7 @@ bool BaselineInspector::hasSeenAccessedGetter(jsbytecode* pc) {
|
||||
}
|
||||
|
||||
bool BaselineInspector::hasSeenDoubleResult(jsbytecode* pc) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -720,7 +723,7 @@ JSObject* MaybeTemplateObject(ICStub* stub, MetaTwoByteKind kind,
|
||||
}
|
||||
|
||||
JSObject* BaselineInspector::getTemplateObject(jsbytecode* pc) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -760,7 +763,7 @@ JSObject* BaselineInspector::getTemplateObject(jsbytecode* pc) {
|
||||
}
|
||||
|
||||
ObjectGroup* BaselineInspector::getTemplateObjectGroup(jsbytecode* pc) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -780,7 +783,7 @@ ObjectGroup* BaselineInspector::getTemplateObjectGroup(jsbytecode* pc) {
|
||||
JSFunction* BaselineInspector::getSingleCallee(jsbytecode* pc) {
|
||||
MOZ_ASSERT(*pc == JSOP_NEW);
|
||||
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -815,7 +818,7 @@ JSFunction* BaselineInspector::getSingleCallee(jsbytecode* pc) {
|
||||
|
||||
JSObject* BaselineInspector::getTemplateObjectForNative(jsbytecode* pc,
|
||||
Native native) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -845,7 +848,7 @@ JSObject* BaselineInspector::getTemplateObjectForNative(jsbytecode* pc,
|
||||
|
||||
JSObject* BaselineInspector::getTemplateObjectForClassHook(jsbytecode* pc,
|
||||
const Class* clasp) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1204,7 +1207,7 @@ bool BaselineInspector::commonGetPropFunction(
|
||||
jsbytecode* pc, jsid id, bool innerized, JSObject** holder,
|
||||
Shape** holderShape, JSFunction** commonGetter, Shape** globalShape,
|
||||
bool* isOwnProperty, ReceiverVector& receivers) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1286,7 +1289,7 @@ static JSFunction* GetMegamorphicGetterSetterFunction(
|
||||
|
||||
bool BaselineInspector::megamorphicGetterSetterFunction(
|
||||
jsbytecode* pc, jsid id, bool isGetter, JSFunction** getterOrSetter) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1451,7 +1454,7 @@ bool BaselineInspector::commonSetPropFunction(jsbytecode* pc, JSObject** holder,
|
||||
JSFunction** commonSetter,
|
||||
bool* isOwnProperty,
|
||||
ReceiverVector& receivers) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1551,7 +1554,7 @@ bool BaselineInspector::maybeInfoForProtoReadSlot(jsbytecode* pc,
|
||||
MOZ_ASSERT(receivers.empty());
|
||||
MOZ_ASSERT(!*holder);
|
||||
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1614,7 +1617,7 @@ static MIRType GetCacheIRExpectedInputType(ICCacheIR_Monitored* stub) {
|
||||
}
|
||||
|
||||
MIRType BaselineInspector::expectedPropertyAccessInputType(jsbytecode* pc) {
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return MIRType::Value;
|
||||
}
|
||||
|
||||
@ -1653,7 +1656,7 @@ bool BaselineInspector::instanceOfData(jsbytecode* pc, Shape** shape,
|
||||
uint32_t* slot,
|
||||
JSObject** prototypeObject) {
|
||||
MOZ_ASSERT(*pc == JSOP_INSTANCEOF);
|
||||
if (!hasICScript()) {
|
||||
if (!hasJitScript()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -47,9 +47,9 @@ class BaselineInspector {
|
||||
MOZ_ASSERT(script);
|
||||
}
|
||||
|
||||
bool hasICScript() const { return script->hasICScript(); }
|
||||
bool hasJitScript() const { return script->hasJitScript(); }
|
||||
|
||||
ICScript* icScript() const;
|
||||
JitScript* jitScript() const;
|
||||
|
||||
private:
|
||||
#ifdef DEBUG
|
||||
@ -63,7 +63,7 @@ class BaselineInspector {
|
||||
ICInspectorType makeICInspector(jsbytecode* pc,
|
||||
ICStub::Kind expectedFallbackKind) {
|
||||
ICEntry* ent = nullptr;
|
||||
if (hasICScript()) {
|
||||
if (hasJitScript()) {
|
||||
ent = &icEntryFromPC(pc);
|
||||
MOZ_ASSERT(ent->fallbackStub()->kind() == expectedFallbackKind);
|
||||
}
|
||||
|
@ -517,7 +517,7 @@ void BaselineScript::trace(JSTracer* trc) {
|
||||
TraceNullableEdge(trc, &templateEnv_, "baseline-template-environment");
|
||||
}
|
||||
|
||||
void ICScript::trace(JSTracer* trc) {
|
||||
void JitScript::trace(JSTracer* trc) {
|
||||
// Mark all IC stub codes hanging off the IC stub entries.
|
||||
for (size_t i = 0; i < numICEntries(); i++) {
|
||||
ICEntry& ent = icEntry(i);
|
||||
@ -620,12 +620,12 @@ CompactBufferReader BaselineScript::pcMappingReader(size_t indexEntry) {
|
||||
}
|
||||
|
||||
struct ICEntries {
|
||||
ICScript* const icScript_;
|
||||
JitScript* const jitScript_;
|
||||
|
||||
explicit ICEntries(ICScript* icScript) : icScript_(icScript) {}
|
||||
explicit ICEntries(JitScript* jitScript) : jitScript_(jitScript) {}
|
||||
|
||||
size_t numEntries() const { return icScript_->numICEntries(); }
|
||||
ICEntry& operator[](size_t index) const { return icScript_->icEntry(index); }
|
||||
size_t numEntries() const { return jitScript_->numICEntries(); }
|
||||
ICEntry& operator[](size_t index) const { return jitScript_->icEntry(index); }
|
||||
};
|
||||
|
||||
struct RetAddrEntries {
|
||||
@ -712,7 +712,7 @@ uint8_t* BaselineScript::returnAddressForEntry(const RetAddrEntry& ent) {
|
||||
return method()->raw() + ent.returnOffset().offset();
|
||||
}
|
||||
|
||||
ICEntry* ICScript::maybeICEntryFromPCOffset(uint32_t pcOffset) {
|
||||
ICEntry* JitScript::maybeICEntryFromPCOffset(uint32_t pcOffset) {
|
||||
// This method ignores prologue IC entries. There can be at most one
|
||||
// non-prologue IC per bytecode op.
|
||||
|
||||
@ -729,14 +729,14 @@ ICEntry* ICScript::maybeICEntryFromPCOffset(uint32_t pcOffset) {
|
||||
return &entry;
|
||||
}
|
||||
|
||||
ICEntry& ICScript::icEntryFromPCOffset(uint32_t pcOffset) {
|
||||
ICEntry& JitScript::icEntryFromPCOffset(uint32_t pcOffset) {
|
||||
ICEntry* entry = maybeICEntryFromPCOffset(pcOffset);
|
||||
MOZ_RELEASE_ASSERT(entry);
|
||||
return *entry;
|
||||
}
|
||||
|
||||
ICEntry* ICScript::maybeICEntryFromPCOffset(uint32_t pcOffset,
|
||||
ICEntry* prevLookedUpEntry) {
|
||||
ICEntry* JitScript::maybeICEntryFromPCOffset(uint32_t pcOffset,
|
||||
ICEntry* prevLookedUpEntry) {
|
||||
// Do a linear forward search from the last queried PC offset, or fallback to
|
||||
// a binary search if the last offset is too far away.
|
||||
if (prevLookedUpEntry && pcOffset >= prevLookedUpEntry->pcOffset() &&
|
||||
@ -756,14 +756,14 @@ ICEntry* ICScript::maybeICEntryFromPCOffset(uint32_t pcOffset,
|
||||
return maybeICEntryFromPCOffset(pcOffset);
|
||||
}
|
||||
|
||||
ICEntry& ICScript::icEntryFromPCOffset(uint32_t pcOffset,
|
||||
ICEntry* prevLookedUpEntry) {
|
||||
ICEntry& JitScript::icEntryFromPCOffset(uint32_t pcOffset,
|
||||
ICEntry* prevLookedUpEntry) {
|
||||
ICEntry* entry = maybeICEntryFromPCOffset(pcOffset, prevLookedUpEntry);
|
||||
MOZ_RELEASE_ASSERT(entry);
|
||||
return *entry;
|
||||
}
|
||||
|
||||
ICEntry* ICScript::interpreterICEntryFromPCOffset(uint32_t pcOffset) {
|
||||
ICEntry* JitScript::interpreterICEntryFromPCOffset(uint32_t pcOffset) {
|
||||
// We have to return the entry to store in BaselineFrame::interpreterICEntry
|
||||
// when resuming in the Baseline Interpreter at pcOffset. The bytecode op at
|
||||
// pcOffset does not necessarily have an ICEntry, so we want to return the
|
||||
@ -1197,8 +1197,8 @@ void BaselineInterpreter::toggleCodeCoverageInstrumentation(bool enable) {
|
||||
toggleCodeCoverageInstrumentationUnchecked(enable);
|
||||
}
|
||||
|
||||
void ICScript::purgeOptimizedStubs(JSScript* script) {
|
||||
MOZ_ASSERT(script->icScript() == this);
|
||||
void JitScript::purgeOptimizedStubs(JSScript* script) {
|
||||
MOZ_ASSERT(script->jitScript() == this);
|
||||
|
||||
Zone* zone = script->zone();
|
||||
if (zone->isGCSweeping() && IsAboutToBeFinalizedDuringSweep(*script)) {
|
||||
@ -1294,18 +1294,18 @@ bool HasEnteredCounters(ICEntry& entry) {
|
||||
}
|
||||
|
||||
void jit::JitSpewBaselineICStats(JSScript* script, const char* dumpReason) {
|
||||
MOZ_ASSERT(script->hasICScript());
|
||||
MOZ_ASSERT(script->hasJitScript());
|
||||
JSContext* cx = TlsContext.get();
|
||||
AutoStructuredSpewer spew(cx, SpewChannel::BaselineICStats, script);
|
||||
if (!spew) {
|
||||
return;
|
||||
}
|
||||
|
||||
ICScript* icScript = script->icScript();
|
||||
JitScript* jitScript = script->jitScript();
|
||||
spew->property("reason", dumpReason);
|
||||
spew->beginListProperty("entries");
|
||||
for (size_t i = 0; i < icScript->numICEntries(); i++) {
|
||||
ICEntry& entry = icScript->icEntry(i);
|
||||
for (size_t i = 0; i < jitScript->numICEntries(); i++) {
|
||||
ICEntry& entry = jitScript->icEntry(i);
|
||||
if (!HasEnteredCounters(entry)) {
|
||||
continue;
|
||||
}
|
||||
@ -1352,13 +1352,7 @@ void jit::FinishDiscardBaselineScript(FreeOp* fop, JSScript* script) {
|
||||
|
||||
void jit::AddSizeOfBaselineData(JSScript* script,
|
||||
mozilla::MallocSizeOf mallocSizeOf,
|
||||
size_t* data, size_t* fallbackStubs) {
|
||||
if (script->hasICScript()) {
|
||||
// ICScript is stored in JitScript but we report its size here and not
|
||||
// in JitScript::sizeOfIncludingThis.
|
||||
script->icScript()->addSizeOfIncludingThis(mallocSizeOf, data,
|
||||
fallbackStubs);
|
||||
}
|
||||
size_t* data) {
|
||||
if (script->hasBaselineScript()) {
|
||||
script->baselineScript()->addSizeOfIncludingThis(mallocSizeOf, data);
|
||||
}
|
||||
|
@ -575,7 +575,7 @@ bool BaselineCompileFromBaselineInterpreter(JSContext* cx, BaselineFrame* frame,
|
||||
void FinishDiscardBaselineScript(FreeOp* fop, JSScript* script);
|
||||
|
||||
void AddSizeOfBaselineData(JSScript* script, mozilla::MallocSizeOf mallocSizeOf,
|
||||
size_t* data, size_t* fallbackStubs);
|
||||
size_t* data);
|
||||
|
||||
void ToggleBaselineProfiling(JSRuntime* runtime, bool enable);
|
||||
|
||||
|
@ -3146,8 +3146,8 @@ void jit::TraceJitScripts(JSTracer* trc, JSScript* script) {
|
||||
jit::BaselineScript::Trace(trc, script->baselineScript());
|
||||
}
|
||||
|
||||
if (script->hasICScript()) {
|
||||
script->icScript()->trace(trc);
|
||||
if (script->hasJitScript()) {
|
||||
script->jitScript()->trace(trc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "vm/TypeInference-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
static void FillBytecodeTypeMap(JSScript* script, uint32_t* bytecodeMap) {
|
||||
uint32_t added = 0;
|
||||
@ -35,28 +36,28 @@ static void FillBytecodeTypeMap(JSScript* script, uint32_t* bytecodeMap) {
|
||||
}
|
||||
|
||||
static size_t NumTypeSets(JSScript* script) {
|
||||
size_t num = script->numBytecodeTypeSets() + 1 /* this */;
|
||||
if (JSFunction* fun = script->functionNonDelazifying()) {
|
||||
num += fun->nargs();
|
||||
}
|
||||
|
||||
// We rely on |num| being in a safe range to prevent overflow when allocating
|
||||
// JitScript.
|
||||
// We rely on |num| not overflowing below.
|
||||
static_assert(JSScript::MaxBytecodeTypeSets == UINT16_MAX,
|
||||
"JSScript typesets should have safe range to avoid overflow");
|
||||
static_assert(JSFunction::NArgsBits == 16,
|
||||
"JSFunction nargs should have safe range to avoid overflow");
|
||||
|
||||
size_t num = script->numBytecodeTypeSets() + 1 /* this */;
|
||||
if (JSFunction* fun = script->functionNonDelazifying()) {
|
||||
num += fun->nargs();
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
JitScript::JitScript(JSScript* script, ICScriptPtr&& icScript,
|
||||
uint32_t numTypeSets)
|
||||
: icScript_(std::move(icScript)), numTypeSets_(numTypeSets) {
|
||||
JitScript::JitScript(JSScript* script, uint32_t typeSetOffset,
|
||||
uint32_t bytecodeTypeMapOffset)
|
||||
: typeSetOffset_(typeSetOffset),
|
||||
bytecodeTypeMapOffset_(bytecodeTypeMapOffset) {
|
||||
setTypesGeneration(script->zone()->types.generation);
|
||||
|
||||
StackTypeSet* array = typeArrayDontCheckGeneration();
|
||||
for (unsigned i = 0; i < numTypeSets; i++) {
|
||||
for (uint32_t i = 0, len = numTypeSets(); i < len; i++) {
|
||||
new (&array[i]) StackTypeSet();
|
||||
}
|
||||
|
||||
@ -84,38 +85,52 @@ bool JSScript::createJitScript(JSContext* cx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
UniquePtr<jit::ICScript> icScript(jit::ICScript::create(cx, this));
|
||||
if (!icScript) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We need to call prepareForDestruction on ICScript before we |delete| it.
|
||||
auto prepareForDestruction = mozilla::MakeScopeExit(
|
||||
[&] { icScript->prepareForDestruction(cx->zone()); });
|
||||
|
||||
size_t numTypeSets = NumTypeSets(this);
|
||||
size_t bytecodeTypeMapEntries = numBytecodeTypeSets();
|
||||
|
||||
// Calculate allocation size. This cannot overflow, see comment in
|
||||
// NumTypeSets.
|
||||
static_assert(sizeof(JitScript) ==
|
||||
sizeof(StackTypeSet) + offsetof(JitScript, typeArray_),
|
||||
"typeArray_ must be last member of JitScript");
|
||||
size_t allocSize =
|
||||
(offsetof(JitScript, typeArray_) + numTypeSets * sizeof(StackTypeSet) +
|
||||
bytecodeTypeMapEntries * sizeof(uint32_t));
|
||||
static_assert(sizeof(JitScript) % sizeof(uintptr_t) == 0,
|
||||
"Trailing arrays must be aligned properly");
|
||||
static_assert(sizeof(ICEntry) % sizeof(uintptr_t) == 0,
|
||||
"Trailing arrays must be aligned properly");
|
||||
static_assert(sizeof(StackTypeSet) % sizeof(uintptr_t) == 0,
|
||||
"Trailing arrays must be aligned properly");
|
||||
|
||||
auto jitScript =
|
||||
reinterpret_cast<JitScript*>(cx->pod_malloc<uint8_t>(allocSize));
|
||||
if (!jitScript) {
|
||||
// Calculate allocation size.
|
||||
CheckedInt<uint32_t> allocSize = sizeof(JitScript);
|
||||
allocSize += CheckedInt<uint32_t>(numICEntries()) * sizeof(ICEntry);
|
||||
allocSize += CheckedInt<uint32_t>(numTypeSets) * sizeof(StackTypeSet);
|
||||
allocSize += CheckedInt<uint32_t>(numBytecodeTypeSets()) * sizeof(uint32_t);
|
||||
if (!allocSize.isValid()) {
|
||||
ReportAllocationOverflow(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
prepareForDestruction.release();
|
||||
void* raw = cx->pod_malloc<uint8_t>(allocSize.value());
|
||||
MOZ_ASSERT(uintptr_t(raw) % alignof(JitScript) == 0);
|
||||
if (!raw) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t typeSetOffset = sizeof(JitScript) + numICEntries() * sizeof(ICEntry);
|
||||
uint32_t bytecodeTypeMapOffset =
|
||||
typeSetOffset + numTypeSets * sizeof(StackTypeSet);
|
||||
UniquePtr<JitScript> jitScript(
|
||||
new (raw) JitScript(this, typeSetOffset, bytecodeTypeMapOffset));
|
||||
|
||||
// Sanity check the length computations.
|
||||
MOZ_ASSERT(jitScript->numICEntries() == numICEntries());
|
||||
MOZ_ASSERT(jitScript->numTypeSets() == numTypeSets);
|
||||
|
||||
// We need to call prepareForDestruction on JitScript before we |delete| it.
|
||||
auto prepareForDestruction = mozilla::MakeScopeExit(
|
||||
[&] { jitScript->prepareForDestruction(cx->zone()); });
|
||||
|
||||
if (!jitScript->initICEntries(cx, this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!jitScript_);
|
||||
jitScript_ =
|
||||
new (jitScript) JitScript(this, std::move(icScript), numTypeSets);
|
||||
prepareForDestruction.release();
|
||||
jitScript_ = jitScript.release();
|
||||
|
||||
// We have a JitScript so we can set the script's jitCodeRaw_ pointer to the
|
||||
// Baseline Interpreter code.
|
||||
@ -123,19 +138,19 @@ bool JSScript::createJitScript(JSContext* cx) {
|
||||
|
||||
#ifdef DEBUG
|
||||
AutoSweepJitScript sweep(this);
|
||||
StackTypeSet* typeArray = jitScript->typeArrayDontCheckGeneration();
|
||||
StackTypeSet* typeArray = jitScript_->typeArrayDontCheckGeneration();
|
||||
for (unsigned i = 0; i < numBytecodeTypeSets(); i++) {
|
||||
InferSpew(ISpewOps, "typeSet: %sT%p%s bytecode%u %p",
|
||||
InferSpewColor(&typeArray[i]), &typeArray[i],
|
||||
InferSpewColorReset(), i, this);
|
||||
}
|
||||
StackTypeSet* thisTypes = jitScript->thisTypes(sweep, this);
|
||||
StackTypeSet* thisTypes = jitScript_->thisTypes(sweep, this);
|
||||
InferSpew(ISpewOps, "typeSet: %sT%p%s this %p", InferSpewColor(thisTypes),
|
||||
thisTypes, InferSpewColorReset(), this);
|
||||
unsigned nargs =
|
||||
functionNonDelazifying() ? functionNonDelazifying()->nargs() : 0;
|
||||
for (unsigned i = 0; i < nargs; i++) {
|
||||
StackTypeSet* types = jitScript->argTypes(sweep, this, i);
|
||||
StackTypeSet* types = jitScript_->argTypes(sweep, this, i);
|
||||
InferSpew(ISpewOps, "typeSet: %sT%p%s arg%u %p", InferSpewColor(types),
|
||||
types, InferSpewColorReset(), i, this);
|
||||
}
|
||||
@ -158,8 +173,7 @@ void JSScript::maybeReleaseJitScript() {
|
||||
}
|
||||
|
||||
void JitScript::destroy(Zone* zone) {
|
||||
icScript_->prepareForDestruction(zone);
|
||||
|
||||
prepareForDestruction(zone);
|
||||
js_delete(this);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef jit_JitScript_h
|
||||
#define jit_JitScript_h
|
||||
|
||||
#include "jit/BaselineIC.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "vm/TypeInference.h"
|
||||
|
||||
@ -14,30 +15,72 @@ class JSScript;
|
||||
|
||||
namespace js {
|
||||
|
||||
namespace jit {
|
||||
|
||||
class ICScript;
|
||||
|
||||
} // namespace jit
|
||||
|
||||
// JitScript stores type inference and JIT data for a script. Scripts with a
|
||||
// JitScript can run in the Baseline Interpreter.
|
||||
class JitScript {
|
||||
// [SMDOC] JitScript
|
||||
//
|
||||
// JitScript stores type inference data, Baseline ICs and other JIT-related data
|
||||
// for a script. Scripts with a JitScript can run in the Baseline Interpreter.
|
||||
//
|
||||
// IC Data
|
||||
// -------
|
||||
//
|
||||
// JitScript contains IC data used by Baseline (Interpreter and JIT). Ion has
|
||||
// its own IC chains stored in IonScript.
|
||||
//
|
||||
// For each IC we store an ICEntry, which points to the first ICStub in the
|
||||
// chain. Note that multiple stubs in the same zone can share Baseline IC code.
|
||||
// This works because the stub data is stored in the ICStub instead of baked in
|
||||
// in the stub code.
|
||||
//
|
||||
// Storing this separate from BaselineScript allows us to use the same ICs in
|
||||
// the Baseline Interpreter and Baseline JIT. It also simplifies debug mode OSR
|
||||
// because the JitScript can be reused when we have to recompile the
|
||||
// BaselineScript.
|
||||
//
|
||||
// JitScript contains the following IC data structures:
|
||||
//
|
||||
// * Fallback stub space: this stores all fallback stubs and the "can GC" stubs.
|
||||
// These stubs are never purged before destroying the JitScript. (Other stubs
|
||||
// are stored in the optimized stub space stored in JitZone and can be
|
||||
// discarded more eagerly. See JitScript::purgeOptimizedStubs.)
|
||||
//
|
||||
// * List of IC entries, in the following order:
|
||||
//
|
||||
// - Type monitor IC for |this|.
|
||||
// - Type monitor IC for each formal argument.
|
||||
// - IC for each JOF_IC bytecode op.
|
||||
//
|
||||
// Memory Layout
|
||||
// -------------
|
||||
//
|
||||
// JitScript has various trailing (variable-length) arrays. The memory layout is
|
||||
// as follows:
|
||||
//
|
||||
// Item | Offset
|
||||
// ------------------------+------------------------
|
||||
// JitScript | 0
|
||||
// ICEntry[] | sizeof(JitScript)
|
||||
// StackTypeSet[] | typeSetOffset_
|
||||
// uint32_t[] | bytecodeTypeMapOffset_
|
||||
// (= bytecode type map) |
|
||||
//
|
||||
// These offsets are also used to compute numICEntries and numTypeSets.
|
||||
class alignas(uintptr_t) JitScript final {
|
||||
friend class ::JSScript;
|
||||
|
||||
// Allocated space for fallback IC stubs.
|
||||
jit::FallbackICStubSpace fallbackStubSpace_ = {};
|
||||
|
||||
// The freeze constraints added to stack type sets will only directly
|
||||
// invalidate the script containing those stack type sets. This Vector
|
||||
// contains compilations that inlined this script, so we can invalidate
|
||||
// them as well.
|
||||
RecompileInfoVector inlinedCompilations_;
|
||||
|
||||
// ICScript and JitScript have the same lifetimes, so we store a pointer to
|
||||
// ICScript here to not increase sizeof(JSScript).
|
||||
using ICScriptPtr = js::UniquePtr<js::jit::ICScript>;
|
||||
ICScriptPtr icScript_;
|
||||
// Offset of the StackTypeSet array.
|
||||
uint32_t typeSetOffset_ = 0;
|
||||
|
||||
// Number of TypeSets in typeArray_.
|
||||
uint32_t numTypeSets_;
|
||||
// Offset of the bytecode type map.
|
||||
uint32_t bytecodeTypeMapOffset_ = 0;
|
||||
|
||||
// This field is used to avoid binary searches for the sought entry when
|
||||
// bytecode map queries are in linear order.
|
||||
@ -57,15 +100,14 @@ class JitScript {
|
||||
};
|
||||
Flags flags_ = {}; // Zero-initialize flags.
|
||||
|
||||
// Variable-size array. This is followed by the bytecode type map.
|
||||
StackTypeSet typeArray_[1];
|
||||
jit::ICEntry* icEntries() {
|
||||
uint8_t* base = reinterpret_cast<uint8_t*>(this);
|
||||
return reinterpret_cast<jit::ICEntry*>(base + offsetOfICEntries());
|
||||
}
|
||||
|
||||
StackTypeSet* typeArrayDontCheckGeneration() {
|
||||
// Ensure typeArray_ is the last data member of JitScript.
|
||||
static_assert(sizeof(JitScript) ==
|
||||
sizeof(typeArray_) + offsetof(JitScript, typeArray_),
|
||||
"typeArray_ must be the last member of JitScript");
|
||||
return const_cast<StackTypeSet*>(typeArray_);
|
||||
uint8_t* base = reinterpret_cast<uint8_t*>(this);
|
||||
return reinterpret_cast<StackTypeSet*>(base + typeSetOffset_);
|
||||
}
|
||||
|
||||
uint32_t typesGeneration() const { return uint32_t(flags_.typesGeneration); }
|
||||
@ -75,7 +117,18 @@ class JitScript {
|
||||
}
|
||||
|
||||
public:
|
||||
JitScript(JSScript* script, ICScriptPtr&& icScript, uint32_t numTypeSets);
|
||||
JitScript(JSScript* script, uint32_t typeSetOffset,
|
||||
uint32_t bytecodeTypeMapOffset);
|
||||
|
||||
#ifdef DEBUG
|
||||
~JitScript() {
|
||||
// The contents of the fallback stub space are removed and freed
|
||||
// separately after the next minor GC. See prepareForDestruction.
|
||||
MOZ_ASSERT(fallbackStubSpace_.isEmpty());
|
||||
}
|
||||
#endif
|
||||
|
||||
MOZ_MUST_USE bool initICEntries(JSContext* cx, JSScript* script);
|
||||
|
||||
bool hasFreezeConstraints(const js::AutoSweepJitScript& sweep) const {
|
||||
MOZ_ASSERT(sweep.jitScript() == this);
|
||||
@ -103,7 +156,12 @@ class JitScript {
|
||||
return inlinedCompilations_.append(info);
|
||||
}
|
||||
|
||||
uint32_t numTypeSets() const { return numTypeSets_; }
|
||||
uint32_t numICEntries() const {
|
||||
return (typeSetOffset_ - offsetOfICEntries()) / sizeof(jit::ICEntry);
|
||||
}
|
||||
uint32_t numTypeSets() const {
|
||||
return (bytecodeTypeMapOffset_ - typeSetOffset_) / sizeof(StackTypeSet);
|
||||
}
|
||||
|
||||
uint32_t* bytecodeTypeMapHint() { return &bytecodeTypeMapHint_; }
|
||||
|
||||
@ -111,11 +169,6 @@ class JitScript {
|
||||
void setActive() { flags_.active = true; }
|
||||
void resetActive() { flags_.active = false; }
|
||||
|
||||
jit::ICScript* icScript() const {
|
||||
MOZ_ASSERT(icScript_);
|
||||
return icScript_.get();
|
||||
}
|
||||
|
||||
/* Array of type sets for variables and JOF_TYPESET ops. */
|
||||
StackTypeSet* typeArray(const js::AutoSweepJitScript& sweep) {
|
||||
MOZ_ASSERT(sweep.jitScript() == this);
|
||||
@ -123,8 +176,8 @@ class JitScript {
|
||||
}
|
||||
|
||||
uint32_t* bytecodeTypeMap() {
|
||||
MOZ_ASSERT(numTypeSets_ > 0);
|
||||
return reinterpret_cast<uint32_t*>(typeArray_ + numTypeSets_);
|
||||
uint8_t* base = reinterpret_cast<uint8_t*>(this);
|
||||
return reinterpret_cast<uint32_t*>(base + bytecodeTypeMapOffset_);
|
||||
}
|
||||
|
||||
inline StackTypeSet* thisTypes(const AutoSweepJitScript& sweep,
|
||||
@ -188,22 +241,53 @@ class JitScript {
|
||||
|
||||
void destroy(Zone* zone);
|
||||
|
||||
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||
// Note: icScript_ size is reported in jit::AddSizeOfBaselineData.
|
||||
return mallocSizeOf(this);
|
||||
}
|
||||
|
||||
static constexpr size_t offsetOfICScript() {
|
||||
// Note: icScript_ is a UniquePtr that stores the raw pointer. If that ever
|
||||
// changes and this assertion fails, we should stop using UniquePtr.
|
||||
static_assert(sizeof(icScript_) == sizeof(uintptr_t),
|
||||
"JIT code assumes icScript_ is pointer-sized");
|
||||
return offsetof(JitScript, icScript_);
|
||||
}
|
||||
static constexpr size_t offsetOfICEntries() { return sizeof(JitScript); }
|
||||
|
||||
#ifdef DEBUG
|
||||
void printTypes(JSContext* cx, HandleScript script);
|
||||
#endif
|
||||
|
||||
void prepareForDestruction(Zone* zone) {
|
||||
// When the script contains pointers to nursery things, the store buffer can
|
||||
// contain entries that point into the fallback stub space. Since we can
|
||||
// destroy scripts outside the context of a GC, this situation could result
|
||||
// in us trying to mark invalid store buffer entries.
|
||||
//
|
||||
// Defer freeing any allocated blocks until after the next minor GC.
|
||||
fallbackStubSpace_.freeAllAfterMinorGC(zone);
|
||||
}
|
||||
|
||||
jit::FallbackICStubSpace* fallbackStubSpace() { return &fallbackStubSpace_; }
|
||||
|
||||
void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t* data,
|
||||
size_t* fallbackStubs) const {
|
||||
*data += mallocSizeOf(this);
|
||||
|
||||
// |data| already includes the ICStubSpace itself, so use
|
||||
// sizeOfExcludingThis.
|
||||
*fallbackStubs += fallbackStubSpace_.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
jit::ICEntry& icEntry(size_t index) {
|
||||
MOZ_ASSERT(index < numICEntries());
|
||||
return icEntries()[index];
|
||||
}
|
||||
|
||||
void noteAccessedGetter(uint32_t pcOffset);
|
||||
void noteHasDenseAdd(uint32_t pcOffset);
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
void purgeOptimizedStubs(JSScript* script);
|
||||
|
||||
jit::ICEntry* interpreterICEntryFromPCOffset(uint32_t pcOffset);
|
||||
|
||||
jit::ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset);
|
||||
jit::ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset,
|
||||
jit::ICEntry* prevLookedUpEntry);
|
||||
|
||||
jit::ICEntry& icEntryFromPCOffset(uint32_t pcOffset);
|
||||
jit::ICEntry& icEntryFromPCOffset(uint32_t pcOffset,
|
||||
jit::ICEntry* prevLookedUpEntry);
|
||||
};
|
||||
|
||||
// Ensures no JitScripts are purged in the current zone.
|
||||
|
@ -1553,8 +1553,8 @@ static MOZ_ALWAYS_INLINE bool SetObjectElementOperation(
|
||||
int32_t i = JSID_TO_INT(id);
|
||||
if ((uint32_t)i >= length) {
|
||||
// Annotate script if provided with information (e.g. baseline)
|
||||
if (script && script->hasICScript() && IsSetElemPC(pc)) {
|
||||
script->icScript()->noteHasDenseAdd(script->pcToOffset(pc));
|
||||
if (script && script->hasJitScript() && IsSetElemPC(pc)) {
|
||||
script->jitScript()->noteHasDenseAdd(script->pcToOffset(pc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -182,9 +182,4 @@ inline bool JSScript::isDebuggee() const {
|
||||
return realm_->debuggerObservesAllExecution() || hasDebugScript();
|
||||
}
|
||||
|
||||
inline js::jit::ICScript* JSScript::icScript() const {
|
||||
MOZ_ASSERT(hasICScript());
|
||||
return jitScript_->icScript();
|
||||
}
|
||||
|
||||
#endif /* vm_JSScript_inl_h */
|
||||
|
@ -1725,9 +1725,8 @@ class ScriptSource::LoadSourceMatcher {
|
||||
}
|
||||
|
||||
if (!ss_->setRetrievedSource(
|
||||
cx_,
|
||||
EntryUnits<Utf8Unit>(reinterpret_cast<Utf8Unit*>(utf8Source)),
|
||||
*length)) {
|
||||
cx_, EntryUnits<Utf8Unit>(reinterpret_cast<Utf8Unit*>(utf8Source)),
|
||||
*length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2748,8 +2747,8 @@ XDRResult ScriptSource::codeBinASTData(XDRState<mode>* const xdr,
|
||||
// XDR the BinAST data.
|
||||
Maybe<SharedImmutableString> binASTData;
|
||||
if (mode == XDR_DECODE) {
|
||||
auto bytes = xdr->cx()->template make_pod_array<char>(Max<size_t>(
|
||||
binASTLength, 1));
|
||||
auto bytes =
|
||||
xdr->cx()->template make_pod_array<char>(Max<size_t>(binASTLength, 1));
|
||||
if (!bytes) {
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
@ -2820,7 +2819,8 @@ XDRResult ScriptSource::codeBinASTData(XDRState<mode>* const xdr,
|
||||
JSAtom** atomsBase = binASTMetadata->atomsBase();
|
||||
auto slices = binASTMetadata->sliceBase();
|
||||
const char* sourceBase =
|
||||
(mode == XDR_ENCODE ? ss->data.as<BinAST>().string : *binASTData).chars();
|
||||
(mode == XDR_ENCODE ? ss->data.as<BinAST>().string : *binASTData)
|
||||
.chars();
|
||||
|
||||
for (uint32_t i = 0; i < numStrings; i++) {
|
||||
uint8_t isNull;
|
||||
@ -3373,7 +3373,8 @@ void js::FreeScriptData(JSRuntime* rt) {
|
||||
|
||||
#ifdef DEBUG
|
||||
if (numLive > 0) {
|
||||
fprintf(stderr, "ERROR: GC found %zu live SharedScriptData at shutdown\n", numLive);
|
||||
fprintf(stderr, "ERROR: GC found %zu live SharedScriptData at shutdown\n",
|
||||
numLive);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -4039,8 +4040,15 @@ size_t JSScript::sizeOfData(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||
return mallocSizeOf(data_);
|
||||
}
|
||||
|
||||
size_t JSScript::sizeOfJitScript(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||
return jitScript_ ? jitScript_->sizeOfIncludingThis(mallocSizeOf) : 0;
|
||||
void JSScript::addSizeOfJitScript(mozilla::MallocSizeOf mallocSizeOf,
|
||||
size_t* sizeOfJitScript,
|
||||
size_t* sizeOfBaselineFallbackStubs) const {
|
||||
if (!jitScript_) {
|
||||
return;
|
||||
}
|
||||
|
||||
jitScript_->addSizeOfIncludingThis(mallocSizeOf, sizeOfJitScript,
|
||||
sizeOfBaselineFallbackStubs);
|
||||
}
|
||||
|
||||
js::GlobalObject& JSScript::uninlinedGlobal() const { return global(); }
|
||||
@ -5511,14 +5519,16 @@ JS::ubi::Base::Size JS::ubi::Concrete<JSScript>::size(
|
||||
Size size = gc::Arena::thingSize(get().asTenured().getAllocKind());
|
||||
|
||||
size += get().sizeOfData(mallocSizeOf);
|
||||
size += get().sizeOfJitScript(mallocSizeOf);
|
||||
|
||||
size_t jitScriptSize = 0;
|
||||
size_t fallbackStubSize = 0;
|
||||
get().addSizeOfJitScript(mallocSizeOf, &jitScriptSize, &fallbackStubSize);
|
||||
size += jitScriptSize;
|
||||
size += fallbackStubSize;
|
||||
|
||||
size_t baselineSize = 0;
|
||||
size_t baselineStubsSize = 0;
|
||||
jit::AddSizeOfBaselineData(&get(), mallocSizeOf, &baselineSize,
|
||||
&baselineStubsSize);
|
||||
jit::AddSizeOfBaselineData(&get(), mallocSizeOf, &baselineSize);
|
||||
size += baselineSize;
|
||||
size += baselineStubsSize;
|
||||
|
||||
size += jit::SizeOfIonData(&get(), mallocSizeOf);
|
||||
|
||||
|
@ -55,7 +55,6 @@ namespace js {
|
||||
|
||||
namespace jit {
|
||||
struct BaselineScript;
|
||||
class ICScript;
|
||||
struct IonScriptCounts;
|
||||
} // namespace jit
|
||||
|
||||
@ -1568,7 +1567,7 @@ class alignas(uintptr_t) SharedScriptData final {
|
||||
// Index into the scopes array of the body scope.
|
||||
uint32_t bodyScopeIndex = 0;
|
||||
|
||||
// Number of IC entries to allocate in ICScript for Baseline ICs.
|
||||
// Number of IC entries to allocate in JitScript for Baseline ICs.
|
||||
uint32_t numICEntries = 0;
|
||||
|
||||
// ES6 function length.
|
||||
@ -2467,14 +2466,6 @@ class JSScript : public js::gc::TenuredCell {
|
||||
inline void setBaselineScript(JSRuntime* rt,
|
||||
js::jit::BaselineScript* baselineScript);
|
||||
|
||||
inline js::jit::ICScript* icScript() const;
|
||||
|
||||
bool hasICScript() const {
|
||||
// ICScript is stored in JitScript so we have an ICScript iff we have a
|
||||
// JitScript.
|
||||
return !!jitScript_;
|
||||
}
|
||||
|
||||
void updateJitCodeRaw(JSRuntime* rt);
|
||||
|
||||
static size_t offsetOfBaselineScript() {
|
||||
@ -2604,6 +2595,7 @@ class JSScript : public js::gc::TenuredCell {
|
||||
/* Ensure the script has a JitScript. */
|
||||
inline bool ensureHasJitScript(JSContext* cx, js::AutoKeepJitScripts&);
|
||||
|
||||
bool hasJitScript() const { return jitScript_ != nullptr; }
|
||||
js::JitScript* jitScript() { return jitScript_; }
|
||||
|
||||
void maybeReleaseJitScript();
|
||||
@ -2734,7 +2726,10 @@ class JSScript : public js::gc::TenuredCell {
|
||||
*/
|
||||
size_t computedSizeOfData() const;
|
||||
size_t sizeOfData(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
size_t sizeOfJitScript(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
|
||||
void addSizeOfJitScript(mozilla::MallocSizeOf mallocSizeOf,
|
||||
size_t* sizeOfJitScript,
|
||||
size_t* sizeOfBaselineFallbackStubs) const;
|
||||
|
||||
size_t dataSize() const { return dataSize_; }
|
||||
|
||||
|
@ -445,10 +445,10 @@ static void StatsCellCallback(JSRuntime* rt, void* data, void* thing,
|
||||
realmStats.scriptsGCHeap += thingSize;
|
||||
realmStats.scriptsMallocHeapData +=
|
||||
script->sizeOfData(rtStats->mallocSizeOf_);
|
||||
realmStats.jitScripts += script->sizeOfJitScript(rtStats->mallocSizeOf_);
|
||||
jit::AddSizeOfBaselineData(script, rtStats->mallocSizeOf_,
|
||||
&realmStats.baselineData,
|
||||
script->addSizeOfJitScript(rtStats->mallocSizeOf_, &realmStats.jitScripts,
|
||||
&realmStats.baselineStubsFallback);
|
||||
jit::AddSizeOfBaselineData(script, rtStats->mallocSizeOf_,
|
||||
&realmStats.baselineData);
|
||||
realmStats.ionData += jit::SizeOfIonData(script, rtStats->mallocSizeOf_);
|
||||
CollectScriptSourceStats<granularity>(closure, script->scriptSource());
|
||||
break;
|
||||
|
@ -2248,12 +2248,12 @@ static MOZ_ALWAYS_INLINE bool GetExistingProperty(
|
||||
{
|
||||
jsbytecode* pc;
|
||||
JSScript* script = cx->currentScript(&pc);
|
||||
if (script && script->hasICScript()) {
|
||||
if (script && script->hasJitScript()) {
|
||||
switch (JSOp(*pc)) {
|
||||
case JSOP_GETPROP:
|
||||
case JSOP_CALLPROP:
|
||||
case JSOP_LENGTH:
|
||||
script->icScript()->noteAccessedGetter(script->pcToOffset(pc));
|
||||
script->jitScript()->noteAccessedGetter(script->pcToOffset(pc));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -3109,4 +3109,4 @@ bool js::CopyDataPropertiesNative(JSContext* cx, HandlePlainObject target,
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,6 @@ class HeapTypeSetKey;
|
||||
|
||||
namespace jit {
|
||||
|
||||
class ICScript;
|
||||
struct IonScript;
|
||||
class TempAllocator;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user