mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-07 09:54:42 +00:00
Bug 1533636 - Don't bother explicitly aligning when XDRing char16_t data: the operations we use to perform the little/native-endian conversion will correctly translate into, or translate out of, unaligned memory. r=tcampbell
Differential Revision: https://phabricator.services.mozilla.com/D22654 --HG-- extra : rebase_source : 2013431c35fff24bb003671dc257005903ff3c07
This commit is contained in:
parent
6004ce1971
commit
b299df2f1a
@ -11,6 +11,8 @@
|
|||||||
#ifndef vm_AtomsTable_h
|
#ifndef vm_AtomsTable_h
|
||||||
#define vm_AtomsTable_h
|
#define vm_AtomsTable_h
|
||||||
|
|
||||||
|
#include <type_traits> // std::{enable_if,is_const}
|
||||||
|
|
||||||
#include "js/GCHashTable.h"
|
#include "js/GCHashTable.h"
|
||||||
#include "js/TypeDecls.h"
|
#include "js/TypeDecls.h"
|
||||||
#include "vm/JSAtom.h"
|
#include "vm/JSAtom.h"
|
||||||
@ -162,12 +164,22 @@ class AtomsTable {
|
|||||||
~AtomsTable();
|
~AtomsTable();
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename Chars>
|
||||||
MOZ_ALWAYS_INLINE JSAtom* atomizeAndCopyChars(
|
MOZ_ALWAYS_INLINE JSAtom* atomizeAndCopyChars(
|
||||||
JSContext* cx, const CharT* tbchars, size_t length, PinningBehavior pin,
|
JSContext* cx, Chars chars, size_t length, PinningBehavior pin,
|
||||||
const mozilla::Maybe<uint32_t>& indexValue,
|
const mozilla::Maybe<uint32_t>& indexValue,
|
||||||
const AtomHasher::Lookup& lookup);
|
const AtomHasher::Lookup& lookup);
|
||||||
|
|
||||||
|
template <typename CharT, typename = typename std::enable_if<
|
||||||
|
!std::is_const<CharT>::value>::type>
|
||||||
|
MOZ_ALWAYS_INLINE JSAtom* atomizeAndCopyChars(
|
||||||
|
JSContext* cx, CharT* chars, size_t length, PinningBehavior pin,
|
||||||
|
const mozilla::Maybe<uint32_t>& indexValue,
|
||||||
|
const AtomHasher::Lookup& lookup) {
|
||||||
|
return atomizeAndCopyChars(cx, const_cast<const CharT*>(chars), length, pin,
|
||||||
|
indexValue, lookup);
|
||||||
|
}
|
||||||
|
|
||||||
void pinExistingAtom(JSContext* cx, JSAtom* atom);
|
void pinExistingAtom(JSContext* cx, JSAtom* atom);
|
||||||
|
|
||||||
void tracePinnedAtoms(JSTracer* trc, const AutoAccessAtomsZone& access);
|
void tracePinnedAtoms(JSTracer* trc, const AutoAccessAtomsZone& access);
|
||||||
|
@ -60,9 +60,10 @@ struct js::AtomHasher::Lookup {
|
|||||||
union {
|
union {
|
||||||
const JS::Latin1Char* latin1Chars;
|
const JS::Latin1Char* latin1Chars;
|
||||||
const char16_t* twoByteChars;
|
const char16_t* twoByteChars;
|
||||||
|
LittleEndianChars littleEndianChars;
|
||||||
const char* utf8Bytes;
|
const char* utf8Bytes;
|
||||||
};
|
};
|
||||||
enum { TwoByteChar, Latin1, UTF8, WTF8 } type;
|
enum { TwoByteChar, LittleEndianTwoByte, Latin1, UTF8, WTF8 } type;
|
||||||
size_t length;
|
size_t length;
|
||||||
size_t byteLength;
|
size_t byteLength;
|
||||||
const JSAtom* atom; /* Optional. */
|
const JSAtom* atom; /* Optional. */
|
||||||
@ -107,6 +108,13 @@ struct js::AtomHasher::Lookup {
|
|||||||
MOZ_ASSERT(mozilla::HashString(twoByteChars, length) == hash);
|
MOZ_ASSERT(mozilla::HashString(twoByteChars, length) == hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ALWAYS_INLINE Lookup(LittleEndianChars chars, size_t length)
|
||||||
|
: littleEndianChars(chars),
|
||||||
|
type(LittleEndianTwoByte),
|
||||||
|
length(length),
|
||||||
|
atom(nullptr),
|
||||||
|
hash(mozilla::HashStringKnownLength(chars, length)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline HashNumber js::AtomHasher::hash(const Lookup& l) { return l.hash; }
|
inline HashNumber js::AtomHasher::hash(const Lookup& l) { return l.hash; }
|
||||||
@ -121,6 +129,15 @@ MOZ_ALWAYS_INLINE bool js::AtomHasher::match(const AtomStateEntry& entry,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto EqualsLittleEndianChars = [&lookup](auto keyChars) {
|
||||||
|
for (size_t i = 0, len = lookup.length; i < len; i++) {
|
||||||
|
if (keyChars[i] != lookup.littleEndianChars[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
if (key->hasLatin1Chars()) {
|
if (key->hasLatin1Chars()) {
|
||||||
const Latin1Char* keyChars = key->latin1Chars(lookup.nogc);
|
const Latin1Char* keyChars = key->latin1Chars(lookup.nogc);
|
||||||
switch (lookup.type) {
|
switch (lookup.type) {
|
||||||
@ -128,6 +145,8 @@ MOZ_ALWAYS_INLINE bool js::AtomHasher::match(const AtomStateEntry& entry,
|
|||||||
return mozilla::ArrayEqual(keyChars, lookup.latin1Chars, lookup.length);
|
return mozilla::ArrayEqual(keyChars, lookup.latin1Chars, lookup.length);
|
||||||
case Lookup::TwoByteChar:
|
case Lookup::TwoByteChar:
|
||||||
return EqualChars(keyChars, lookup.twoByteChars, lookup.length);
|
return EqualChars(keyChars, lookup.twoByteChars, lookup.length);
|
||||||
|
case Lookup::LittleEndianTwoByte:
|
||||||
|
return EqualsLittleEndianChars(keyChars);
|
||||||
case Lookup::UTF8: {
|
case Lookup::UTF8: {
|
||||||
JS::UTF8Chars utf8(lookup.utf8Bytes, lookup.byteLength);
|
JS::UTF8Chars utf8(lookup.utf8Bytes, lookup.byteLength);
|
||||||
return UTF8OrWTF8EqualsChars(utf8, keyChars);
|
return UTF8OrWTF8EqualsChars(utf8, keyChars);
|
||||||
@ -145,6 +164,8 @@ MOZ_ALWAYS_INLINE bool js::AtomHasher::match(const AtomStateEntry& entry,
|
|||||||
return EqualChars(lookup.latin1Chars, keyChars, lookup.length);
|
return EqualChars(lookup.latin1Chars, keyChars, lookup.length);
|
||||||
case Lookup::TwoByteChar:
|
case Lookup::TwoByteChar:
|
||||||
return mozilla::ArrayEqual(keyChars, lookup.twoByteChars, lookup.length);
|
return mozilla::ArrayEqual(keyChars, lookup.twoByteChars, lookup.length);
|
||||||
|
case Lookup::LittleEndianTwoByte:
|
||||||
|
return EqualsLittleEndianChars(keyChars);
|
||||||
case Lookup::UTF8: {
|
case Lookup::UTF8: {
|
||||||
JS::UTF8Chars utf8(lookup.utf8Bytes, lookup.byteLength);
|
JS::UTF8Chars utf8(lookup.utf8Bytes, lookup.byteLength);
|
||||||
return UTF8OrWTF8EqualsChars(utf8, keyChars);
|
return UTF8OrWTF8EqualsChars(utf8, keyChars);
|
||||||
@ -607,42 +628,39 @@ bool JSRuntime::initMainAtomsTables(JSContext* cx) {
|
|||||||
return atoms_ && atoms_->init();
|
return atoms_ && atoms_->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename Chars>
|
||||||
MOZ_NEVER_INLINE static JSAtom* PermanentlyAtomizeAndCopyChars(
|
static MOZ_ALWAYS_INLINE JSAtom* AtomizeAndCopyCharsFromLookup(
|
||||||
JSContext* cx, Maybe<AtomSet::AddPtr>& zonePtr, const CharT* tbchars,
|
JSContext* cx, Chars chars, size_t length, const AtomHasher::Lookup& lookup,
|
||||||
size_t length, const Maybe<uint32_t>& indexValue,
|
PinningBehavior pin, const Maybe<uint32_t>& indexValue);
|
||||||
const AtomHasher::Lookup& lookup);
|
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename CharT, typename = typename std::enable_if<
|
||||||
MOZ_ALWAYS_INLINE static JSAtom* AllocateNewAtom(
|
!std::is_const<CharT>::value>::type>
|
||||||
JSContext* cx, const CharT* tbchars, size_t length, PinningBehavior pin,
|
static MOZ_ALWAYS_INLINE JSAtom* AtomizeAndCopyCharsFromLookup(
|
||||||
const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup);
|
JSContext* cx, CharT* chars, size_t length,
|
||||||
|
|
||||||
template <typename CharT>
|
|
||||||
MOZ_ALWAYS_INLINE static JSAtom* AtomizeAndCopyCharsFromLookup(
|
|
||||||
JSContext* cx, const CharT* tbchars, size_t length,
|
|
||||||
const AtomHasher::Lookup& lookup, PinningBehavior pin,
|
const AtomHasher::Lookup& lookup, PinningBehavior pin,
|
||||||
const Maybe<uint32_t>& indexValue);
|
|
||||||
|
|
||||||
/* |tbchars| must not point into an inline or short string. */
|
|
||||||
template <typename CharT>
|
|
||||||
MOZ_ALWAYS_INLINE static JSAtom* AtomizeAndCopyChars(
|
|
||||||
JSContext* cx, const CharT* tbchars, size_t length, PinningBehavior pin,
|
|
||||||
const Maybe<uint32_t>& indexValue) {
|
const Maybe<uint32_t>& indexValue) {
|
||||||
if (JSAtom* s = cx->staticStrings().lookup(tbchars, length)) {
|
return AtomizeAndCopyCharsFromLookup(cx, const_cast<const CharT*>(chars),
|
||||||
return s;
|
length, lookup, pin, indexValue);
|
||||||
}
|
|
||||||
|
|
||||||
AtomHasher::Lookup lookup(tbchars, length);
|
|
||||||
return AtomizeAndCopyCharsFromLookup(cx, tbchars, length, lookup, pin,
|
|
||||||
indexValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename Chars>
|
||||||
MOZ_ALWAYS_INLINE static JSAtom* AtomizeAndCopyCharsFromLookup(
|
static MOZ_NEVER_INLINE JSAtom* PermanentlyAtomizeAndCopyChars(
|
||||||
JSContext* cx, const CharT* tbchars, size_t length,
|
JSContext* cx, Maybe<AtomSet::AddPtr>& zonePtr, Chars chars, size_t length,
|
||||||
const AtomHasher::Lookup& lookup, PinningBehavior pin,
|
const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup);
|
||||||
const Maybe<uint32_t>& indexValue) {
|
|
||||||
|
template <typename CharT, typename = typename std::enable_if<
|
||||||
|
!std::is_const<CharT>::value>::type>
|
||||||
|
static JSAtom* PermanentlyAtomizeAndCopyChars(
|
||||||
|
JSContext* cx, Maybe<AtomSet::AddPtr>& zonePtr, CharT* chars, size_t length,
|
||||||
|
const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup) {
|
||||||
|
return PermanentlyAtomizeAndCopyChars(
|
||||||
|
cx, zonePtr, const_cast<const CharT*>(chars), length, indexValue, lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Chars>
|
||||||
|
static MOZ_ALWAYS_INLINE JSAtom* AtomizeAndCopyCharsFromLookup(
|
||||||
|
JSContext* cx, Chars chars, size_t length, const AtomHasher::Lookup& lookup,
|
||||||
|
PinningBehavior pin, const Maybe<uint32_t>& indexValue) {
|
||||||
// Try the per-Zone cache first. If we find the atom there we can avoid the
|
// Try the per-Zone cache first. If we find the atom there we can avoid the
|
||||||
// atoms lock, the markAtom call, and the multiple HashSet lookups below.
|
// atoms lock, the markAtom call, and the multiple HashSet lookups below.
|
||||||
// We don't use the per-Zone cache if we want a pinned atom: handling that
|
// We don't use the per-Zone cache if we want a pinned atom: handling that
|
||||||
@ -665,7 +683,7 @@ MOZ_ALWAYS_INLINE static JSAtom* AtomizeAndCopyCharsFromLookup(
|
|||||||
// atoms table is being created. In this case all atoms created are added to
|
// atoms table is being created. In this case all atoms created are added to
|
||||||
// the permanent atoms table.
|
// the permanent atoms table.
|
||||||
if (!cx->permanentAtomsPopulated()) {
|
if (!cx->permanentAtomsPopulated()) {
|
||||||
return PermanentlyAtomizeAndCopyChars(cx, zonePtr, tbchars, length,
|
return PermanentlyAtomizeAndCopyChars(cx, zonePtr, chars, length,
|
||||||
indexValue, lookup);
|
indexValue, lookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,7 +705,7 @@ MOZ_ALWAYS_INLINE static JSAtom* AtomizeAndCopyCharsFromLookup(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSAtom* atom = cx->atoms().atomizeAndCopyChars(cx, tbchars, length, pin,
|
JSAtom* atom = cx->atoms().atomizeAndCopyChars(cx, chars, length, pin,
|
||||||
indexValue, lookup);
|
indexValue, lookup);
|
||||||
if (!atom) {
|
if (!atom) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -707,9 +725,23 @@ MOZ_ALWAYS_INLINE static JSAtom* AtomizeAndCopyCharsFromLookup(
|
|||||||
return atom;
|
return atom;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename Chars>
|
||||||
|
static MOZ_ALWAYS_INLINE JSAtom* AllocateNewAtom(
|
||||||
|
JSContext* cx, Chars chars, size_t length, PinningBehavior pin,
|
||||||
|
const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup);
|
||||||
|
|
||||||
|
template <typename CharT, typename = typename std::enable_if<
|
||||||
|
!std::is_const<CharT>::value>::type>
|
||||||
|
static MOZ_ALWAYS_INLINE JSAtom* AllocateNewAtom(
|
||||||
|
JSContext* cx, CharT* chars, size_t length, PinningBehavior pin,
|
||||||
|
const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup) {
|
||||||
|
return AllocateNewAtom(cx, const_cast<const CharT*>(chars), length, pin,
|
||||||
|
indexValue, lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Chars>
|
||||||
MOZ_ALWAYS_INLINE JSAtom* AtomsTable::atomizeAndCopyChars(
|
MOZ_ALWAYS_INLINE JSAtom* AtomsTable::atomizeAndCopyChars(
|
||||||
JSContext* cx, const CharT* tbchars, size_t length, PinningBehavior pin,
|
JSContext* cx, Chars chars, size_t length, PinningBehavior pin,
|
||||||
const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup) {
|
const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup) {
|
||||||
Partition& part = *partitions[getPartitionIndex(lookup)];
|
Partition& part = *partitions[getPartitionIndex(lookup)];
|
||||||
AutoLock lock(cx->runtime(), part.lock);
|
AutoLock lock(cx->runtime(), part.lock);
|
||||||
@ -746,7 +778,7 @@ MOZ_ALWAYS_INLINE JSAtom* AtomsTable::atomizeAndCopyChars(
|
|||||||
return atom;
|
return atom;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSAtom* atom = AllocateNewAtom(cx, tbchars, length, pin, indexValue, lookup);
|
JSAtom* atom = AllocateNewAtom(cx, chars, length, pin, indexValue, lookup);
|
||||||
if (!atom) {
|
if (!atom) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -764,19 +796,24 @@ MOZ_ALWAYS_INLINE JSAtom* AtomsTable::atomizeAndCopyChars(
|
|||||||
return atom;
|
return atom;
|
||||||
}
|
}
|
||||||
|
|
||||||
template JSAtom* AtomizeAndCopyChars(JSContext* cx, const char16_t* tbchars,
|
/* |chars| must not point into an inline or short string. */
|
||||||
size_t length, PinningBehavior pin,
|
|
||||||
const Maybe<uint32_t>& indexValue);
|
|
||||||
|
|
||||||
template JSAtom* AtomizeAndCopyChars(JSContext* cx, const Latin1Char* tbchars,
|
|
||||||
size_t length, PinningBehavior pin,
|
|
||||||
const Maybe<uint32_t>& indexValue);
|
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
MOZ_NEVER_INLINE static JSAtom* PermanentlyAtomizeAndCopyChars(
|
static MOZ_ALWAYS_INLINE JSAtom* AtomizeAndCopyChars(
|
||||||
JSContext* cx, Maybe<AtomSet::AddPtr>& zonePtr, const CharT* tbchars,
|
JSContext* cx, const CharT* chars, size_t length, PinningBehavior pin,
|
||||||
size_t length, const Maybe<uint32_t>& indexValue,
|
const Maybe<uint32_t>& indexValue) {
|
||||||
const AtomHasher::Lookup& lookup) {
|
if (JSAtom* s = cx->staticStrings().lookup(chars, length)) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
AtomHasher::Lookup lookup(chars, length);
|
||||||
|
return AtomizeAndCopyCharsFromLookup(cx, chars, length, lookup, pin,
|
||||||
|
indexValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Chars>
|
||||||
|
static MOZ_NEVER_INLINE JSAtom* PermanentlyAtomizeAndCopyChars(
|
||||||
|
JSContext* cx, Maybe<AtomSet::AddPtr>& zonePtr, Chars chars, size_t length,
|
||||||
|
const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup) {
|
||||||
MOZ_ASSERT(!cx->permanentAtomsPopulated());
|
MOZ_ASSERT(!cx->permanentAtomsPopulated());
|
||||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||||
|
|
||||||
@ -788,7 +825,7 @@ MOZ_NEVER_INLINE static JSAtom* PermanentlyAtomizeAndCopyChars(
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSAtom* atom =
|
JSAtom* atom =
|
||||||
AllocateNewAtom(cx, tbchars, length, DoNotPinAtom, indexValue, lookup);
|
AllocateNewAtom(cx, chars, length, DoNotPinAtom, indexValue, lookup);
|
||||||
if (!atom) {
|
if (!atom) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -825,13 +862,20 @@ struct AtomizeUTF8OrWTF8CharsWrapper {
|
|||||||
// MakeFlatStringForAtomization has 4 variants.
|
// MakeFlatStringForAtomization has 4 variants.
|
||||||
// This is used by Latin1Char and char16_t.
|
// This is used by Latin1Char and char16_t.
|
||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
MOZ_ALWAYS_INLINE static JSFlatString* MakeFlatStringForAtomization(
|
static MOZ_ALWAYS_INLINE JSFlatString* MakeFlatStringForAtomization(
|
||||||
JSContext* cx, const CharT* tbchars, size_t length) {
|
JSContext* cx, const CharT* chars, size_t length) {
|
||||||
return NewStringCopyN<NoGC>(cx, tbchars, length);
|
return NewStringCopyN<NoGC>(cx, chars, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeFlatStringForAtomization has one further variant -- a non-template
|
||||||
|
// overload accepting LittleEndianChars.
|
||||||
|
static MOZ_ALWAYS_INLINE JSFlatString* MakeFlatStringForAtomization(
|
||||||
|
JSContext* cx, LittleEndianChars chars, size_t length) {
|
||||||
|
return NewStringFromLittleEndianNoGC(cx, chars, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename CharT, typename WrapperT>
|
template <typename CharT, typename WrapperT>
|
||||||
MOZ_ALWAYS_INLINE static JSFlatString* MakeUTF8AtomHelper(JSContext* cx,
|
static MOZ_ALWAYS_INLINE JSFlatString* MakeUTF8AtomHelper(JSContext* cx,
|
||||||
const WrapperT* chars,
|
const WrapperT* chars,
|
||||||
size_t length) {
|
size_t length) {
|
||||||
if (JSInlineString::lengthFits<CharT>(length)) {
|
if (JSInlineString::lengthFits<CharT>(length)) {
|
||||||
@ -870,11 +914,9 @@ MOZ_ALWAYS_INLINE static JSFlatString* MakeUTF8AtomHelper(JSContext* cx,
|
|||||||
// Another 2 variants of MakeFlatStringForAtomization.
|
// Another 2 variants of MakeFlatStringForAtomization.
|
||||||
// This is used by AtomizeUTF8OrWTF8CharsWrapper with UTF8Chars or WTF8Chars.
|
// This is used by AtomizeUTF8OrWTF8CharsWrapper with UTF8Chars or WTF8Chars.
|
||||||
template <typename InputCharsT>
|
template <typename InputCharsT>
|
||||||
MOZ_ALWAYS_INLINE
|
/* static */ MOZ_ALWAYS_INLINE JSFlatString* MakeFlatStringForAtomization(
|
||||||
/* static */ JSFlatString*
|
JSContext* cx, const AtomizeUTF8OrWTF8CharsWrapper<InputCharsT>* chars,
|
||||||
MakeFlatStringForAtomization(
|
size_t length) {
|
||||||
JSContext* cx, const AtomizeUTF8OrWTF8CharsWrapper<InputCharsT>* chars,
|
|
||||||
size_t length) {
|
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
return cx->emptyString();
|
return cx->emptyString();
|
||||||
}
|
}
|
||||||
@ -885,13 +927,13 @@ MOZ_ALWAYS_INLINE
|
|||||||
return MakeUTF8AtomHelper<JS::Latin1Char>(cx, chars, length);
|
return MakeUTF8AtomHelper<JS::Latin1Char>(cx, chars, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename Chars>
|
||||||
MOZ_ALWAYS_INLINE static JSAtom* AllocateNewAtom(
|
static MOZ_ALWAYS_INLINE JSAtom* AllocateNewAtom(
|
||||||
JSContext* cx, const CharT* tbchars, size_t length, PinningBehavior pin,
|
JSContext* cx, Chars chars, size_t length, PinningBehavior pin,
|
||||||
const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup) {
|
const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup) {
|
||||||
AutoAllocInAtomsZone ac(cx);
|
AutoAllocInAtomsZone ac(cx);
|
||||||
|
|
||||||
JSFlatString* flat = MakeFlatStringForAtomization(cx, tbchars, length);
|
JSFlatString* flat = MakeFlatStringForAtomization(cx, chars, length);
|
||||||
if (!flat) {
|
if (!flat) {
|
||||||
// Grudgingly forgo last-ditch GC. The alternative would be to release
|
// Grudgingly forgo last-ditch GC. The alternative would be to release
|
||||||
// the lock, manually GC here, and retry from the top. If you fix this,
|
// the lock, manually GC here, and retry from the top. If you fix this,
|
||||||
@ -1126,6 +1168,22 @@ template JSAtom* js::ToAtom<CanGC>(JSContext* cx, HandleValue v);
|
|||||||
|
|
||||||
template JSAtom* js::ToAtom<NoGC>(JSContext* cx, const Value& v);
|
template JSAtom* js::ToAtom<NoGC>(JSContext* cx, const Value& v);
|
||||||
|
|
||||||
|
static JSAtom* AtomizeLittleEndianTwoByteChars(JSContext* cx,
|
||||||
|
const uint8_t* leTwoByte,
|
||||||
|
size_t length) {
|
||||||
|
CHECK_THREAD(cx);
|
||||||
|
|
||||||
|
LittleEndianChars chars(leTwoByte);
|
||||||
|
|
||||||
|
if (JSAtom* s = cx->staticStrings().lookup(chars, length)) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
AtomHasher::Lookup lookup(chars, length);
|
||||||
|
return AtomizeAndCopyCharsFromLookup(cx, chars, length, lookup, DoNotPinAtom,
|
||||||
|
Nothing());
|
||||||
|
}
|
||||||
|
|
||||||
template <XDRMode mode>
|
template <XDRMode mode>
|
||||||
XDRResult js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp) {
|
XDRResult js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp) {
|
||||||
bool latin1 = false;
|
bool latin1 = false;
|
||||||
@ -1170,51 +1228,13 @@ XDRResult js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp) {
|
|||||||
}
|
}
|
||||||
atom = AtomizeChars(cx, chars, length);
|
atom = AtomizeChars(cx, chars, length);
|
||||||
} else {
|
} else {
|
||||||
#if MOZ_LITTLE_ENDIAN
|
const uint8_t* twoByteCharsLE = nullptr;
|
||||||
/* Directly access the little endian chars in the XDR buffer. */
|
|
||||||
const char16_t* chars = nullptr;
|
|
||||||
if (length) {
|
if (length) {
|
||||||
// In the |mode == XDR_ENCODE| case above, when |nchars > 0|,
|
|
||||||
// |XDRState::codeChars(char16_t*, size_t nchars)| will align the
|
|
||||||
// buffer. This code never calls that function, but it must act
|
|
||||||
// *as if* it had, so we must align manually here.
|
|
||||||
MOZ_TRY(xdr->codeAlign(sizeof(char16_t)));
|
|
||||||
|
|
||||||
const uint8_t* ptr;
|
|
||||||
size_t nbyte = length * sizeof(char16_t);
|
size_t nbyte = length * sizeof(char16_t);
|
||||||
MOZ_TRY(xdr->peekData(&ptr, nbyte));
|
MOZ_TRY(xdr->peekData(&twoByteCharsLE, nbyte));
|
||||||
MOZ_ASSERT(reinterpret_cast<uintptr_t>(ptr) % sizeof(char16_t) == 0,
|
|
||||||
"non-aligned buffer during JSAtom decoding");
|
|
||||||
chars = reinterpret_cast<const char16_t*>(ptr);
|
|
||||||
}
|
|
||||||
atom = AtomizeChars(cx, chars, length);
|
|
||||||
#else
|
|
||||||
/*
|
|
||||||
* We must copy chars to a temporary buffer to convert between little and
|
|
||||||
* big endian data.
|
|
||||||
*/
|
|
||||||
char16_t* chars;
|
|
||||||
char16_t stackChars[256];
|
|
||||||
UniqueTwoByteChars heapChars;
|
|
||||||
if (length <= ArrayLength(stackChars)) {
|
|
||||||
chars = stackChars;
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* This is very uncommon. Don't use the tempLifoAlloc arena for this as
|
|
||||||
* most allocations here will be bigger than tempLifoAlloc's default
|
|
||||||
* chunk size.
|
|
||||||
*/
|
|
||||||
heapChars.reset(cx->pod_malloc<char16_t>(length));
|
|
||||||
if (!heapChars) {
|
|
||||||
return xdr->fail(JS::TranscodeResult_Throw);
|
|
||||||
}
|
|
||||||
|
|
||||||
chars = heapChars.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_TRY(xdr->codeChars(chars, length));
|
atom = AtomizeLittleEndianTwoByteChars(cx, twoByteCharsLE, length);
|
||||||
atom = AtomizeChars(cx, chars, length);
|
|
||||||
#endif /* !MOZ_LITTLE_ENDIAN */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!atom) {
|
if (!atom) {
|
||||||
|
@ -86,9 +86,10 @@ static MOZ_ALWAYS_INLINE JSInlineString* NewInlineString(
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename Chars>
|
||||||
static MOZ_ALWAYS_INLINE JSFlatString* TryEmptyOrStaticString(
|
static MOZ_ALWAYS_INLINE JSFlatString* TryEmptyOrStaticString(JSContext* cx,
|
||||||
JSContext* cx, const CharT* chars, size_t n) {
|
Chars chars,
|
||||||
|
size_t n) {
|
||||||
// Measurements on popular websites indicate empty strings are pretty common
|
// Measurements on popular websites indicate empty strings are pretty common
|
||||||
// and most strings with length 1 or 2 are in the StaticStrings table. For
|
// and most strings with length 1 or 2 are in the StaticStrings table. For
|
||||||
// length 3 strings that's only about 1%, so we check n <= 2.
|
// length 3 strings that's only about 1%, so we check n <= 2.
|
||||||
@ -105,6 +106,14 @@ static MOZ_ALWAYS_INLINE JSFlatString* TryEmptyOrStaticString(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename CharT, typename = typename std::enable_if<
|
||||||
|
!std::is_const<CharT>::value>::type>
|
||||||
|
static MOZ_ALWAYS_INLINE JSFlatString* TryEmptyOrStaticString(JSContext* cx,
|
||||||
|
CharT* chars,
|
||||||
|
size_t n) {
|
||||||
|
return TryEmptyOrStaticString(cx, const_cast<const CharT*>(chars), n);
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE bool JSString::validateLength(JSContext* maybecx,
|
MOZ_ALWAYS_INLINE bool JSString::validateLength(JSContext* maybecx,
|
||||||
|
@ -1539,6 +1539,16 @@ static bool CanStoreCharsAsLatin1(const Latin1Char* s, size_t length) {
|
|||||||
MOZ_CRASH("Shouldn't be called for Latin1 chars");
|
MOZ_CRASH("Shouldn't be called for Latin1 chars");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool CanStoreCharsAsLatin1(LittleEndianChars chars, size_t length) {
|
||||||
|
for (size_t i = 0; i < length; i++) {
|
||||||
|
if (chars[i] > JSString::MAX_LATIN1_CHAR) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
template <AllowGC allowGC>
|
||||||
static MOZ_ALWAYS_INLINE JSInlineString* NewInlineStringDeflated(
|
static MOZ_ALWAYS_INLINE JSInlineString* NewInlineStringDeflated(
|
||||||
JSContext* cx, mozilla::Range<const char16_t> chars) {
|
JSContext* cx, mozilla::Range<const char16_t> chars) {
|
||||||
@ -1589,6 +1599,38 @@ static JSFlatString* NewStringDeflated(JSContext* cx, const Latin1Char* s,
|
|||||||
MOZ_CRASH("Shouldn't be called for Latin1 chars");
|
MOZ_CRASH("Shouldn't be called for Latin1 chars");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSFlatString* NewStringDeflatedFromLittleEndianNoGC(
|
||||||
|
JSContext* cx, LittleEndianChars chars, size_t length) {
|
||||||
|
MOZ_ASSERT(CanStoreCharsAsLatin1(chars, length));
|
||||||
|
|
||||||
|
if (JSInlineString::lengthFits<Latin1Char>(length)) {
|
||||||
|
Latin1Char* storage;
|
||||||
|
JSInlineString* str = AllocateInlineString<NoGC>(cx, length, &storage);
|
||||||
|
if (!str) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
FillFromCompatibleAndTerminate(storage, chars, length);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto news = cx->make_pod_array<Latin1Char>(length + 1);
|
||||||
|
if (!news) {
|
||||||
|
cx->recoverFromOutOfMemory();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
FillFromCompatibleAndTerminate(news.get(), chars, length);
|
||||||
|
|
||||||
|
JSFlatString* str = JSFlatString::new_<NoGC>(cx, news.get(), length);
|
||||||
|
if (!str) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::Unused << news.release();
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
JSFlatString* js::NewStringDontDeflate(JSContext* cx, CharT* chars,
|
JSFlatString* js::NewStringDontDeflate(JSContext* cx, CharT* chars,
|
||||||
size_t length) {
|
size_t length) {
|
||||||
@ -1756,6 +1798,36 @@ template JSFlatString* NewStringCopyNDontDeflate<NoGC>(JSContext* cx,
|
|||||||
const Latin1Char* s,
|
const Latin1Char* s,
|
||||||
size_t n);
|
size_t n);
|
||||||
|
|
||||||
|
static JSFlatString* NewUndeflatedStringFromLittleEndianNoGC(
|
||||||
|
JSContext* cx, LittleEndianChars chars, size_t length) {
|
||||||
|
if (JSInlineString::lengthFits<char16_t>(length)) {
|
||||||
|
char16_t* storage;
|
||||||
|
JSInlineString* str = AllocateInlineString<NoGC>(cx, length, &storage);
|
||||||
|
if (!str) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
FillAndTerminate(storage, chars, length);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto news = cx->make_pod_array<char16_t>(length + 1);
|
||||||
|
if (!news) {
|
||||||
|
cx->recoverFromOutOfMemory();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
FillAndTerminate(news.get(), chars, length);
|
||||||
|
|
||||||
|
if (JSFlatString* str = JSFlatString::new_<NoGC>(cx, news.get(), length)) {
|
||||||
|
// Successful JSFlatString::new_ took ownership of |news.release()|.
|
||||||
|
mozilla::Unused << news.release();
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
JSFlatString* NewLatin1StringZ(JSContext* cx, UniqueChars chars) {
|
JSFlatString* NewLatin1StringZ(JSContext* cx, UniqueChars chars) {
|
||||||
size_t length = strlen(chars.get());
|
size_t length = strlen(chars.get());
|
||||||
UniqueLatin1Chars latin1(reinterpret_cast<Latin1Char*>(chars.release()));
|
UniqueLatin1Chars latin1(reinterpret_cast<Latin1Char*>(chars.release()));
|
||||||
@ -1783,6 +1855,20 @@ template JSFlatString* NewStringCopyN<CanGC>(JSContext* cx, const Latin1Char* s,
|
|||||||
template JSFlatString* NewStringCopyN<NoGC>(JSContext* cx, const Latin1Char* s,
|
template JSFlatString* NewStringCopyN<NoGC>(JSContext* cx, const Latin1Char* s,
|
||||||
size_t n);
|
size_t n);
|
||||||
|
|
||||||
|
JSFlatString* NewStringFromLittleEndianNoGC(JSContext* cx,
|
||||||
|
LittleEndianChars chars,
|
||||||
|
size_t length) {
|
||||||
|
if (JSFlatString* str = TryEmptyOrStaticString(cx, chars, length)) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CanStoreCharsAsLatin1(chars, length)) {
|
||||||
|
return NewStringDeflatedFromLittleEndianNoGC(cx, chars, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewUndeflatedStringFromLittleEndianNoGC(cx, chars, length);
|
||||||
|
}
|
||||||
|
|
||||||
template <js::AllowGC allowGC>
|
template <js::AllowGC allowGC>
|
||||||
JSFlatString* NewStringCopyUTF8N(JSContext* cx, const JS::UTF8Chars utf8) {
|
JSFlatString* NewStringCopyUTF8N(JSContext* cx, const JS::UTF8Chars utf8) {
|
||||||
JS::SmallestEncoding encoding = JS::FindSmallestEncoding(utf8);
|
JS::SmallestEncoding encoding = JS::FindSmallestEncoding(utf8);
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include "mozilla/Range.h"
|
#include "mozilla/Range.h"
|
||||||
#include "mozilla/TextUtils.h"
|
#include "mozilla/TextUtils.h"
|
||||||
|
|
||||||
|
#include <type_traits> // std::is_same
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "jsfriendapi.h"
|
#include "jsfriendapi.h"
|
||||||
|
|
||||||
@ -1331,6 +1333,24 @@ MOZ_ALWAYS_INLINE JSAtom* JSFlatString::morphAtomizedStringIntoPermanentAtom(
|
|||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An indexable characters class exposing unaligned, little-endian encoded
|
||||||
|
* char16_t data.
|
||||||
|
*/
|
||||||
|
class LittleEndianChars {
|
||||||
|
public:
|
||||||
|
explicit constexpr LittleEndianChars(const uint8_t* leTwoByte)
|
||||||
|
: current(leTwoByte) {}
|
||||||
|
|
||||||
|
constexpr char16_t operator[](size_t index) const {
|
||||||
|
size_t offset = index * sizeof(char16_t);
|
||||||
|
return (current[offset + 1] << 8) | current[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const uint8_t* current;
|
||||||
|
};
|
||||||
|
|
||||||
class StaticStrings {
|
class StaticStrings {
|
||||||
private:
|
private:
|
||||||
/* Bigger chars cannot be in a length-2 string. */
|
/* Bigger chars cannot be in a length-2 string. */
|
||||||
@ -1382,8 +1402,14 @@ class StaticStrings {
|
|||||||
static bool isStatic(JSAtom* atom);
|
static bool isStatic(JSAtom* atom);
|
||||||
|
|
||||||
/* Return null if no static atom exists for the given (chars, length). */
|
/* Return null if no static atom exists for the given (chars, length). */
|
||||||
template <typename CharT>
|
template <typename Chars>
|
||||||
MOZ_ALWAYS_INLINE JSAtom* lookup(const CharT* chars, size_t length) {
|
MOZ_ALWAYS_INLINE JSAtom* lookup(Chars chars, size_t length) {
|
||||||
|
static_assert(std::is_same<Chars, const Latin1Char*>::value ||
|
||||||
|
std::is_same<Chars, const char16_t*>::value ||
|
||||||
|
std::is_same<Chars, LittleEndianChars>::value,
|
||||||
|
"for understandability, |chars| must be one of a few "
|
||||||
|
"identified types");
|
||||||
|
|
||||||
switch (length) {
|
switch (length) {
|
||||||
case 1: {
|
case 1: {
|
||||||
char16_t c = chars[0];
|
char16_t c = chars[0];
|
||||||
@ -1423,6 +1449,19 @@ class StaticStrings {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename CharT, typename = typename std::enable_if<
|
||||||
|
std::is_same<CharT, char>::value ||
|
||||||
|
std::is_same<CharT, const char>::value ||
|
||||||
|
!std::is_const<CharT>::value>::type>
|
||||||
|
MOZ_ALWAYS_INLINE JSAtom* lookup(CharT* chars, size_t length) {
|
||||||
|
// Collapse calls for |char*| or |const char*| into |const unsigned char*|
|
||||||
|
// to avoid excess instantiations. Collapse the remaining |CharT*| to
|
||||||
|
// |const CharT*| for the same reason.
|
||||||
|
using UnsignedCharT = typename std::make_unsigned<CharT>::type;
|
||||||
|
UnsignedCharT* unsignedChars = reinterpret_cast<UnsignedCharT*>(chars);
|
||||||
|
return lookup(const_cast<const UnsignedCharT*>(unsignedChars), length);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef uint8_t SmallChar;
|
typedef uint8_t SmallChar;
|
||||||
static const SmallChar INVALID_SMALL_CHAR = -1;
|
static const SmallChar INVALID_SMALL_CHAR = -1;
|
||||||
@ -1560,6 +1599,13 @@ JSString* NewMaybeExternalString(JSContext* cx, const char16_t* s, size_t n,
|
|||||||
const JSStringFinalizer* fin,
|
const JSStringFinalizer* fin,
|
||||||
bool* allocatedExternal);
|
bool* allocatedExternal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a new string consisting of |chars[0..length]| characters.
|
||||||
|
*/
|
||||||
|
extern JSFlatString* NewStringFromLittleEndianNoGC(JSContext* cx,
|
||||||
|
LittleEndianChars chars,
|
||||||
|
size_t length);
|
||||||
|
|
||||||
JS_STATIC_ASSERT(sizeof(HashNumber) == 4);
|
JS_STATIC_ASSERT(sizeof(HashNumber) == 4);
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
template <AllowGC allowGC>
|
||||||
|
@ -86,21 +86,22 @@ XDRResult XDRState<mode>::codeChars(char16_t* chars, size_t nchars) {
|
|||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Align the buffer to avoid unaligned loads.
|
|
||||||
MOZ_TRY(codeAlign(sizeof(char16_t)));
|
|
||||||
|
|
||||||
size_t nbytes = nchars * sizeof(char16_t);
|
size_t nbytes = nchars * sizeof(char16_t);
|
||||||
if (mode == XDR_ENCODE) {
|
if (mode == XDR_ENCODE) {
|
||||||
uint8_t* ptr = buf.write(nbytes);
|
uint8_t* ptr = buf.write(nbytes);
|
||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
return fail(JS::TranscodeResult_Throw);
|
return fail(JS::TranscodeResult_Throw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// |mozilla::NativeEndian| correctly handles writing into unaligned |ptr|.
|
||||||
mozilla::NativeEndian::copyAndSwapToLittleEndian(ptr, chars, nchars);
|
mozilla::NativeEndian::copyAndSwapToLittleEndian(ptr, chars, nchars);
|
||||||
} else {
|
} else {
|
||||||
const uint8_t* ptr = buf.read(nbytes);
|
const uint8_t* ptr = buf.read(nbytes);
|
||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
return fail(JS::TranscodeResult_Failure_BadDecode);
|
return fail(JS::TranscodeResult_Failure_BadDecode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// |mozilla::NativeEndian| correctly handles reading from unaligned |ptr|.
|
||||||
mozilla::NativeEndian::copyAndSwapFromLittleEndian(chars, ptr, nchars);
|
mozilla::NativeEndian::copyAndSwapFromLittleEndian(chars, ptr, nchars);
|
||||||
}
|
}
|
||||||
return Ok();
|
return Ok();
|
||||||
|
@ -484,8 +484,6 @@ class XDRState : public XDRCoderBase {
|
|||||||
XDRResult codeChars(JS::Latin1Char* chars, size_t nchars);
|
XDRResult codeChars(JS::Latin1Char* chars, size_t nchars);
|
||||||
XDRResult codeChars(mozilla::Utf8Unit* units, size_t nchars);
|
XDRResult codeChars(mozilla::Utf8Unit* units, size_t nchars);
|
||||||
|
|
||||||
// If |nchars > 0|, this calls |codeAlign(sizeof(char16_t))| so callers
|
|
||||||
// don't have to.
|
|
||||||
XDRResult codeChars(char16_t* chars, size_t nchars);
|
XDRResult codeChars(char16_t* chars, size_t nchars);
|
||||||
|
|
||||||
XDRResult codeFunction(JS::MutableHandleFunction objp,
|
XDRResult codeFunction(JS::MutableHandleFunction objp,
|
||||||
|
@ -60,15 +60,6 @@ using namespace mozilla::loader;
|
|||||||
|
|
||||||
ProcessType ScriptPreloader::sProcessType;
|
ProcessType ScriptPreloader::sProcessType;
|
||||||
|
|
||||||
// This type correspond to js::vm::XDRAlignment type, which is used as a size
|
|
||||||
// reference for alignment of XDR buffers.
|
|
||||||
using XDRAlign = uint16_t;
|
|
||||||
static const uint8_t sAlignPadding[sizeof(XDRAlign)] = {0, 0};
|
|
||||||
|
|
||||||
static inline size_t ComputeByteAlignment(size_t bytes, size_t align) {
|
|
||||||
return (align - (bytes % align)) % align;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult ScriptPreloader::CollectReports(nsIHandleReportCallback* aHandleReport,
|
nsresult ScriptPreloader::CollectReports(nsIHandleReportCallback* aHandleReport,
|
||||||
nsISupports* aData, bool aAnonymize) {
|
nsISupports* aData, bool aAnonymize) {
|
||||||
MOZ_COLLECT_REPORT(
|
MOZ_COLLECT_REPORT(
|
||||||
@ -540,8 +531,6 @@ Result<Ok, nsresult> ScriptPreloader::InitCacheInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto data = mCacheData.get<uint8_t>();
|
auto data = mCacheData.get<uint8_t>();
|
||||||
uint8_t* start = data.get();
|
|
||||||
MOZ_ASSERT(reinterpret_cast<uintptr_t>(start) % sizeof(XDRAlign) == 0);
|
|
||||||
auto end = data + size;
|
auto end = data + size;
|
||||||
|
|
||||||
if (memcmp(MAGIC, data.get(), sizeof(MAGIC))) {
|
if (memcmp(MAGIC, data.get(), sizeof(MAGIC))) {
|
||||||
@ -566,10 +555,6 @@ Result<Ok, nsresult> ScriptPreloader::InitCacheInternal(
|
|||||||
|
|
||||||
InputBuffer buf(header);
|
InputBuffer buf(header);
|
||||||
|
|
||||||
size_t len = data.get() - start;
|
|
||||||
size_t alignLen = ComputeByteAlignment(len, sizeof(XDRAlign));
|
|
||||||
data += alignLen;
|
|
||||||
|
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
while (!buf.finished()) {
|
while (!buf.finished()) {
|
||||||
auto script = MakeUnique<CachedScript>(*this, buf);
|
auto script = MakeUnique<CachedScript>(*this, buf);
|
||||||
@ -587,9 +572,6 @@ Result<Ok, nsresult> ScriptPreloader::InitCacheInternal(
|
|||||||
}
|
}
|
||||||
offset += script->mSize;
|
offset += script->mSize;
|
||||||
|
|
||||||
MOZ_ASSERT(reinterpret_cast<uintptr_t>(scriptData.get()) %
|
|
||||||
sizeof(XDRAlign) ==
|
|
||||||
0);
|
|
||||||
script->mXDRRange.emplace(scriptData, scriptData + script->mSize);
|
script->mXDRRange.emplace(scriptData, scriptData + script->mSize);
|
||||||
|
|
||||||
// Don't pre-decode the script unless it was used in this process type
|
// Don't pre-decode the script unless it was used in this process type
|
||||||
@ -739,7 +721,6 @@ Result<Ok, nsresult> ScriptPreloader::WriteCache() {
|
|||||||
OutputBuffer buf;
|
OutputBuffer buf;
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
for (auto script : scripts) {
|
for (auto script : scripts) {
|
||||||
MOZ_ASSERT(offset % sizeof(XDRAlign) == 0);
|
|
||||||
script->mOffset = offset;
|
script->mOffset = offset;
|
||||||
script->Code(buf);
|
script->Code(buf);
|
||||||
|
|
||||||
@ -749,22 +730,11 @@ Result<Ok, nsresult> ScriptPreloader::WriteCache() {
|
|||||||
uint8_t headerSize[4];
|
uint8_t headerSize[4];
|
||||||
LittleEndian::writeUint32(headerSize, buf.cursor());
|
LittleEndian::writeUint32(headerSize, buf.cursor());
|
||||||
|
|
||||||
size_t len = 0;
|
|
||||||
MOZ_TRY(Write(fd, MAGIC, sizeof(MAGIC)));
|
MOZ_TRY(Write(fd, MAGIC, sizeof(MAGIC)));
|
||||||
len += sizeof(MAGIC);
|
|
||||||
MOZ_TRY(Write(fd, headerSize, sizeof(headerSize)));
|
MOZ_TRY(Write(fd, headerSize, sizeof(headerSize)));
|
||||||
len += sizeof(headerSize);
|
|
||||||
MOZ_TRY(Write(fd, buf.Get(), buf.cursor()));
|
MOZ_TRY(Write(fd, buf.Get(), buf.cursor()));
|
||||||
len += buf.cursor();
|
|
||||||
size_t alignLen = ComputeByteAlignment(len, sizeof(XDRAlign));
|
|
||||||
if (alignLen) {
|
|
||||||
MOZ_TRY(Write(fd, sAlignPadding, alignLen));
|
|
||||||
len += alignLen;
|
|
||||||
}
|
|
||||||
for (auto script : scripts) {
|
for (auto script : scripts) {
|
||||||
MOZ_ASSERT(script->mSize % sizeof(XDRAlign) == 0);
|
|
||||||
MOZ_TRY(Write(fd, script->Range().begin().get(), script->mSize));
|
MOZ_TRY(Write(fd, script->Range().begin().get(), script->mSize));
|
||||||
len += script->mSize;
|
|
||||||
|
|
||||||
if (script->mScript) {
|
if (script->mScript) {
|
||||||
script->FreeData();
|
script->FreeData();
|
||||||
|
@ -404,7 +404,9 @@ class Endian : private EndianUtils {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
|
* Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
|
||||||
* them to little-endian format if ThisEndian is Big.
|
* them to little-endian format if ThisEndian is Big. |aSrc| as a typed
|
||||||
|
* pointer must be aligned; |aDest| need not be.
|
||||||
|
*
|
||||||
* As with memcpy, |aDest| and |aSrc| must not overlap.
|
* As with memcpy, |aDest| and |aSrc| must not overlap.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -431,7 +433,9 @@ class Endian : private EndianUtils {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
|
* Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
|
||||||
* them to big-endian format if ThisEndian is Little.
|
* them to big-endian format if ThisEndian is Little. |aSrc| as a typed
|
||||||
|
* pointer must be aligned; |aDest| need not be.
|
||||||
|
*
|
||||||
* As with memcpy, |aDest| and |aSrc| must not overlap.
|
* As with memcpy, |aDest| and |aSrc| must not overlap.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -479,7 +483,9 @@ class Endian : private EndianUtils {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
|
* Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
|
||||||
* them to little-endian format if ThisEndian is Big.
|
* them to little-endian format if ThisEndian is Big. |aDest| as a typed
|
||||||
|
* pointer must be aligned; |aSrc| need not be.
|
||||||
|
*
|
||||||
* As with memcpy, |aDest| and |aSrc| must not overlap.
|
* As with memcpy, |aDest| and |aSrc| must not overlap.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -506,7 +512,9 @@ class Endian : private EndianUtils {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
|
* Copies |aCount| values of type T starting at |aSrc| to |aDest|, converting
|
||||||
* them to big-endian format if ThisEndian is Little.
|
* them to big-endian format if ThisEndian is Little. |aDest| as a typed
|
||||||
|
* pointer must be aligned; |aSrc| need not be.
|
||||||
|
*
|
||||||
* As with memcpy, |aDest| and |aSrc| must not overlap.
|
* As with memcpy, |aDest| and |aSrc| must not overlap.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
Loading…
Reference in New Issue
Block a user