зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1667697 - Do not transcode well-known parser atoms and short atoms. r=djvj,tcampbell
Differential Revision: https://phabricator.services.mozilla.com/D91922
This commit is contained in:
Родитель
8d1987c5dd
Коммит
f542b51fae
|
@ -111,7 +111,7 @@ namespace frontend {
|
||||||
|
|
||||||
static JS::OOM PARSER_ATOMS_OOM;
|
static JS::OOM PARSER_ATOMS_OOM;
|
||||||
|
|
||||||
static JSAtom* GetWellKnownAtom(JSContext* cx, WellKnownAtomId kind) {
|
static JSAtom* GetWellKnownAtom(JSContext* cx, WellKnownAtomId atomId) {
|
||||||
#define ASSERT_OFFSET_(idpart, id, text) \
|
#define ASSERT_OFFSET_(idpart, id, text) \
|
||||||
static_assert(offsetof(JSAtomState, id) == \
|
static_assert(offsetof(JSAtomState, id) == \
|
||||||
int32_t(WellKnownAtomId::id) * \
|
int32_t(WellKnownAtomId::id) * \
|
||||||
|
@ -129,7 +129,7 @@ static JSAtom* GetWellKnownAtom(JSContext* cx, WellKnownAtomId kind) {
|
||||||
static_assert(int32_t(WellKnownAtomId::abort) == 0,
|
static_assert(int32_t(WellKnownAtomId::abort) == 0,
|
||||||
"Unexpected order of WellKnownAtom");
|
"Unexpected order of WellKnownAtom");
|
||||||
|
|
||||||
return (&cx->names().abort)[int32_t(kind)];
|
return (&cx->names().abort)[int32_t(atomId)];
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::GenericErrorResult<OOM> RaiseParserAtomsOOMError(JSContext* cx) {
|
mozilla::GenericErrorResult<OOM> RaiseParserAtomsOOMError(JSContext* cx) {
|
||||||
|
@ -555,6 +555,33 @@ JS::Result<const ParserAtom*, OOM> ParserAtomsTable::concatAtoms(
|
||||||
catLen);
|
catLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ParserAtom* ParserAtomsTable::getWellKnown(WellKnownAtomId atomId) const {
|
||||||
|
#define ASSERT_OFFSET_(idpart, id, text) \
|
||||||
|
static_assert(offsetof(WellKnownParserAtoms, id) == \
|
||||||
|
int32_t(WellKnownAtomId::id) * sizeof(ParserAtom*));
|
||||||
|
FOR_EACH_COMMON_PROPERTYNAME(ASSERT_OFFSET_);
|
||||||
|
#undef ASSERT_OFFSET_
|
||||||
|
|
||||||
|
#define ASSERT_OFFSET_(name, clasp) \
|
||||||
|
static_assert(offsetof(WellKnownParserAtoms, name) == \
|
||||||
|
int32_t(WellKnownAtomId::name) * sizeof(ParserAtom*));
|
||||||
|
JS_FOR_EACH_PROTOTYPE(ASSERT_OFFSET_);
|
||||||
|
#undef ASSERT_OFFSET_
|
||||||
|
|
||||||
|
static_assert(int32_t(WellKnownAtomId::abort) == 0,
|
||||||
|
"Unexpected order of WellKnownAtom");
|
||||||
|
|
||||||
|
return (&wellKnownTable_.abort)[int32_t(atomId)];
|
||||||
|
}
|
||||||
|
|
||||||
|
const ParserAtom* ParserAtomsTable::getStatic1(StaticParserString1 s) const {
|
||||||
|
return WellKnownParserAtoms::rom_.length1Table[size_t(s)].asAtom();
|
||||||
|
}
|
||||||
|
|
||||||
|
const ParserAtom* ParserAtomsTable::getStatic2(StaticParserString2 s) const {
|
||||||
|
return WellKnownParserAtoms::rom_.length2Table[size_t(s)].asAtom();
|
||||||
|
}
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
const ParserAtom* WellKnownParserAtoms::lookupChar16Seq(
|
const ParserAtom* WellKnownParserAtoms::lookupChar16Seq(
|
||||||
const SpecificParserAtomLookup<CharT>& lookup) const {
|
const SpecificParserAtomLookup<CharT>& lookup) const {
|
||||||
|
@ -566,7 +593,7 @@ const ParserAtom* WellKnownParserAtoms::lookupChar16Seq(
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WellKnownParserAtoms::initSingle(JSContext* cx, const ParserName** name,
|
bool WellKnownParserAtoms::initSingle(JSContext* cx, const ParserName** name,
|
||||||
const char* str, WellKnownAtomId kind) {
|
const char* str, WellKnownAtomId atomId) {
|
||||||
MOZ_ASSERT(name != nullptr);
|
MOZ_ASSERT(name != nullptr);
|
||||||
|
|
||||||
unsigned int len = strlen(str);
|
unsigned int len = strlen(str);
|
||||||
|
@ -592,7 +619,7 @@ bool WellKnownParserAtoms::initSingle(JSContext* cx, const ParserName** name,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
UniquePtr<ParserAtomEntry> entry = maybeEntry.unwrap();
|
UniquePtr<ParserAtomEntry> entry = maybeEntry.unwrap();
|
||||||
entry->setWellKnownAtomId(kind);
|
entry->setWellKnownAtomId(atomId);
|
||||||
|
|
||||||
// Save name for returning after moving entry into set.
|
// Save name for returning after moving entry into set.
|
||||||
const ParserName* nm = entry.get()->asName();
|
const ParserName* nm = entry.get()->asName();
|
||||||
|
@ -665,9 +692,59 @@ bool WellKnownParserAtoms::init(JSContext* cx) {
|
||||||
// XDR code.
|
// XDR code.
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
enum class ParserAtomTag : uint32_t {
|
||||||
|
Normal = 0,
|
||||||
|
WellKnown,
|
||||||
|
Static1,
|
||||||
|
Static2,
|
||||||
|
};
|
||||||
|
|
||||||
template <XDRMode mode>
|
template <XDRMode mode>
|
||||||
static XDRResult XDRParserAtomIndex(XDRState<mode>* xdr, uint32_t* index) {
|
static XDRResult XDRParserAtomTaggedIndex(XDRState<mode>* xdr,
|
||||||
return xdr->codeUint32(index);
|
ParserAtomTag* tag, uint32_t* index) {
|
||||||
|
// We encode 2 bit (tag) + 32 bit (index) data in the following format:
|
||||||
|
//
|
||||||
|
// index = 0bAABB'CCDD'EEFF'GGHH'IIJJ'KKLL'MMNN'OOPP
|
||||||
|
// tag = 0bTT
|
||||||
|
//
|
||||||
|
// if index < 0b0011'1111'1111'1111'1111'1111'1111'1111:
|
||||||
|
// single uint32_t = 0bBBCC'DDEE'FFGG'HHII'JJKK'LLMM'NNOO'PPTT
|
||||||
|
// else:
|
||||||
|
// two uint32_t = 0b1111'1111'1111'1111'1111'1111'1111'11TT,
|
||||||
|
// 0bAABB'CCDD'EEFF'GGHH'IIJJ'KKLL'MMNN'OOPP
|
||||||
|
|
||||||
|
constexpr uint32_t TagShift = 2;
|
||||||
|
constexpr uint32_t TagMask = 0b0011;
|
||||||
|
constexpr uint32_t TwoUnitPattern = UINT32_MAX ^ TagMask;
|
||||||
|
constexpr uint32_t CodeLimit = TwoUnitPattern >> TagShift;
|
||||||
|
|
||||||
|
MOZ_ASSERT((uint32_t(*tag) & TagMask) == uint32_t(*tag));
|
||||||
|
|
||||||
|
if (mode == XDR_ENCODE) {
|
||||||
|
if (*index < CodeLimit) {
|
||||||
|
uint32_t data = (*index) << TagShift | uint32_t(*tag);
|
||||||
|
return xdr->codeUint32(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t data = TwoUnitPattern | uint32_t(*tag);
|
||||||
|
MOZ_TRY(xdr->codeUint32(&data));
|
||||||
|
return xdr->codeUint32(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(mode == XDR_DECODE);
|
||||||
|
|
||||||
|
uint32_t data;
|
||||||
|
MOZ_TRY(xdr->codeUint32(&data));
|
||||||
|
|
||||||
|
*tag = ParserAtomTag(data & TagMask);
|
||||||
|
|
||||||
|
if ((data & TwoUnitPattern) == TwoUnitPattern) {
|
||||||
|
MOZ_TRY(xdr->codeUint32(index));
|
||||||
|
} else {
|
||||||
|
*index = data >> TagShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <XDRMode mode>
|
template <XDRMode mode>
|
||||||
|
@ -733,49 +810,86 @@ XDRResult XDRParserAtomData(XDRState<mode>* xdr, const ParserAtom** atomp) {
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template XDRResult XDRParserAtomData(XDRState<XDR_ENCODE>* xdr,
|
||||||
|
const ParserAtom** atomp);
|
||||||
|
template XDRResult XDRParserAtomData(XDRState<XDR_DECODE>* xdr,
|
||||||
|
const ParserAtom** atomp);
|
||||||
|
|
||||||
template <XDRMode mode>
|
template <XDRMode mode>
|
||||||
XDRResult XDRParserAtom(XDRState<mode>* xdr, const ParserAtom** atomp) {
|
XDRResult XDRParserAtom(XDRState<mode>* xdr, const ParserAtom** atomp) {
|
||||||
// If dedup tables aren't enabled for this XDR encoding, encode/decode
|
|
||||||
// the parser atoms inline.
|
|
||||||
if (!xdr->hasAtomMap() && !xdr->hasAtomTable()) {
|
|
||||||
return XDRParserAtomData(xdr, atomp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == XDR_ENCODE) {
|
if (mode == XDR_ENCODE) {
|
||||||
MOZ_ASSERT(xdr->hasAtomMap());
|
MOZ_ASSERT(xdr->hasAtomMap());
|
||||||
|
|
||||||
// Atom contents are encoded in a separate buffer, which is joined to the
|
|
||||||
// final result in XDRIncrementalEncoder::linearize. References to atoms
|
|
||||||
// are encoded as indices into the atom stream.
|
|
||||||
uint32_t atomIndex;
|
uint32_t atomIndex;
|
||||||
XDRParserAtomMap::AddPtr p = xdr->parserAtomMap().lookupForAdd(*atomp);
|
ParserAtomTag tag = ParserAtomTag::Normal;
|
||||||
if (p) {
|
if ((*atomp)->isWellKnownAtomId()) {
|
||||||
atomIndex = p->value();
|
atomIndex = uint32_t((*atomp)->toWellKnownAtomId());
|
||||||
|
tag = ParserAtomTag::WellKnown;
|
||||||
|
} else if ((*atomp)->isStaticParserString1()) {
|
||||||
|
atomIndex = uint32_t((*atomp)->toStaticParserString1());
|
||||||
|
tag = ParserAtomTag::Static1;
|
||||||
|
} else if ((*atomp)->isStaticParserString2()) {
|
||||||
|
atomIndex = uint32_t((*atomp)->toStaticParserString2());
|
||||||
|
tag = ParserAtomTag::Static2;
|
||||||
} else {
|
} else {
|
||||||
xdr->switchToAtomBuf();
|
// Either AtomIndexKind::Unresolved or AtomIndexKind::AtomIndex.
|
||||||
MOZ_TRY(XDRParserAtomData(xdr, atomp));
|
|
||||||
xdr->switchToMainBuf();
|
|
||||||
|
|
||||||
atomIndex = xdr->natoms();
|
// Atom contents are encoded in a separate buffer, which is joined to the
|
||||||
xdr->natoms() += 1;
|
// final result in XDRIncrementalEncoder::linearize. References to atoms
|
||||||
if (!xdr->parserAtomMap().add(p, *atomp, atomIndex)) {
|
// are encoded as indices into the atom stream.
|
||||||
return xdr->fail(JS::TranscodeResult_Throw);
|
XDRParserAtomMap::AddPtr p = xdr->parserAtomMap().lookupForAdd(*atomp);
|
||||||
|
if (p) {
|
||||||
|
atomIndex = p->value();
|
||||||
|
} else {
|
||||||
|
xdr->switchToAtomBuf();
|
||||||
|
MOZ_TRY(XDRParserAtomData(xdr, atomp));
|
||||||
|
xdr->switchToMainBuf();
|
||||||
|
|
||||||
|
atomIndex = xdr->natoms();
|
||||||
|
xdr->natoms() += 1;
|
||||||
|
if (!xdr->parserAtomMap().add(p, *atomp, atomIndex)) {
|
||||||
|
return xdr->fail(JS::TranscodeResult_Throw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
tag = ParserAtomTag::Normal;
|
||||||
}
|
}
|
||||||
MOZ_TRY(XDRParserAtomIndex(xdr, &atomIndex));
|
MOZ_TRY(XDRParserAtomTaggedIndex(xdr, &tag, &atomIndex));
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(mode == XDR_DECODE && xdr->hasAtomTable());
|
MOZ_ASSERT(mode == XDR_DECODE && xdr->hasAtomTable());
|
||||||
|
|
||||||
uint32_t atomIndex;
|
uint32_t atomIndex = 0;
|
||||||
MOZ_TRY(XDRParserAtomIndex(xdr, &atomIndex));
|
ParserAtomTag tag = ParserAtomTag::Normal;
|
||||||
if (atomIndex >= xdr->parserAtomTable().length()) {
|
MOZ_TRY(XDRParserAtomTaggedIndex(xdr, &tag, &atomIndex));
|
||||||
return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
|
|
||||||
}
|
switch (tag) {
|
||||||
const ParserAtom* atom = xdr->parserAtomTable()[atomIndex];
|
case ParserAtomTag::Normal:
|
||||||
|
if (atomIndex >= xdr->parserAtomTable().length()) {
|
||||||
|
return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
|
||||||
|
}
|
||||||
|
*atomp = xdr->parserAtomTable()[atomIndex];
|
||||||
|
break;
|
||||||
|
case ParserAtomTag::WellKnown:
|
||||||
|
if (atomIndex >= uint32_t(WellKnownAtomId::Limit)) {
|
||||||
|
return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
|
||||||
|
}
|
||||||
|
*atomp = xdr->frontendAtoms().getWellKnown(WellKnownAtomId(atomIndex));
|
||||||
|
break;
|
||||||
|
case ParserAtomTag::Static1:
|
||||||
|
if (atomIndex >= WellKnownParserAtoms_ROM::ASCII_STATIC_LIMIT) {
|
||||||
|
return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
|
||||||
|
}
|
||||||
|
*atomp = xdr->frontendAtoms().getStatic1(StaticParserString1(atomIndex));
|
||||||
|
break;
|
||||||
|
case ParserAtomTag::Static2:
|
||||||
|
if (atomIndex >= WellKnownParserAtoms_ROM::NUM_LENGTH2_ENTRIES) {
|
||||||
|
return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
|
||||||
|
}
|
||||||
|
*atomp = xdr->frontendAtoms().getStatic2(StaticParserString2(atomIndex));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
*atomp = atom;
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ enum class WellKnownAtomId : uint32_t {
|
||||||
#define ENUM_ENTRY_(name, clasp) name,
|
#define ENUM_ENTRY_(name, clasp) name,
|
||||||
JS_FOR_EACH_PROTOTYPE(ENUM_ENTRY_)
|
JS_FOR_EACH_PROTOTYPE(ENUM_ENTRY_)
|
||||||
#undef ENUM_ENTRY_
|
#undef ENUM_ENTRY_
|
||||||
|
Limit,
|
||||||
};
|
};
|
||||||
|
|
||||||
// These types correspond into indices in the StaticStrings arrays.
|
// These types correspond into indices in the StaticStrings arrays.
|
||||||
|
@ -183,13 +184,36 @@ 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;
|
||||||
|
|
||||||
|
WellKnownAtomId toWellKnownAtomId() const {
|
||||||
|
MOZ_ASSERT(isWellKnownAtomId());
|
||||||
|
return WellKnownAtomId(atomIndex_);
|
||||||
|
}
|
||||||
|
StaticParserString1 toStaticParserString1() const {
|
||||||
|
MOZ_ASSERT(isStaticParserString1());
|
||||||
|
return StaticParserString1(atomIndex_);
|
||||||
|
}
|
||||||
|
StaticParserString2 toStaticParserString2() const {
|
||||||
|
MOZ_ASSERT(isStaticParserString2());
|
||||||
|
return StaticParserString2(atomIndex_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isWellKnownAtomId() const {
|
||||||
|
return atomIndexKind_ == AtomIndexKind::WellKnown;
|
||||||
|
}
|
||||||
|
bool isStaticParserString1() const {
|
||||||
|
return atomIndexKind_ == AtomIndexKind::Static1;
|
||||||
|
}
|
||||||
|
bool isStaticParserString2() const {
|
||||||
|
return atomIndexKind_ == AtomIndexKind::Static2;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setAtomIndex(AtomIndex index) {
|
void setAtomIndex(AtomIndex index) {
|
||||||
atomIndex_ = index;
|
atomIndex_ = index;
|
||||||
atomIndexKind_ = AtomIndexKind::AtomIndex;
|
atomIndexKind_ = AtomIndexKind::AtomIndex;
|
||||||
}
|
}
|
||||||
constexpr void setWellKnownAtomId(WellKnownAtomId kind) {
|
constexpr void setWellKnownAtomId(WellKnownAtomId atomId) {
|
||||||
atomIndex_ = static_cast<uint32_t>(kind);
|
atomIndex_ = static_cast<uint32_t>(atomId);
|
||||||
atomIndexKind_ = AtomIndexKind::WellKnown;
|
atomIndexKind_ = AtomIndexKind::WellKnown;
|
||||||
}
|
}
|
||||||
constexpr void setStaticParserString1(StaticParserString1 s) {
|
constexpr void setStaticParserString1(StaticParserString1 s) {
|
||||||
|
@ -414,7 +438,7 @@ class WellKnownParserAtoms {
|
||||||
bool initTinyStringAlias(JSContext* cx, const ParserName** name,
|
bool initTinyStringAlias(JSContext* cx, const ParserName** name,
|
||||||
const char* str);
|
const char* str);
|
||||||
bool initSingle(JSContext* cx, const ParserName** name, const char* str,
|
bool initSingle(JSContext* cx, const ParserName** name, const char* str,
|
||||||
WellKnownAtomId kind);
|
WellKnownAtomId atomId);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WellKnownParserAtoms() = default;
|
WellKnownParserAtoms() = default;
|
||||||
|
@ -489,6 +513,10 @@ class ParserAtomsTable {
|
||||||
|
|
||||||
JS::Result<const ParserAtom*, OOM> concatAtoms(
|
JS::Result<const ParserAtom*, OOM> concatAtoms(
|
||||||
JSContext* cx, mozilla::Range<const ParserAtom*> atoms);
|
JSContext* cx, mozilla::Range<const ParserAtom*> atoms);
|
||||||
|
|
||||||
|
const ParserAtom* getWellKnown(WellKnownAtomId atomId) const;
|
||||||
|
const ParserAtom* getStatic1(StaticParserString1 s) const;
|
||||||
|
const ParserAtom* getStatic2(StaticParserString2 s) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "builtin/ModuleObject.h"
|
#include "builtin/ModuleObject.h"
|
||||||
#include "debugger/DebugAPI.h"
|
#include "debugger/DebugAPI.h"
|
||||||
#include "frontend/CompilationInfo.h" // frontend::CompilationStencil, frontend::CompilationInfo, frontend::CompilationInfoVector
|
#include "frontend/CompilationInfo.h" // frontend::CompilationStencil, frontend::CompilationInfo, frontend::CompilationInfoVector
|
||||||
#include "frontend/ParserAtom.h" // XDRParserAtom
|
#include "frontend/ParserAtom.h" // XDRParserAtomData
|
||||||
#include "js/BuildId.h" // JS::BuildIdCharVector
|
#include "js/BuildId.h" // JS::BuildIdCharVector
|
||||||
#include "vm/JSContext.h"
|
#include "vm/JSContext.h"
|
||||||
#include "vm/JSScript.h"
|
#include "vm/JSScript.h"
|
||||||
|
@ -318,7 +318,7 @@ static XDRResult ParserAtomTable(XDRState<mode>* xdr) {
|
||||||
|
|
||||||
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(XDRParserAtom(xdr, &atom));
|
MOZ_TRY(XDRParserAtomData(xdr, &atom));
|
||||||
if (!xdr->parserAtomTable().append(atom)) {
|
if (!xdr->parserAtomTable().append(atom)) {
|
||||||
ReportOutOfMemory(xdr->cx());
|
ReportOutOfMemory(xdr->cx());
|
||||||
return xdr->fail(JS::TranscodeResult_Throw);
|
return xdr->fail(JS::TranscodeResult_Throw);
|
||||||
|
|
|
@ -781,6 +781,10 @@ template <XDRMode mode>
|
||||||
XDRResult XDRParserAtom(XDRState<mode>* xdr,
|
XDRResult XDRParserAtom(XDRState<mode>* xdr,
|
||||||
const frontend::ParserAtom** atomp);
|
const frontend::ParserAtom** atomp);
|
||||||
|
|
||||||
|
template <XDRMode mode>
|
||||||
|
XDRResult XDRParserAtomData(XDRState<mode>* xdr,
|
||||||
|
const frontend::ParserAtom** atomp);
|
||||||
|
|
||||||
template <XDRMode mode>
|
template <XDRMode mode>
|
||||||
XDRResult XDRParserAtomOrNull(XDRState<mode>* xdr,
|
XDRResult XDRParserAtomOrNull(XDRState<mode>* xdr,
|
||||||
const frontend::ParserAtom** atomp);
|
const frontend::ParserAtom** atomp);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче