зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1676688 - Part 3: Merge AtomIndex and ParserAtomIndex. r=tcampbell
Differential Revision: https://phabricator.services.mozilla.com/D96812
This commit is contained in:
Родитель
9b9b55b106
Коммит
cee7e57c4c
|
@ -1207,7 +1207,7 @@ void CompilationInput::trace(JSTracer* trc) {
|
|||
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); }
|
||||
|
||||
|
|
|
@ -93,12 +93,20 @@ struct ScopeContext {
|
|||
};
|
||||
|
||||
struct CompilationAtomCache {
|
||||
private:
|
||||
// Atoms lowered into or converted from CompilationStencil.parserAtomData.
|
||||
//
|
||||
// This field is here instead of in CompilationGCOutput because atoms lowered
|
||||
// from JSAtom is part of input (enclosing scope bindings, lazy function name,
|
||||
// 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);
|
||||
} JS_HAZ_GC_POINTER;
|
||||
|
@ -252,6 +260,8 @@ struct CompilationStencil {
|
|||
asmJS;
|
||||
|
||||
// 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;
|
||||
|
||||
// Parameterized chunk size to use for LifoAlloc.
|
||||
|
|
|
@ -216,8 +216,13 @@ bool ParserAtomEntry::isIndex(uint32_t* indexp) const {
|
|||
JSAtom* ParserAtomEntry::toJSAtom(JSContext* cx,
|
||||
CompilationAtomCache& atomCache) const {
|
||||
switch (atomIndexKind_) {
|
||||
case AtomIndexKind::AtomIndex:
|
||||
return atomCache.atoms[atomIndex_];
|
||||
case AtomIndexKind::ParserAtomIndex: {
|
||||
JSAtom* atom = atomCache.getAtomAt(toParserAtomIndex());
|
||||
if (atom) {
|
||||
return atom;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case AtomIndexKind::WellKnown:
|
||||
return GetWellKnownAtom(cx, WellKnownAtomId(atomIndex_));
|
||||
|
@ -229,9 +234,6 @@ JSAtom* ParserAtomEntry::toJSAtom(JSContext* cx,
|
|||
|
||||
case AtomIndexKind::Static2:
|
||||
return cx->staticStrings().getLength2FromIndex(atomIndex_);
|
||||
|
||||
case AtomIndexKind::NotInstantiated:
|
||||
break;
|
||||
}
|
||||
|
||||
return instantiate(cx, atomCache);
|
||||
|
@ -240,8 +242,11 @@ JSAtom* ParserAtomEntry::toJSAtom(JSContext* cx,
|
|||
JSAtom* ParserAtomEntry::toExistingJSAtom(
|
||||
JSContext* cx, CompilationAtomCache& atomCache) const {
|
||||
switch (atomIndexKind_) {
|
||||
case AtomIndexKind::AtomIndex:
|
||||
return atomCache.atoms[atomIndex_];
|
||||
case AtomIndexKind::ParserAtomIndex: {
|
||||
JSAtom* atom = atomCache.getExistingAtomAt(toParserAtomIndex());
|
||||
MOZ_ASSERT(atom);
|
||||
return atom;
|
||||
}
|
||||
|
||||
case AtomIndexKind::WellKnown:
|
||||
return GetWellKnownAtom(cx, WellKnownAtomId(atomIndex_));
|
||||
|
@ -253,9 +258,6 @@ JSAtom* ParserAtomEntry::toExistingJSAtom(
|
|||
|
||||
case AtomIndexKind::Static2:
|
||||
return cx->staticStrings().getLength2FromIndex(atomIndex_);
|
||||
|
||||
case AtomIndexKind::NotInstantiated:
|
||||
MOZ_CRASH("ParserAtom should already be instantiated");
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -263,8 +265,6 @@ JSAtom* ParserAtomEntry::toExistingJSAtom(
|
|||
|
||||
JSAtom* ParserAtomEntry::instantiate(JSContext* cx,
|
||||
CompilationAtomCache& atomCache) const {
|
||||
MOZ_ASSERT(isNotInstantiated());
|
||||
|
||||
JSAtom* atom;
|
||||
if (hasLatin1Chars()) {
|
||||
atom = AtomizeChars(cx, hash(), latin1Chars(), length());
|
||||
|
@ -275,17 +275,10 @@ JSAtom* ParserAtomEntry::instantiate(JSContext* cx,
|
|||
js::ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
auto index = atomCache.atoms.length();
|
||||
|
||||
// This cannot be infallibleAppend because there are toJSAtom consumers that
|
||||
// doesn't reserve CompilationAtomCache.atoms beforehand
|
||||
if (!atomCache.atoms.append(atom)) {
|
||||
js::ReportOutOfMemory(cx);
|
||||
if (!atomCache.setAtomAt(cx, toParserAtomIndex(), atom)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const_cast<ParserAtomEntry*>(this)->setAtomIndex(AtomIndex(index));
|
||||
|
||||
return atom;
|
||||
}
|
||||
|
||||
|
@ -328,6 +321,7 @@ JS::Result<const ParserAtom*, OOM> ParserAtomsTable::addEntry(
|
|||
if (!entries_.append(entry)) {
|
||||
return RaiseParserAtomsOOMError(cx);
|
||||
}
|
||||
entry->setParserAtomIndex(index);
|
||||
if (!entryMap_.add(addPtr, entry, index)) {
|
||||
return RaiseParserAtomsOOMError(cx);
|
||||
}
|
||||
|
@ -385,27 +379,27 @@ ParserAtomVectorBuilder::ParserAtomVectorBuilder(JSRuntime* rt,
|
|||
alloc_(&alloc),
|
||||
entries_(entries) {}
|
||||
|
||||
bool ParserAtomVectorBuilder::reserve(JSContext* cx, size_t count) {
|
||||
bool ParserAtomVectorBuilder::resize(JSContext* cx, size_t count) {
|
||||
if (count >= TaggedParserAtomIndex::IndexLimit) {
|
||||
ReportAllocationOverflow(cx);
|
||||
return false;
|
||||
}
|
||||
if (!entries_.reserve(count)) {
|
||||
if (!entries_.resize(count)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::internLatin1(
|
||||
JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::internLatin1At(
|
||||
JSContext* cx, const Latin1Char* latin1Ptr, HashNumber hash,
|
||||
uint32_t length) {
|
||||
return intern<Latin1Char, Latin1Char>(cx, latin1Ptr, hash, length);
|
||||
uint32_t length, ParserAtomIndex index) {
|
||||
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,
|
||||
uint32_t length) {
|
||||
uint32_t length, ParserAtomIndex index) {
|
||||
#ifdef DEBUG
|
||||
InflatedChar16Sequence<LittleEndianChars> seq(twoByteLE, length);
|
||||
bool wide = false;
|
||||
|
@ -419,12 +413,14 @@ JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::internChar16(
|
|||
MOZ_ASSERT(wide);
|
||||
#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>
|
||||
JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::intern(
|
||||
JSContext* cx, InputCharsT chars, HashNumber hash, uint32_t length) {
|
||||
JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::internAt(
|
||||
JSContext* cx, InputCharsT chars, HashNumber hash, uint32_t length,
|
||||
ParserAtomIndex index) {
|
||||
InflatedChar16Sequence<SeqCharT> seq(chars, length);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -437,9 +433,9 @@ JS::Result<const ParserAtom*, OOM> ParserAtomVectorBuilder::intern(
|
|||
ParserAtomEntry* entry;
|
||||
MOZ_TRY_VAR(entry,
|
||||
ParserAtomEntry::allocate<CharT>(cx, *alloc_, seq, length, hash));
|
||||
if (!entries_.append(entry)) {
|
||||
return RaiseParserAtomsOOMError(cx);
|
||||
}
|
||||
entry->setParserAtomIndex(index);
|
||||
entries_[index] = entry;
|
||||
|
||||
return entry->asAtom();
|
||||
}
|
||||
|
||||
|
@ -533,7 +529,7 @@ JS::Result<const ParserAtom*, OOM> ParserAtomsTable::internChar16(
|
|||
|
||||
JS::Result<const ParserAtom*, OOM> ParserAtomsTable::internJSAtom(
|
||||
JSContext* cx, CompilationInfo& compilationInfo, JSAtom* atom) {
|
||||
const ParserAtom* id;
|
||||
const ParserAtom* parserAtom;
|
||||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
|
||||
|
@ -544,24 +540,24 @@ JS::Result<const ParserAtom*, OOM> ParserAtomsTable::internJSAtom(
|
|||
if (result.isErr()) {
|
||||
return result;
|
||||
}
|
||||
id = result.unwrap();
|
||||
parserAtom = result.unwrap();
|
||||
}
|
||||
|
||||
if (id->isNotInstantiated()) {
|
||||
MOZ_ASSERT(id->equalsJSAtom(atom));
|
||||
if (parserAtom->isParserAtomIndex()) {
|
||||
ParserAtomIndex index = parserAtom->toParserAtomIndex();
|
||||
auto& atomCache = compilationInfo.input.atomCache;
|
||||
|
||||
auto index = AtomIndex(compilationInfo.input.atomCache.atoms.length());
|
||||
if (!compilationInfo.input.atomCache.atoms.append(atom)) {
|
||||
return RaiseParserAtomsOOMError(cx);
|
||||
if (!atomCache.hasAtomAt(index)) {
|
||||
if (!atomCache.setAtomAt(cx, index, atom)) {
|
||||
return mozilla::Err(PARSER_ATOMS_OOM);
|
||||
}
|
||||
}
|
||||
|
||||
const_cast<ParserAtom*>(id)->setAtomIndex(AtomIndex(index));
|
||||
}
|
||||
|
||||
// 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(
|
||||
|
@ -643,20 +639,14 @@ const ParserAtom* ParserAtomVectorBuilder::getStatic2(
|
|||
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,
|
||||
CompilationAtomCache& atomCache) {
|
||||
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)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -818,7 +808,8 @@ static XDRResult XDRParserAtomTaggedIndex(XDRState<mode>* xdr,
|
|||
}
|
||||
|
||||
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,
|
||||
"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)));
|
||||
chars = reinterpret_cast<const Latin1Char*>(ptr);
|
||||
}
|
||||
mbAtom = xdr->frontendAtoms().internLatin1(cx, chars, hash, length);
|
||||
mbAtom =
|
||||
xdr->frontendAtoms().internLatin1At(cx, chars, hash, length, index);
|
||||
} else {
|
||||
const uint8_t* twoByteCharsLE = nullptr;
|
||||
if (length) {
|
||||
MOZ_TRY(xdr->peekData(&twoByteCharsLE, length * sizeof(char16_t)));
|
||||
}
|
||||
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);
|
||||
|
@ -888,16 +881,16 @@ XDRResult XDRParserAtomData(XDRState<mode>* xdr, const ParserAtom** atomp) {
|
|||
return Ok();
|
||||
}
|
||||
|
||||
template XDRResult XDRParserAtomData(XDRState<XDR_ENCODE>* xdr,
|
||||
const ParserAtom** atomp);
|
||||
template XDRResult XDRParserAtomData(XDRState<XDR_DECODE>* xdr,
|
||||
const ParserAtom** atomp);
|
||||
template XDRResult XDRParserAtomDataAt(XDRState<XDR_ENCODE>* xdr,
|
||||
const ParserAtom** atomp,
|
||||
ParserAtomIndex index);
|
||||
template XDRResult XDRParserAtomDataAt(XDRState<XDR_DECODE>* xdr,
|
||||
const ParserAtom** atomp,
|
||||
ParserAtomIndex index);
|
||||
|
||||
template <XDRMode mode>
|
||||
XDRResult XDRParserAtom(XDRState<mode>* xdr, const ParserAtom** atomp) {
|
||||
if (mode == XDR_ENCODE) {
|
||||
MOZ_ASSERT(xdr->hasAtomMap());
|
||||
|
||||
uint32_t atomIndex;
|
||||
ParserAtomTag tag = ParserAtomTag::Normal;
|
||||
if ((*atomp)->isWellKnownAtomId()) {
|
||||
|
@ -910,14 +903,7 @@ XDRResult XDRParserAtom(XDRState<mode>* xdr, const ParserAtom** atomp) {
|
|||
atomIndex = uint32_t((*atomp)->toStaticParserString2());
|
||||
tag = ParserAtomTag::Static2;
|
||||
} else {
|
||||
MOZ_ASSERT((*atomp)->isNotInstantiated() || (*atomp)->isAtomIndex());
|
||||
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();
|
||||
atomIndex = uint32_t((*atomp)->toParserAtomIndex());
|
||||
tag = ParserAtomTag::Normal;
|
||||
}
|
||||
MOZ_TRY(XDRParserAtomTaggedIndex(xdr, &tag, &atomIndex));
|
||||
|
|
|
@ -35,10 +35,6 @@ class ParserAtomsTable;
|
|||
|
||||
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().
|
||||
// This is consistent across multiple compilation.
|
||||
//
|
||||
|
@ -209,10 +205,8 @@ class alignas(alignof(uint32_t)) ParserAtomEntry {
|
|||
|
||||
// Mapping into from ParserAtoms to JSAtoms.
|
||||
enum class AtomIndexKind : uint8_t {
|
||||
// Not yet instantiated
|
||||
NotInstantiated,
|
||||
// Index into CompilationAtomCache
|
||||
AtomIndex,
|
||||
// Index into CompilationStencil.parserAtomData.
|
||||
ParserAtomIndex,
|
||||
// WellKnownAtomId to index into cx->names() set
|
||||
WellKnown,
|
||||
// Index into StaticStrings length-1 set
|
||||
|
@ -221,12 +215,12 @@ class alignas(alignof(uint32_t)) ParserAtomEntry {
|
|||
Static2,
|
||||
};
|
||||
uint32_t atomIndex_ = 0;
|
||||
AtomIndexKind atomIndexKind_ = AtomIndexKind::NotInstantiated;
|
||||
AtomIndexKind atomIndexKind_ = AtomIndexKind::ParserAtomIndex;
|
||||
|
||||
// Encoding type.
|
||||
bool hasTwoByteChars_ = false;
|
||||
|
||||
// Other flags.
|
||||
// Mutable flags.
|
||||
bool usedByStencil_ = false;
|
||||
|
||||
// End of fields.
|
||||
|
@ -304,13 +298,9 @@ class alignas(alignof(uint32_t)) ParserAtomEntry {
|
|||
HashNumber hash() const { return hash_; }
|
||||
uint32_t length() const { return length_; }
|
||||
|
||||
bool isNotInstantiated() const {
|
||||
return atomIndexKind_ == AtomIndexKind::NotInstantiated;
|
||||
}
|
||||
|
||||
bool isUsedByStencil() const { return usedByStencil_; }
|
||||
void markUsedByStencil() const {
|
||||
if ((isNotInstantiated() || isAtomIndex())) {
|
||||
if (isParserAtomIndex()) {
|
||||
// Use const method + const_cast here to avoid marking static strings'
|
||||
// field mutable.
|
||||
const_cast<ParserAtomEntry*>(this)->usedByStencil_ = true;
|
||||
|
@ -322,6 +312,10 @@ class alignas(alignof(uint32_t)) ParserAtomEntry {
|
|||
template <typename CharT>
|
||||
bool equalsSeq(HashNumber hash, InflatedChar16Sequence<CharT> seq) const;
|
||||
|
||||
ParserAtomIndex toParserAtomIndex() const {
|
||||
MOZ_ASSERT(isParserAtomIndex());
|
||||
return ParserAtomIndex(atomIndex_);
|
||||
}
|
||||
WellKnownAtomId toWellKnownAtomId() const {
|
||||
MOZ_ASSERT(isWellKnownAtomId());
|
||||
return WellKnownAtomId(atomIndex_);
|
||||
|
@ -335,8 +329,8 @@ class alignas(alignof(uint32_t)) ParserAtomEntry {
|
|||
return StaticParserString2(atomIndex_);
|
||||
}
|
||||
|
||||
bool isAtomIndex() const {
|
||||
return atomIndexKind_ == AtomIndexKind::AtomIndex;
|
||||
bool isParserAtomIndex() const {
|
||||
return atomIndexKind_ == AtomIndexKind::ParserAtomIndex;
|
||||
}
|
||||
bool isWellKnownAtomId() const {
|
||||
return atomIndexKind_ == AtomIndexKind::WellKnown;
|
||||
|
@ -348,11 +342,12 @@ class alignas(alignof(uint32_t)) ParserAtomEntry {
|
|||
return atomIndexKind_ == AtomIndexKind::Static2;
|
||||
}
|
||||
|
||||
private:
|
||||
void setAtomIndex(AtomIndex index) {
|
||||
void setParserAtomIndex(ParserAtomIndex index) {
|
||||
atomIndex_ = index;
|
||||
atomIndexKind_ = AtomIndexKind::AtomIndex;
|
||||
atomIndexKind_ = AtomIndexKind::ParserAtomIndex;
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr void setWellKnownAtomId(WellKnownAtomId atomId) {
|
||||
atomIndex_ = static_cast<uint32_t>(atomId);
|
||||
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,
|
||||
CompilationAtomCache& atomCache);
|
||||
|
||||
|
@ -723,22 +714,23 @@ class ParserAtomVectorBuilder {
|
|||
ParserAtomVectorBuilder(JSRuntime* rt, LifoAlloc& alloc,
|
||||
ParserAtomVector& entries);
|
||||
|
||||
bool reserve(JSContext* cx, size_t count);
|
||||
bool resize(JSContext* cx, size_t count);
|
||||
size_t length() const { return entries_.length(); }
|
||||
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,
|
||||
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,
|
||||
uint32_t length);
|
||||
uint32_t length, ParserAtomIndex index);
|
||||
|
||||
private:
|
||||
template <typename CharT, typename SeqCharT, typename InputCharsT>
|
||||
JS::Result<const ParserAtom*, OOM> intern(JSContext* cx, InputCharsT chars,
|
||||
HashNumber hash, uint32_t length);
|
||||
JS::Result<const ParserAtom*, OOM> internAt(JSContext* cx, InputCharsT chars,
|
||||
HashNumber hash, uint32_t length,
|
||||
ParserAtomIndex index);
|
||||
|
||||
public:
|
||||
const ParserAtom* getWellKnown(WellKnownAtomId atomId) const;
|
||||
|
|
|
@ -799,9 +799,7 @@ bool CompilationInfoVector::instantiateStencilsAfterPreparation(
|
|||
}
|
||||
|
||||
bool CompilationInfo::prepareInputAndStencilForInstantiate(JSContext* cx) {
|
||||
if (!input.atomCache.atoms.reserve(
|
||||
RequiredNonStaticAtomCount(stencil.parserAtomData))) {
|
||||
ReportOutOfMemory(cx);
|
||||
if (!input.atomCache.allocate(cx, stencil.parserAtomData.length())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1583,3 +1581,51 @@ mozilla::Span<ScriptThingVariant> js::frontend::NewScriptThingSpanUninitialized(
|
|||
|
||||
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,
|
||||
frontend::CompilationStencil& stencil) {
|
||||
if (mode == XDR_ENCODE) {
|
||||
uint32_t atomVectorLength = stencil.parserAtomData.length();
|
||||
MOZ_TRY(XDRAtomCount(xdr, &atomVectorLength));
|
||||
|
||||
uint32_t atomCount = 0;
|
||||
for (const auto& entry : stencil.parserAtomData) {
|
||||
if (!entry) {
|
||||
continue;
|
||||
}
|
||||
if (entry->isUsedByStencil()) {
|
||||
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) {
|
||||
if (!entry) {
|
||||
continue;
|
||||
}
|
||||
if (entry->isUsedByStencil()) {
|
||||
const frontend::ParserAtom* atom = entry->asAtom();
|
||||
MOZ_TRY(XDRParserAtomData(xdr, &atom));
|
||||
|
||||
xdr->parserAtomMap().putNewInfallible(atom, index);
|
||||
index++;
|
||||
uint32_t index = atom->toParserAtomIndex();
|
||||
MOZ_TRY(xdr->codeUint32(&index));
|
||||
MOZ_TRY(
|
||||
XDRParserAtomDataAt(xdr, &atom, frontend::ParserAtomIndex(index)));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
MOZ_TRY(XDRAtomCount(xdr, &atomCount));
|
||||
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++) {
|
||||
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();
|
||||
|
||||
|
@ -457,7 +464,6 @@ XDRResult XDRState<mode>::codeStencil(
|
|||
|
||||
MOZ_ASSERT(isMainBuf());
|
||||
MOZ_TRY(XDRCompilationStencil(this, compilationInfo.stencil));
|
||||
MOZ_TRY(finishChunk());
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
@ -478,7 +484,6 @@ XDRResult XDRState<mode>::codeFunctionStencil(
|
|||
MOZ_TRY(ParserAtomTable(this, stencil));
|
||||
|
||||
MOZ_TRY(XDRCompilationStencil(this, stencil));
|
||||
MOZ_TRY(finishChunk());
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
@ -709,12 +714,6 @@ XDRResult XDRIncrementalEncoder::linearize(JS::TranscodeBuffer& buffer) {
|
|||
return Ok();
|
||||
}
|
||||
|
||||
XDRResult XDRIncrementalStencilEncoder::finishChunk() {
|
||||
parserAtomMap_.clear();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
XDRResult XDRIncrementalStencilEncoder::linearize(JS::TranscodeBuffer& buffer) {
|
||||
switchToHeaderBuf();
|
||||
|
||||
|
|
|
@ -45,8 +45,6 @@ using XDRResult = XDRResultT<mozilla::Ok>;
|
|||
using XDRAtomTable = JS::GCVector<PreBarriered<JSAtom*>>;
|
||||
using XDRAtomMap = JS::GCHashMap<PreBarriered<JSAtom*>, uint32_t>;
|
||||
|
||||
using XDRParserAtomMap = HashMap<const frontend::ParserAtom*, uint32_t>;
|
||||
|
||||
class XDRBufferBase {
|
||||
public:
|
||||
explicit XDRBufferBase(JSContext* cx, size_t cursor = 0)
|
||||
|
@ -262,10 +260,6 @@ class XDRState : public XDRCoderBase {
|
|||
|
||||
virtual bool hasAtomMap() const { return false; }
|
||||
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."); }
|
||||
|
||||
// The number of chunks (CompilationStencils) in the buffer.
|
||||
|
@ -287,7 +281,6 @@ class XDRState : public XDRCoderBase {
|
|||
MOZ_CRASH("cannot switch to header buffer.");
|
||||
}
|
||||
|
||||
virtual XDRResult finishChunk() { return Ok(); }
|
||||
virtual XDRResult codeDelazificationStencils(
|
||||
frontend::CompilationInfoVector& compilationInfos) {
|
||||
MOZ_CRASH("cannot code delazification stencils.");
|
||||
|
@ -734,10 +727,6 @@ class XDRIncrementalStencilEncoder : public XDRIncrementalEncoderBase {
|
|||
// b. atoms
|
||||
// c. CompilationStencil
|
||||
|
||||
// Map from atoms to their index in the atom buffer
|
||||
// Reset for each chunk.
|
||||
XDRParserAtomMap parserAtomMap_;
|
||||
|
||||
using FunctionKey = uint64_t;
|
||||
static FunctionKey toFunctionKey(const SourceExtent& extent);
|
||||
|
||||
|
@ -748,9 +737,7 @@ class XDRIncrementalStencilEncoder : public XDRIncrementalEncoderBase {
|
|||
|
||||
public:
|
||||
explicit XDRIncrementalStencilEncoder(JSContext* cx)
|
||||
: XDRIncrementalEncoderBase(cx),
|
||||
parserAtomMap_(cx),
|
||||
encodedFunctions_(cx) {}
|
||||
: XDRIncrementalEncoderBase(cx), encodedFunctions_(cx) {}
|
||||
|
||||
virtual ~XDRIncrementalStencilEncoder() = default;
|
||||
|
||||
|
@ -759,11 +746,6 @@ class XDRIncrementalStencilEncoder : public XDRIncrementalEncoderBase {
|
|||
|
||||
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 codeStencils(frontend::CompilationInfoVector& compilationInfos);
|
||||
|
@ -783,8 +765,9 @@ XDRResult XDRParserAtom(XDRState<mode>* xdr,
|
|||
const frontend::ParserAtom** atomp);
|
||||
|
||||
template <XDRMode mode>
|
||||
XDRResult XDRParserAtomData(XDRState<mode>* xdr,
|
||||
const frontend::ParserAtom** atomp);
|
||||
XDRResult XDRParserAtomDataAt(XDRState<mode>* xdr,
|
||||
const frontend::ParserAtom** atomp,
|
||||
frontend::ParserAtomIndex index);
|
||||
|
||||
template <XDRMode mode>
|
||||
XDRResult XDRParserAtomOrNull(XDRState<mode>* xdr,
|
||||
|
|
Загрузка…
Ссылка в новой задаче