Bug 1676688 - Part 3: Merge AtomIndex and ParserAtomIndex. r=tcampbell

Differential Revision: https://phabricator.services.mozilla.com/D96812
This commit is contained in:
Tooru Fujisawa 2020-11-12 20:27:10 +00:00
Родитель 9b9b55b106
Коммит cee7e57c4c
7 изменённых файлов: 169 добавлений и 153 удалений

Просмотреть файл

@ -1207,7 +1207,7 @@ void CompilationInput::trace(JSTracer* trc) {
TraceNullableRoot(trc, &enclosingScope, "compilation-input-enclosing-scope"); TraceNullableRoot(trc, &enclosingScope, "compilation-input-enclosing-scope");
} }
void CompilationAtomCache::trace(JSTracer* trc) { atoms.trace(trc); } void CompilationAtomCache::trace(JSTracer* trc) { atoms_.trace(trc); }
void CompilationInfo::trace(JSTracer* trc) { input.trace(trc); } void CompilationInfo::trace(JSTracer* trc) { input.trace(trc); }

Просмотреть файл

@ -93,12 +93,20 @@ struct ScopeContext {
}; };
struct CompilationAtomCache { struct CompilationAtomCache {
private:
// Atoms lowered into or converted from CompilationStencil.parserAtomData. // Atoms lowered into or converted from CompilationStencil.parserAtomData.
// //
// This field is here instead of in CompilationGCOutput because atoms lowered // This field is here instead of in CompilationGCOutput because atoms lowered
// from JSAtom is part of input (enclosing scope bindings, lazy function name, // from JSAtom is part of input (enclosing scope bindings, lazy function name,
// etc), and having 2 vectors in both input/output is error prone. // etc), and having 2 vectors in both input/output is error prone.
JS::GCVector<JSAtom*, 0, js::SystemAllocPolicy> atoms; JS::GCVector<JSAtom*, 0, js::SystemAllocPolicy> atoms_;
public:
JSAtom* getExistingAtomAt(ParserAtomIndex index) const;
JSAtom* getAtomAt(ParserAtomIndex index) const;
bool hasAtomAt(ParserAtomIndex index) const;
bool setAtomAt(JSContext* cx, ParserAtomIndex index, JSAtom* atom);
bool allocate(JSContext* cx, size_t length);
void trace(JSTracer* trc); void trace(JSTracer* trc);
} JS_HAZ_GC_POINTER; } JS_HAZ_GC_POINTER;
@ -252,6 +260,8 @@ struct CompilationStencil {
asmJS; asmJS;
// List of parser atoms for this compilation. // List of parser atoms for this compilation.
// This may contain nullptr entries when round-tripping with XDR if the atom
// was generated in original parse but not used by stencil.
ParserAtomVector parserAtomData; ParserAtomVector parserAtomData;
// Parameterized chunk size to use for LifoAlloc. // Parameterized chunk size to use for LifoAlloc.

Просмотреть файл

@ -216,8 +216,13 @@ bool ParserAtomEntry::isIndex(uint32_t* indexp) const {
JSAtom* ParserAtomEntry::toJSAtom(JSContext* cx, JSAtom* ParserAtomEntry::toJSAtom(JSContext* cx,
CompilationAtomCache& atomCache) const { CompilationAtomCache& atomCache) const {
switch (atomIndexKind_) { switch (atomIndexKind_) {
case AtomIndexKind::AtomIndex: case AtomIndexKind::ParserAtomIndex: {
return atomCache.atoms[atomIndex_]; JSAtom* atom = atomCache.getAtomAt(toParserAtomIndex());
if (atom) {
return atom;
}
break;
}
case AtomIndexKind::WellKnown: case AtomIndexKind::WellKnown:
return GetWellKnownAtom(cx, WellKnownAtomId(atomIndex_)); return GetWellKnownAtom(cx, WellKnownAtomId(atomIndex_));
@ -229,9 +234,6 @@ JSAtom* ParserAtomEntry::toJSAtom(JSContext* cx,
case AtomIndexKind::Static2: case AtomIndexKind::Static2:
return cx->staticStrings().getLength2FromIndex(atomIndex_); return cx->staticStrings().getLength2FromIndex(atomIndex_);
case AtomIndexKind::NotInstantiated:
break;
} }
return instantiate(cx, atomCache); return instantiate(cx, atomCache);
@ -240,8 +242,11 @@ JSAtom* ParserAtomEntry::toJSAtom(JSContext* cx,
JSAtom* ParserAtomEntry::toExistingJSAtom( JSAtom* ParserAtomEntry::toExistingJSAtom(
JSContext* cx, CompilationAtomCache& atomCache) const { JSContext* cx, CompilationAtomCache& atomCache) const {
switch (atomIndexKind_) { switch (atomIndexKind_) {
case AtomIndexKind::AtomIndex: case AtomIndexKind::ParserAtomIndex: {
return atomCache.atoms[atomIndex_]; JSAtom* atom = atomCache.getExistingAtomAt(toParserAtomIndex());
MOZ_ASSERT(atom);
return atom;
}
case AtomIndexKind::WellKnown: case AtomIndexKind::WellKnown:
return GetWellKnownAtom(cx, WellKnownAtomId(atomIndex_)); return GetWellKnownAtom(cx, WellKnownAtomId(atomIndex_));
@ -253,9 +258,6 @@ JSAtom* ParserAtomEntry::toExistingJSAtom(
case AtomIndexKind::Static2: case AtomIndexKind::Static2:
return cx->staticStrings().getLength2FromIndex(atomIndex_); return cx->staticStrings().getLength2FromIndex(atomIndex_);
case AtomIndexKind::NotInstantiated:
MOZ_CRASH("ParserAtom should already be instantiated");
} }
return nullptr; return nullptr;
@ -263,8 +265,6 @@ JSAtom* ParserAtomEntry::toExistingJSAtom(
JSAtom* ParserAtomEntry::instantiate(JSContext* cx, JSAtom* ParserAtomEntry::instantiate(JSContext* cx,
CompilationAtomCache& atomCache) const { CompilationAtomCache& atomCache) const {
MOZ_ASSERT(isNotInstantiated());
JSAtom* atom; JSAtom* atom;
if (hasLatin1Chars()) { if (hasLatin1Chars()) {
atom = AtomizeChars(cx, hash(), latin1Chars(), length()); atom = AtomizeChars(cx, hash(), latin1Chars(), length());
@ -275,17 +275,10 @@ JSAtom* ParserAtomEntry::instantiate(JSContext* cx,
js::ReportOutOfMemory(cx); js::ReportOutOfMemory(cx);
return nullptr; return nullptr;
} }
auto index = atomCache.atoms.length(); if (!atomCache.setAtomAt(cx, toParserAtomIndex(), atom)) {
// This cannot be infallibleAppend because there are toJSAtom consumers that
// doesn't reserve CompilationAtomCache.atoms beforehand
if (!atomCache.atoms.append(atom)) {
js::ReportOutOfMemory(cx);
return nullptr; return nullptr;
} }
const_cast<ParserAtomEntry*>(this)->setAtomIndex(AtomIndex(index));
return atom; return atom;
} }
@ -328,6 +321,7 @@ JS::Result<const ParserAtom*, OOM> ParserAtomsTable::addEntry(
if (!entries_.append(entry)) { if (!entries_.append(entry)) {
return RaiseParserAtomsOOMError(cx); return RaiseParserAtomsOOMError(cx);
} }
entry->setParserAtomIndex(index);
if (!entryMap_.add(addPtr, entry, index)) { if (!entryMap_.add(addPtr, entry, index)) {
return RaiseParserAtomsOOMError(cx); return RaiseParserAtomsOOMError(cx);
} }
@ -385,27 +379,27 @@ ParserAtomVectorBuilder::ParserAtomVectorBuilder(JSRuntime* rt,
alloc_(&alloc), alloc_(&alloc),
entries_(entries) {} entries_(entries) {}
bool ParserAtomVectorBuilder::reserve(JSContext* cx, size_t count) { bool ParserAtomVectorBuilder::resize(JSContext* cx, size_t count) {
if (count >= TaggedParserAtomIndex::IndexLimit) { if (count >= TaggedParserAtomIndex::IndexLimit) {
ReportAllocationOverflow(cx); ReportAllocationOverflow(cx);
return false; return false;
} }
if (!entries_.reserve(count)) { if (!entries_.resize(count)) {
ReportOutOfMemory(cx); ReportOutOfMemory(cx);
return false; return false;
} }
return true; return true;
} }
JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::internLatin1( JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::internLatin1At(
JSContext* cx, const Latin1Char* latin1Ptr, HashNumber hash, JSContext* cx, const Latin1Char* latin1Ptr, HashNumber hash,
uint32_t length) { uint32_t length, ParserAtomIndex index) {
return intern<Latin1Char, Latin1Char>(cx, latin1Ptr, hash, length); return internAt<Latin1Char, Latin1Char>(cx, latin1Ptr, hash, length, index);
} }
JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::internChar16( JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::internChar16At(
JSContext* cx, LittleEndianChars twoByteLE, HashNumber hash, JSContext* cx, LittleEndianChars twoByteLE, HashNumber hash,
uint32_t length) { uint32_t length, ParserAtomIndex index) {
#ifdef DEBUG #ifdef DEBUG
InflatedChar16Sequence<LittleEndianChars> seq(twoByteLE, length); InflatedChar16Sequence<LittleEndianChars> seq(twoByteLE, length);
bool wide = false; bool wide = false;
@ -419,12 +413,14 @@ JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::internChar16(
MOZ_ASSERT(wide); MOZ_ASSERT(wide);
#endif #endif
return intern<char16_t, LittleEndianChars>(cx, twoByteLE, hash, length); return internAt<char16_t, LittleEndianChars>(cx, twoByteLE, hash, length,
index);
} }
template <typename CharT, typename SeqCharT, typename InputCharsT> template <typename CharT, typename SeqCharT, typename InputCharsT>
JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::intern( JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::internAt(
JSContext* cx, InputCharsT chars, HashNumber hash, uint32_t length) { JSContext* cx, InputCharsT chars, HashNumber hash, uint32_t length,
ParserAtomIndex index) {
InflatedChar16Sequence<SeqCharT> seq(chars, length); InflatedChar16Sequence<SeqCharT> seq(chars, length);
#ifdef DEBUG #ifdef DEBUG
@ -437,9 +433,9 @@ JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::intern(
ParserAtomEntry* entry; ParserAtomEntry* entry;
MOZ_TRY_VAR(entry, MOZ_TRY_VAR(entry,
ParserAtomEntry::allocate<CharT>(cx, *alloc_, seq, length, hash)); ParserAtomEntry::allocate<CharT>(cx, *alloc_, seq, length, hash));
if (!entries_.append(entry)) { entry->setParserAtomIndex(index);
return RaiseParserAtomsOOMError(cx); entries_[index] = entry;
}
return entry->asAtom(); return entry->asAtom();
} }
@ -533,7 +529,7 @@ JS::Result<const ParserAtom*, OOM> ParserAtomsTable::internChar16(
JS::Result<const ParserAtom*, OOM> ParserAtomsTable::internJSAtom( JS::Result<const ParserAtom*, OOM> ParserAtomsTable::internJSAtom(
JSContext* cx, CompilationInfo& compilationInfo, JSAtom* atom) { JSContext* cx, CompilationInfo& compilationInfo, JSAtom* atom) {
const ParserAtom* id; const ParserAtom* parserAtom;
{ {
JS::AutoCheckCannotGC nogc; JS::AutoCheckCannotGC nogc;
@ -544,24 +540,24 @@ JS::Result<const ParserAtom*, OOM> ParserAtomsTable::internJSAtom(
if (result.isErr()) { if (result.isErr()) {
return result; return result;
} }
id = result.unwrap(); parserAtom = result.unwrap();
} }
if (id->isNotInstantiated()) { if (parserAtom->isParserAtomIndex()) {
MOZ_ASSERT(id->equalsJSAtom(atom)); ParserAtomIndex index = parserAtom->toParserAtomIndex();
auto& atomCache = compilationInfo.input.atomCache;
auto index = AtomIndex(compilationInfo.input.atomCache.atoms.length()); if (!atomCache.hasAtomAt(index)) {
if (!compilationInfo.input.atomCache.atoms.append(atom)) { if (!atomCache.setAtomAt(cx, index, atom)) {
return RaiseParserAtomsOOMError(cx); return mozilla::Err(PARSER_ATOMS_OOM);
}
} }
const_cast<ParserAtom*>(id)->setAtomIndex(AtomIndex(index));
} }
// We should (infallibly) map back to the same JSAtom. // We should (infallibly) map back to the same JSAtom.
MOZ_ASSERT(id->toJSAtom(cx, compilationInfo.input.atomCache) == atom); MOZ_ASSERT(parserAtom->toJSAtom(cx, compilationInfo.input.atomCache) == atom);
return id; return parserAtom;
} }
JS::Result<const ParserAtom*, OOM> ParserAtomsTable::concatAtoms( JS::Result<const ParserAtom*, OOM> ParserAtomsTable::concatAtoms(
@ -643,20 +639,14 @@ const ParserAtom* ParserAtomVectorBuilder::getStatic2(
return WellKnownParserAtoms::rom_.length2Table[size_t(s)].asAtom(); return WellKnownParserAtoms::rom_.length2Table[size_t(s)].asAtom();
} }
size_t RequiredNonStaticAtomCount(const ParserAtomVector& entries) {
size_t count = 0;
for (const auto& entry : entries) {
if (entry->isUsedByStencil() || entry->isAtomIndex()) {
count++;
}
}
return count;
}
bool InstantiateMarkedAtoms(JSContext* cx, const ParserAtomVector& entries, bool InstantiateMarkedAtoms(JSContext* cx, const ParserAtomVector& entries,
CompilationAtomCache& atomCache) { CompilationAtomCache& atomCache) {
for (const auto& entry : entries) { for (const auto& entry : entries) {
if (entry->isUsedByStencil() && entry->isNotInstantiated()) { if (!entry) {
continue;
}
if (entry->isUsedByStencil() && entry->isParserAtomIndex() &&
!atomCache.hasAtomAt(entry->toParserAtomIndex())) {
if (!entry->instantiate(cx, atomCache)) { if (!entry->instantiate(cx, atomCache)) {
return false; return false;
} }
@ -818,7 +808,8 @@ static XDRResult XDRParserAtomTaggedIndex(XDRState<mode>* xdr,
} }
template <XDRMode mode> template <XDRMode mode>
XDRResult XDRParserAtomData(XDRState<mode>* xdr, const ParserAtom** atomp) { XDRResult XDRParserAtomDataAt(XDRState<mode>* xdr, const ParserAtom** atomp,
ParserAtomIndex index) {
static_assert(JSString::MAX_LENGTH <= INT32_MAX, static_assert(JSString::MAX_LENGTH <= INT32_MAX,
"String length must fit in 31 bits"); "String length must fit in 31 bits");
@ -865,14 +856,16 @@ XDRResult XDRParserAtomData(XDRState<mode>* xdr, const ParserAtom** atomp) {
MOZ_TRY(xdr->peekData(&ptr, length * sizeof(Latin1Char))); MOZ_TRY(xdr->peekData(&ptr, length * sizeof(Latin1Char)));
chars = reinterpret_cast<const Latin1Char*>(ptr); chars = reinterpret_cast<const Latin1Char*>(ptr);
} }
mbAtom = xdr->frontendAtoms().internLatin1(cx, chars, hash, length); mbAtom =
xdr->frontendAtoms().internLatin1At(cx, chars, hash, length, index);
} else { } else {
const uint8_t* twoByteCharsLE = nullptr; const uint8_t* twoByteCharsLE = nullptr;
if (length) { if (length) {
MOZ_TRY(xdr->peekData(&twoByteCharsLE, length * sizeof(char16_t))); MOZ_TRY(xdr->peekData(&twoByteCharsLE, length * sizeof(char16_t)));
} }
LittleEndianChars leTwoByte(twoByteCharsLE); LittleEndianChars leTwoByte(twoByteCharsLE);
mbAtom = xdr->frontendAtoms().internChar16(cx, leTwoByte, hash, length); mbAtom =
xdr->frontendAtoms().internChar16At(cx, leTwoByte, hash, length, index);
} }
const ParserAtom* atom = mbAtom.unwrapOr(nullptr); const ParserAtom* atom = mbAtom.unwrapOr(nullptr);
@ -888,16 +881,16 @@ XDRResult XDRParserAtomData(XDRState<mode>* xdr, const ParserAtom** atomp) {
return Ok(); return Ok();
} }
template XDRResult XDRParserAtomData(XDRState<XDR_ENCODE>* xdr, template XDRResult XDRParserAtomDataAt(XDRState<XDR_ENCODE>* xdr,
const ParserAtom** atomp); const ParserAtom** atomp,
template XDRResult XDRParserAtomData(XDRState<XDR_DECODE>* xdr, ParserAtomIndex index);
const ParserAtom** atomp); template XDRResult XDRParserAtomDataAt(XDRState<XDR_DECODE>* xdr,
const ParserAtom** atomp,
ParserAtomIndex index);
template <XDRMode mode> template <XDRMode mode>
XDRResult XDRParserAtom(XDRState<mode>* xdr, const ParserAtom** atomp) { XDRResult XDRParserAtom(XDRState<mode>* xdr, const ParserAtom** atomp) {
if (mode == XDR_ENCODE) { if (mode == XDR_ENCODE) {
MOZ_ASSERT(xdr->hasAtomMap());
uint32_t atomIndex; uint32_t atomIndex;
ParserAtomTag tag = ParserAtomTag::Normal; ParserAtomTag tag = ParserAtomTag::Normal;
if ((*atomp)->isWellKnownAtomId()) { if ((*atomp)->isWellKnownAtomId()) {
@ -910,14 +903,7 @@ XDRResult XDRParserAtom(XDRState<mode>* xdr, const ParserAtom** atomp) {
atomIndex = uint32_t((*atomp)->toStaticParserString2()); atomIndex = uint32_t((*atomp)->toStaticParserString2());
tag = ParserAtomTag::Static2; tag = ParserAtomTag::Static2;
} else { } else {
MOZ_ASSERT((*atomp)->isNotInstantiated() || (*atomp)->isAtomIndex()); atomIndex = uint32_t((*atomp)->toParserAtomIndex());
MOZ_ASSERT((*atomp)->isUsedByStencil());
// Either AtomIndexKind::NotInstantiated or AtomIndexKind::AtomIndex.
// References to atoms are encoded as indices into the atom stream.
XDRParserAtomMap::Ptr p = xdr->parserAtomMap().lookup(*atomp);
MOZ_ASSERT(p);
atomIndex = p->value();
tag = ParserAtomTag::Normal; tag = ParserAtomTag::Normal;
} }
MOZ_TRY(XDRParserAtomTaggedIndex(xdr, &tag, &atomIndex)); MOZ_TRY(XDRParserAtomTaggedIndex(xdr, &tag, &atomIndex));

Просмотреть файл

@ -35,10 +35,6 @@ class ParserAtomsTable;
mozilla::GenericErrorResult<OOM> RaiseParserAtomsOOMError(JSContext* cx); mozilla::GenericErrorResult<OOM> RaiseParserAtomsOOMError(JSContext* cx);
// An index into CompilationAtomCache.
// This is local to the current compilation.
using AtomIndex = TypedIndex<JSAtom*>;
// An index to map WellKnownParserAtoms to cx->names(). // An index to map WellKnownParserAtoms to cx->names().
// This is consistent across multiple compilation. // This is consistent across multiple compilation.
// //
@ -209,10 +205,8 @@ class alignas(alignof(uint32_t)) ParserAtomEntry {
// Mapping into from ParserAtoms to JSAtoms. // Mapping into from ParserAtoms to JSAtoms.
enum class AtomIndexKind : uint8_t { enum class AtomIndexKind : uint8_t {
// Not yet instantiated // Index into CompilationStencil.parserAtomData.
NotInstantiated, ParserAtomIndex,
// Index into CompilationAtomCache
AtomIndex,
// WellKnownAtomId to index into cx->names() set // WellKnownAtomId to index into cx->names() set
WellKnown, WellKnown,
// Index into StaticStrings length-1 set // Index into StaticStrings length-1 set
@ -221,12 +215,12 @@ class alignas(alignof(uint32_t)) ParserAtomEntry {
Static2, Static2,
}; };
uint32_t atomIndex_ = 0; uint32_t atomIndex_ = 0;
AtomIndexKind atomIndexKind_ = AtomIndexKind::NotInstantiated; AtomIndexKind atomIndexKind_ = AtomIndexKind::ParserAtomIndex;
// Encoding type. // Encoding type.
bool hasTwoByteChars_ = false; bool hasTwoByteChars_ = false;
// Other flags. // Mutable flags.
bool usedByStencil_ = false; bool usedByStencil_ = false;
// End of fields. // End of fields.
@ -304,13 +298,9 @@ class alignas(alignof(uint32_t)) ParserAtomEntry {
HashNumber hash() const { return hash_; } HashNumber hash() const { return hash_; }
uint32_t length() const { return length_; } uint32_t length() const { return length_; }
bool isNotInstantiated() const {
return atomIndexKind_ == AtomIndexKind::NotInstantiated;
}
bool isUsedByStencil() const { return usedByStencil_; } bool isUsedByStencil() const { return usedByStencil_; }
void markUsedByStencil() const { void markUsedByStencil() const {
if ((isNotInstantiated() || isAtomIndex())) { if (isParserAtomIndex()) {
// Use const method + const_cast here to avoid marking static strings' // Use const method + const_cast here to avoid marking static strings'
// field mutable. // field mutable.
const_cast<ParserAtomEntry*>(this)->usedByStencil_ = true; const_cast<ParserAtomEntry*>(this)->usedByStencil_ = true;
@ -322,6 +312,10 @@ class alignas(alignof(uint32_t)) ParserAtomEntry {
template <typename CharT> template <typename CharT>
bool equalsSeq(HashNumber hash, InflatedChar16Sequence<CharT> seq) const; bool equalsSeq(HashNumber hash, InflatedChar16Sequence<CharT> seq) const;
ParserAtomIndex toParserAtomIndex() const {
MOZ_ASSERT(isParserAtomIndex());
return ParserAtomIndex(atomIndex_);
}
WellKnownAtomId toWellKnownAtomId() const { WellKnownAtomId toWellKnownAtomId() const {
MOZ_ASSERT(isWellKnownAtomId()); MOZ_ASSERT(isWellKnownAtomId());
return WellKnownAtomId(atomIndex_); return WellKnownAtomId(atomIndex_);
@ -335,8 +329,8 @@ class alignas(alignof(uint32_t)) ParserAtomEntry {
return StaticParserString2(atomIndex_); return StaticParserString2(atomIndex_);
} }
bool isAtomIndex() const { bool isParserAtomIndex() const {
return atomIndexKind_ == AtomIndexKind::AtomIndex; return atomIndexKind_ == AtomIndexKind::ParserAtomIndex;
} }
bool isWellKnownAtomId() const { bool isWellKnownAtomId() const {
return atomIndexKind_ == AtomIndexKind::WellKnown; return atomIndexKind_ == AtomIndexKind::WellKnown;
@ -348,11 +342,12 @@ class alignas(alignof(uint32_t)) ParserAtomEntry {
return atomIndexKind_ == AtomIndexKind::Static2; return atomIndexKind_ == AtomIndexKind::Static2;
} }
private: void setParserAtomIndex(ParserAtomIndex index) {
void setAtomIndex(AtomIndex index) {
atomIndex_ = index; atomIndex_ = index;
atomIndexKind_ = AtomIndexKind::AtomIndex; atomIndexKind_ = AtomIndexKind::ParserAtomIndex;
} }
private:
constexpr void setWellKnownAtomId(WellKnownAtomId atomId) { constexpr void setWellKnownAtomId(WellKnownAtomId atomId) {
atomIndex_ = static_cast<uint32_t>(atomId); atomIndex_ = static_cast<uint32_t>(atomId);
atomIndexKind_ = AtomIndexKind::WellKnown; atomIndexKind_ = AtomIndexKind::WellKnown;
@ -648,10 +643,6 @@ class WellKnownParserAtoms {
} }
}; };
// The number of atoms with either usedByStencil or AtomIndex,
// that requires space in CompilationAtomCache.atoms during instantiation.
size_t RequiredNonStaticAtomCount(const ParserAtomVector& entries);
bool InstantiateMarkedAtoms(JSContext* cx, const ParserAtomVector& entries, bool InstantiateMarkedAtoms(JSContext* cx, const ParserAtomVector& entries,
CompilationAtomCache& atomCache); CompilationAtomCache& atomCache);
@ -723,22 +714,23 @@ class ParserAtomVectorBuilder {
ParserAtomVectorBuilder(JSRuntime* rt, LifoAlloc& alloc, ParserAtomVectorBuilder(JSRuntime* rt, LifoAlloc& alloc,
ParserAtomVector& entries); ParserAtomVector& entries);
bool reserve(JSContext* cx, size_t count); bool resize(JSContext* cx, size_t count);
size_t length() const { return entries_.length(); } size_t length() const { return entries_.length(); }
ParserAtom* get(size_t index) { return entries_[index]->asAtom(); } ParserAtom* get(size_t index) { return entries_[index]->asAtom(); }
JS::Result<const ParserAtom*, OOM> internLatin1( JS::Result<const ParserAtom*, OOM> internLatin1At(
JSContext* cx, const JS::Latin1Char* latin1Ptr, HashNumber hash, JSContext* cx, const JS::Latin1Char* latin1Ptr, HashNumber hash,
uint32_t length); uint32_t length, ParserAtomIndex index);
JS::Result<const ParserAtom*, OOM> internChar16( JS::Result<const ParserAtom*, OOM> internChar16At(
JSContext* cx, const LittleEndianChars twoByteLE, HashNumber hash, JSContext* cx, const LittleEndianChars twoByteLE, HashNumber hash,
uint32_t length); uint32_t length, ParserAtomIndex index);
private: private:
template <typename CharT, typename SeqCharT, typename InputCharsT> template <typename CharT, typename SeqCharT, typename InputCharsT>
JS::Result<const ParserAtom*, OOM> intern(JSContext* cx, InputCharsT chars, JS::Result<const ParserAtom*, OOM> internAt(JSContext* cx, InputCharsT chars,
HashNumber hash, uint32_t length); HashNumber hash, uint32_t length,
ParserAtomIndex index);
public: public:
const ParserAtom* getWellKnown(WellKnownAtomId atomId) const; const ParserAtom* getWellKnown(WellKnownAtomId atomId) const;

Просмотреть файл

@ -799,9 +799,7 @@ bool CompilationInfoVector::instantiateStencilsAfterPreparation(
} }
bool CompilationInfo::prepareInputAndStencilForInstantiate(JSContext* cx) { bool CompilationInfo::prepareInputAndStencilForInstantiate(JSContext* cx) {
if (!input.atomCache.atoms.reserve( if (!input.atomCache.allocate(cx, stencil.parserAtomData.length())) {
RequiredNonStaticAtomCount(stencil.parserAtomData))) {
ReportOutOfMemory(cx);
return false; return false;
} }
@ -1583,3 +1581,51 @@ mozilla::Span<ScriptThingVariant> js::frontend::NewScriptThingSpanUninitialized(
return mozilla::Span<ScriptThingVariant>(stencilThings, ngcthings); return mozilla::Span<ScriptThingVariant>(stencilThings, ngcthings);
} }
JSAtom* CompilationAtomCache::getExistingAtomAt(ParserAtomIndex index) const {
return atoms_[index];
}
JSAtom* CompilationAtomCache::getAtomAt(ParserAtomIndex index) const {
if (size_t(index) >= atoms_.length()) {
return nullptr;
}
return atoms_[index];
}
bool CompilationAtomCache::hasAtomAt(ParserAtomIndex index) const {
if (size_t(index) >= atoms_.length()) {
return false;
}
return !!atoms_[index];
}
bool CompilationAtomCache::setAtomAt(JSContext* cx, ParserAtomIndex index,
JSAtom* atom) {
if (size_t(index) < atoms_.length()) {
atoms_[index] = atom;
return true;
}
if (!atoms_.resize(size_t(index) + 1)) {
ReportOutOfMemory(cx);
return false;
}
atoms_[index] = atom;
return true;
}
bool CompilationAtomCache::allocate(JSContext* cx, size_t length) {
MOZ_ASSERT(length >= atoms_.length());
if (length == atoms_.length()) {
return true;
}
if (!atoms_.resize(length)) {
ReportOutOfMemory(cx);
return false;
}
return true;
}

Просмотреть файл

@ -305,45 +305,52 @@ template <XDRMode mode>
static XDRResult ParserAtomTable(XDRState<mode>* xdr, static XDRResult ParserAtomTable(XDRState<mode>* xdr,
frontend::CompilationStencil& stencil) { frontend::CompilationStencil& stencil) {
if (mode == XDR_ENCODE) { if (mode == XDR_ENCODE) {
uint32_t atomVectorLength = stencil.parserAtomData.length();
MOZ_TRY(XDRAtomCount(xdr, &atomVectorLength));
uint32_t atomCount = 0; uint32_t atomCount = 0;
for (const auto& entry : stencil.parserAtomData) { for (const auto& entry : stencil.parserAtomData) {
if (!entry) {
continue;
}
if (entry->isUsedByStencil()) { if (entry->isUsedByStencil()) {
atomCount++; atomCount++;
} }
} }
MOZ_TRY(XDRAtomCount(xdr, &atomCount)); MOZ_TRY(XDRAtomCount(xdr, &atomCount));
if (!xdr->parserAtomMap().reserve(atomCount)) {
return xdr->fail(JS::TranscodeResult_Throw);
}
uint32_t index = 0;
for (const auto& entry : stencil.parserAtomData) { for (const auto& entry : stencil.parserAtomData) {
if (!entry) {
continue;
}
if (entry->isUsedByStencil()) { if (entry->isUsedByStencil()) {
const frontend::ParserAtom* atom = entry->asAtom(); const frontend::ParserAtom* atom = entry->asAtom();
MOZ_TRY(XDRParserAtomData(xdr, &atom)); uint32_t index = atom->toParserAtomIndex();
MOZ_TRY(xdr->codeUint32(&index));
xdr->parserAtomMap().putNewInfallible(atom, index); MOZ_TRY(
index++; XDRParserAtomDataAt(xdr, &atom, frontend::ParserAtomIndex(index)));
} }
} }
return Ok(); return Ok();
} }
uint32_t atomVectorLength;
MOZ_TRY(XDRAtomCount(xdr, &atomVectorLength));
if (!xdr->frontendAtoms().resize(xdr->cx(), atomVectorLength)) {
return xdr->fail(JS::TranscodeResult_Throw);
}
uint32_t atomCount; uint32_t atomCount;
MOZ_TRY(XDRAtomCount(xdr, &atomCount)); MOZ_TRY(XDRAtomCount(xdr, &atomCount));
MOZ_ASSERT(!xdr->hasAtomTable()); MOZ_ASSERT(!xdr->hasAtomTable());
if (!xdr->frontendAtoms().reserve(xdr->cx(), atomCount)) {
return xdr->fail(JS::TranscodeResult_Throw);
}
for (uint32_t i = 0; i < atomCount; i++) { for (uint32_t i = 0; i < atomCount; i++) {
const frontend::ParserAtom* atom = nullptr; const frontend::ParserAtom* atom = nullptr;
MOZ_TRY(XDRParserAtomData(xdr, &atom)); uint32_t index;
MOZ_TRY(xdr->codeUint32(&index));
MOZ_TRY(XDRParserAtomDataAt(xdr, &atom, frontend::ParserAtomIndex(index)));
} }
xdr->finishAtomTable(); xdr->finishAtomTable();
@ -457,7 +464,6 @@ XDRResult XDRState<mode>::codeStencil(
MOZ_ASSERT(isMainBuf()); MOZ_ASSERT(isMainBuf());
MOZ_TRY(XDRCompilationStencil(this, compilationInfo.stencil)); MOZ_TRY(XDRCompilationStencil(this, compilationInfo.stencil));
MOZ_TRY(finishChunk());
return Ok(); return Ok();
} }
@ -478,7 +484,6 @@ XDRResult XDRState<mode>::codeFunctionStencil(
MOZ_TRY(ParserAtomTable(this, stencil)); MOZ_TRY(ParserAtomTable(this, stencil));
MOZ_TRY(XDRCompilationStencil(this, stencil)); MOZ_TRY(XDRCompilationStencil(this, stencil));
MOZ_TRY(finishChunk());
return Ok(); return Ok();
} }
@ -709,12 +714,6 @@ XDRResult XDRIncrementalEncoder::linearize(JS::TranscodeBuffer& buffer) {
return Ok(); return Ok();
} }
XDRResult XDRIncrementalStencilEncoder::finishChunk() {
parserAtomMap_.clear();
return Ok();
}
XDRResult XDRIncrementalStencilEncoder::linearize(JS::TranscodeBuffer& buffer) { XDRResult XDRIncrementalStencilEncoder::linearize(JS::TranscodeBuffer& buffer) {
switchToHeaderBuf(); switchToHeaderBuf();

Просмотреть файл

@ -45,8 +45,6 @@ using XDRResult = XDRResultT<mozilla::Ok>;
using XDRAtomTable = JS::GCVector<PreBarriered<JSAtom*>>; using XDRAtomTable = JS::GCVector<PreBarriered<JSAtom*>>;
using XDRAtomMap = JS::GCHashMap<PreBarriered<JSAtom*>, uint32_t>; using XDRAtomMap = JS::GCHashMap<PreBarriered<JSAtom*>, uint32_t>;
using XDRParserAtomMap = HashMap<const frontend::ParserAtom*, uint32_t>;
class XDRBufferBase { class XDRBufferBase {
public: public:
explicit XDRBufferBase(JSContext* cx, size_t cursor = 0) explicit XDRBufferBase(JSContext* cx, size_t cursor = 0)
@ -262,10 +260,6 @@ class XDRState : public XDRCoderBase {
virtual bool hasAtomMap() const { return false; } virtual bool hasAtomMap() const { return false; }
virtual XDRAtomMap& atomMap() { MOZ_CRASH("does not have atomMap"); } virtual XDRAtomMap& atomMap() { MOZ_CRASH("does not have atomMap"); }
virtual XDRParserAtomMap& parserAtomMap() {
// This accessor is only used when encoding stencils.
MOZ_CRASH("does not have parserAtomMap");
}
virtual uint32_t& natoms() { MOZ_CRASH("does not have atomMap."); } virtual uint32_t& natoms() { MOZ_CRASH("does not have atomMap."); }
// The number of chunks (CompilationStencils) in the buffer. // The number of chunks (CompilationStencils) in the buffer.
@ -287,7 +281,6 @@ class XDRState : public XDRCoderBase {
MOZ_CRASH("cannot switch to header buffer."); MOZ_CRASH("cannot switch to header buffer.");
} }
virtual XDRResult finishChunk() { return Ok(); }
virtual XDRResult codeDelazificationStencils( virtual XDRResult codeDelazificationStencils(
frontend::CompilationInfoVector& compilationInfos) { frontend::CompilationInfoVector& compilationInfos) {
MOZ_CRASH("cannot code delazification stencils."); MOZ_CRASH("cannot code delazification stencils.");
@ -734,10 +727,6 @@ class XDRIncrementalStencilEncoder : public XDRIncrementalEncoderBase {
// b. atoms // b. atoms
// c. CompilationStencil // c. CompilationStencil
// Map from atoms to their index in the atom buffer
// Reset for each chunk.
XDRParserAtomMap parserAtomMap_;
using FunctionKey = uint64_t; using FunctionKey = uint64_t;
static FunctionKey toFunctionKey(const SourceExtent& extent); static FunctionKey toFunctionKey(const SourceExtent& extent);
@ -748,9 +737,7 @@ class XDRIncrementalStencilEncoder : public XDRIncrementalEncoderBase {
public: public:
explicit XDRIncrementalStencilEncoder(JSContext* cx) explicit XDRIncrementalStencilEncoder(JSContext* cx)
: XDRIncrementalEncoderBase(cx), : XDRIncrementalEncoderBase(cx), encodedFunctions_(cx) {}
parserAtomMap_(cx),
encodedFunctions_(cx) {}
virtual ~XDRIncrementalStencilEncoder() = default; virtual ~XDRIncrementalStencilEncoder() = default;
@ -759,11 +746,6 @@ class XDRIncrementalStencilEncoder : public XDRIncrementalEncoderBase {
bool isForStencil() const override { return true; } bool isForStencil() const override { return true; }
bool hasAtomMap() const override { return true; }
XDRParserAtomMap& parserAtomMap() override { return parserAtomMap_; }
XDRResult finishChunk() override;
XDRResult linearize(JS::TranscodeBuffer& buffer) override; XDRResult linearize(JS::TranscodeBuffer& buffer) override;
XDRResult codeStencils(frontend::CompilationInfoVector& compilationInfos); XDRResult codeStencils(frontend::CompilationInfoVector& compilationInfos);
@ -783,8 +765,9 @@ XDRResult XDRParserAtom(XDRState<mode>* xdr,
const frontend::ParserAtom** atomp); const frontend::ParserAtom** atomp);
template <XDRMode mode> template <XDRMode mode>
XDRResult XDRParserAtomData(XDRState<mode>* xdr, XDRResult XDRParserAtomDataAt(XDRState<mode>* xdr,
const frontend::ParserAtom** atomp); const frontend::ParserAtom** atomp,
frontend::ParserAtomIndex index);
template <XDRMode mode> template <XDRMode mode>
XDRResult XDRParserAtomOrNull(XDRState<mode>* xdr, XDRResult XDRParserAtomOrNull(XDRState<mode>* xdr,