зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1587738, bug 1588051) for build bustage on js/src/jsapi-tests/testBinASTReader.cpp. CLOSED TREE
Backed out changeset 0c6326559079 (bug 1588051) Backed out changeset ded00ff91429 (bug 1587738)
This commit is contained in:
Родитель
92caaefe3b
Коммит
c7518beb08
|
@ -1794,8 +1794,7 @@ JS::Result<Ok> GenericHuffmanTable::initStart(JSContext* cx,
|
|||
// `largestBitLength`.
|
||||
// ...hopefully, only one lookup.
|
||||
if (largestBitLength <= SingleLookupHuffmanTable::MAX_BIT_LENGTH) {
|
||||
implementation_ = {mozilla::VariantType<SingleLookupHuffmanTable>{}, cx,
|
||||
SingleLookupHuffmanTable::Use::ToplevelTable};
|
||||
implementation_ = {mozilla::VariantType<SingleLookupHuffmanTable>{}, cx};
|
||||
return implementation_.template as<SingleLookupHuffmanTable>().initStart(
|
||||
cx, numberOfSymbols, largestBitLength);
|
||||
}
|
||||
|
@ -2010,17 +2009,10 @@ JS::Result<Ok> SingleLookupHuffmanTable::initComplete() {
|
|||
MOZ_ASSERT(largestBitLength_ == 0);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool foundMaxBitLength = false;
|
||||
for (size_t i = 0; i < saturated_.length(); ++i) {
|
||||
const uint8_t index = saturated_[i];
|
||||
if (use_ != Use::ToplevelTable) {
|
||||
// The table may not be full.
|
||||
if (index >= values_.length()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(values_[index].key().bitLength_ <= largestBitLength_);
|
||||
if (values_[index].key().bitLength_ == largestBitLength_) {
|
||||
foundMaxBitLength = true;
|
||||
|
@ -2028,7 +2020,6 @@ JS::Result<Ok> SingleLookupHuffmanTable::initComplete() {
|
|||
}
|
||||
MOZ_ASSERT(foundMaxBitLength);
|
||||
#endif // DEBUG
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
@ -2080,12 +2071,6 @@ HuffmanLookupResult SingleLookupHuffmanTable::lookup(HuffmanLookup key) const {
|
|||
// Invariants: `saturated_.length() == 1 << largestBitLength_`
|
||||
// and `bits <= 1 << largestBitLength_`.
|
||||
const size_t index = saturated_[bits];
|
||||
if (index >= values_.length()) {
|
||||
// This is useful only when the `SingleLookupHuffmanTable`
|
||||
// is used as a cache inside a `MultiLookupHuffmanTable`.
|
||||
MOZ_ASSERT(use_ == Use::ShortKeys);
|
||||
return HuffmanLookupResult::notFound();
|
||||
}
|
||||
|
||||
// Invariants: `saturated_[i] < values_.length()`.
|
||||
const auto& entry = values_[index];
|
||||
|
@ -2133,12 +2118,12 @@ JS::Result<Ok> MultiLookupHuffmanTable<Subtable, PrefixBitLength>::initStart(
|
|||
static_assert(PrefixBitLength < MAX_CODE_BIT_LENGTH,
|
||||
"Invalid PrefixBitLength");
|
||||
MOZ_ASSERT(values_.empty()); // Make sure that we're initializing.
|
||||
MOZ_ASSERT(suffixTables_.empty());
|
||||
MOZ_ASSERT(subTables_.empty());
|
||||
largestBitLength_ = largestBitLength;
|
||||
if (MOZ_UNLIKELY(!values_.initCapacity(numberOfSymbols))) {
|
||||
return cx->alreadyReportedError();
|
||||
}
|
||||
if (MOZ_UNLIKELY(!suffixTables_.initCapacity(1 << PrefixBitLength))) {
|
||||
if (MOZ_UNLIKELY(!subTables_.initCapacity(1 << PrefixBitLength))) {
|
||||
return cx->alreadyReportedError();
|
||||
}
|
||||
return Ok();
|
||||
|
@ -2166,24 +2151,11 @@ MultiLookupHuffmanTable<Subtable, PrefixBitLength>::initComplete() {
|
|||
Bucket() : largestBitLength_(0), numberOfSymbols_(0){};
|
||||
uint8_t largestBitLength_;
|
||||
uint32_t numberOfSymbols_;
|
||||
void addSymbol(uint8_t bitLength) {
|
||||
++numberOfSymbols_;
|
||||
if (bitLength > largestBitLength_) {
|
||||
largestBitLength_ = bitLength;
|
||||
}
|
||||
}
|
||||
};
|
||||
Vector<Bucket> buckets{cx_};
|
||||
BINJS_TRY(buckets.resize(1 << PrefixBitLength));
|
||||
Bucket shortKeysBucket;
|
||||
|
||||
for (const auto& entry : values_) {
|
||||
if (entry.key().bitLength_ <= SingleLookupHuffmanTable::MAX_BIT_LENGTH) {
|
||||
// If the key is short, we put it in `shortKeys_` instead of
|
||||
// `suffixTables`.
|
||||
shortKeysBucket.addSymbol(entry.key().bitLength_);
|
||||
continue;
|
||||
}
|
||||
const HuffmanLookup lookup(entry.key().bits_, entry.key().bitLength_);
|
||||
const auto split = lookup.split(PrefixBitLength);
|
||||
MOZ_ASSERT_IF(split.suffix_.bitLength_ != 32,
|
||||
|
@ -2195,46 +2167,34 @@ MultiLookupHuffmanTable<Subtable, PrefixBitLength>::initComplete() {
|
|||
// (e.g. G, H in the documentation).
|
||||
for (const auto index : lookup.suffixes(PrefixBitLength)) {
|
||||
Bucket& bucket = buckets[index];
|
||||
bucket.addSymbol(split.suffix_.bitLength_);
|
||||
if (split.suffix_.bitLength_ >= bucket.largestBitLength_) {
|
||||
bucket.largestBitLength_ = split.suffix_.bitLength_;
|
||||
}
|
||||
bucket.numberOfSymbols_++;
|
||||
}
|
||||
}
|
||||
|
||||
// We may now create the subtables.
|
||||
for (auto& bucket : buckets) {
|
||||
Subtable sub(cx_);
|
||||
if (bucket.numberOfSymbols_ != 0) {
|
||||
// Often, a subtable will end up empty because all the prefixes end up
|
||||
// in `shortKeys_`. In such a case, we want to avoid initializing the
|
||||
// table.
|
||||
MOZ_TRY(sub.initStart(cx_,
|
||||
/* numberOfSymbols = */ bucket.numberOfSymbols_,
|
||||
/* maxBitLength = */ bucket.largestBitLength_));
|
||||
}
|
||||
BINJS_TRY(suffixTables_.append(std::move(sub)));
|
||||
MOZ_TRY(sub.initStart(cx_,
|
||||
/* numberOfSymbols = */ bucket.numberOfSymbols_,
|
||||
/* largestBitLength = */ bucket.largestBitLength_));
|
||||
BINJS_TRY(subTables_.append(std::move(sub)));
|
||||
}
|
||||
|
||||
// Also, create the shortKeys_ fast lookup.
|
||||
MOZ_TRY(shortKeys_.initStart(cx_, shortKeysBucket.numberOfSymbols_,
|
||||
shortKeysBucket.largestBitLength_));
|
||||
|
||||
// Now that all the subtables are created, let's dispatch the values
|
||||
// Now that the subtables are created, let's dispatch the values
|
||||
// among these tables.
|
||||
for (size_t i = 0; i < values_.length(); ++i) {
|
||||
const auto& entry = values_[i];
|
||||
if (entry.key().bitLength_ <= SingleLookupHuffmanTable::MAX_BIT_LENGTH) {
|
||||
// The key fits in `shortKeys_`, let's use this table.
|
||||
MOZ_TRY(shortKeys_.addSymbol(entry.key().bits_, entry.key().bitLength_,
|
||||
BinASTSymbol::fromSubtableIndex(i)));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, use one of the suffix tables.
|
||||
// Find the relevant subtables.
|
||||
const HuffmanLookup lookup(entry.key().bits_, entry.key().bitLength_);
|
||||
const auto split = lookup.split(PrefixBitLength);
|
||||
MOZ_ASSERT_IF(split.suffix_.bitLength_ != 32,
|
||||
split.suffix_.bits_ >> split.suffix_.bitLength_ == 0);
|
||||
for (const auto index : lookup.suffixes(PrefixBitLength)) {
|
||||
auto& sub = suffixTables_[index];
|
||||
auto& sub = subTables_[index];
|
||||
|
||||
// We may now add a reference to `entry` into the sybtable.
|
||||
MOZ_TRY(sub.addSymbol(split.suffix_.bits_, split.suffix_.bitLength_,
|
||||
|
@ -2242,14 +2202,8 @@ MultiLookupHuffmanTable<Subtable, PrefixBitLength>::initComplete() {
|
|||
}
|
||||
}
|
||||
|
||||
// Finally, complete initialization of shortKeys_ and subtables.
|
||||
MOZ_TRY(shortKeys_.initComplete());
|
||||
for (size_t i = 0; i < buckets.length(); ++i) {
|
||||
if (buckets[i].numberOfSymbols_ == 0) {
|
||||
// Again, we don't want to initialize empty subtables.
|
||||
continue;
|
||||
}
|
||||
auto& sub = suffixTables_[i];
|
||||
// Finally, complete initialization of subtables.
|
||||
for (auto& sub : subTables_) {
|
||||
MOZ_TRY(sub.initComplete());
|
||||
}
|
||||
|
||||
|
@ -2259,22 +2213,11 @@ MultiLookupHuffmanTable<Subtable, PrefixBitLength>::initComplete() {
|
|||
template <typename Subtable, uint8_t PrefixBitLength>
|
||||
HuffmanLookupResult MultiLookupHuffmanTable<Subtable, PrefixBitLength>::lookup(
|
||||
HuffmanLookup key) const {
|
||||
{
|
||||
// Let's first look in shortkeys.
|
||||
auto subResult = shortKeys_.lookup(key);
|
||||
if (subResult.isFound()) {
|
||||
// We have found a result in the shortKeys_ fastpath.
|
||||
const auto& result = values_[subResult.value().toSubtableIndex()];
|
||||
|
||||
return HuffmanLookupResult::found(result.key().bitLength_,
|
||||
&result.value());
|
||||
}
|
||||
}
|
||||
const auto split = key.split(PrefixBitLength);
|
||||
if (split.prefix_.bits_ >= suffixTables_.length()) {
|
||||
if (split.prefix_.bits_ >= subTables_.length()) {
|
||||
return HuffmanLookupResult::notFound();
|
||||
}
|
||||
const Subtable& subtable = suffixTables_[split.prefix_.bits_];
|
||||
const Subtable& subtable = subTables_[split.prefix_.bits_];
|
||||
|
||||
auto subResult = subtable.lookup(split.suffix_);
|
||||
if (!subResult.isFound()) {
|
||||
|
|
|
@ -433,31 +433,11 @@ class SingleLookupHuffmanTable {
|
|||
// used by the table.
|
||||
using InternalIndex = uint8_t;
|
||||
|
||||
// An enum used to represent how this table is used.
|
||||
// Used to perform additional DEBUG assertions.
|
||||
enum Use {
|
||||
// Used as a `Subtable` argument of a `MultiLookupHuffmanTable`.
|
||||
LeafOfMultiLookupHuffmanTable,
|
||||
// Used as its own table.
|
||||
ToplevelTable,
|
||||
// Used as a `shortKeys_` in a `MultiLookupHuffmanTable`.
|
||||
ShortKeys,
|
||||
};
|
||||
|
||||
// The largest bit length that may be represented by this table.
|
||||
static const uint8_t MAX_BIT_LENGTH = sizeof(InternalIndex) * 8;
|
||||
|
||||
explicit SingleLookupHuffmanTable(
|
||||
JSContext* cx, Use use = Use::LeafOfMultiLookupHuffmanTable)
|
||||
: values_(cx),
|
||||
saturated_(cx),
|
||||
largestBitLength_(-1)
|
||||
#ifdef DEBUG
|
||||
,
|
||||
use_(use)
|
||||
#endif // DEBUG
|
||||
{
|
||||
}
|
||||
explicit SingleLookupHuffmanTable(JSContext* cx)
|
||||
: values_(cx), saturated_(cx), largestBitLength_(-1) {}
|
||||
SingleLookupHuffmanTable(SingleLookupHuffmanTable&& other) = default;
|
||||
|
||||
// Initialize a Huffman table containing `numberOfSymbols`.
|
||||
|
@ -528,10 +508,6 @@ class SingleLookupHuffmanTable {
|
|||
// - `largestBitLength_ <= MAX_CODE_BIT_LENGTH`
|
||||
uint8_t largestBitLength_;
|
||||
|
||||
#ifdef DEBUG
|
||||
Use use_;
|
||||
#endif // DEBUG
|
||||
|
||||
friend class HuffmanPreludeReader;
|
||||
};
|
||||
|
||||
|
@ -545,13 +521,10 @@ class SingleLookupHuffmanTable {
|
|||
/// # Time complexity
|
||||
///
|
||||
/// A lookup in `MultiLookupHuffmanTable` will also take constant time:
|
||||
|
||||
/// - a constant-time lookup in a `SingleLookupHuffmanTable`, in case we only
|
||||
/// need to look for a small key;
|
||||
/// - if the above lookup fails:
|
||||
/// - a constant-time lookup to determine into which suffix table to perform
|
||||
/// the lookup;
|
||||
/// - a constant-time lookup into the suffix table;
|
||||
///
|
||||
/// - a constant-time lookup to determine into which sub-table to perform the
|
||||
/// lookup;
|
||||
/// - a constant-time lookup into the sub-table;
|
||||
/// - a constant-time lookup into the array of values.
|
||||
///
|
||||
///
|
||||
|
@ -575,100 +548,87 @@ class SingleLookupHuffmanTable {
|
|||
/// G | 00 | 2
|
||||
/// H | 01 | 2
|
||||
///
|
||||
/// Let us assume that we have somehow determined that:
|
||||
/// With a prefix length of 3, we will precompute all possible 3-bit prefixes
|
||||
/// and split the table across such prefixes. Note that we have picked a
|
||||
/// length of 3 bits arbitrarily – in this case it is larger than the
|
||||
/// bit length of some symbols.
|
||||
///
|
||||
/// - we wish to store all values with a bit length of 2
|
||||
/// or less in a fast access table.
|
||||
/// - we wish to use a prefix length of 4.
|
||||
///
|
||||
/// Note: These numbers of 2 and 4 are picked arbitrarily
|
||||
/// for the example. Actual numbers used may vary.
|
||||
///
|
||||
/// We first extract all values with a bit length of <= 2:
|
||||
///
|
||||
/// Symbol | Binary Code | Bit Length
|
||||
/// ------ | ------------ | ----------
|
||||
/// G | 00 | 2
|
||||
/// H | 01 | 2
|
||||
///
|
||||
/// We store these values in a `SingleLookupHuffmanTable` for fast access.
|
||||
/// We are now done with these values. Let's deal with the remaining values.
|
||||
///
|
||||
/// Now, as our prefix length is 4, we precompute all possible 3-bit
|
||||
/// prefixes and split the table across such prefixes.
|
||||
///
|
||||
/// Prefix | Int Value of Prefix | Symbols | Max bit length
|
||||
/// ------- | ------------------- | --------- | --------------
|
||||
/// 0000 | 0 | | 0
|
||||
/// 0001 | 1 | | 0
|
||||
/// 0010 | 2 | | 0
|
||||
/// 0011 | 3 | | 0
|
||||
/// 0100 | 4 | | 0
|
||||
/// 0101 | 5 | | 0
|
||||
/// 0110 | 6 | | 0
|
||||
/// 0111 | 7 | | 0
|
||||
/// 1000 | 8 | D | 0
|
||||
/// 1001 | 9 | D | 0
|
||||
/// 1010 | 10 | E | 0
|
||||
/// 1011 | 11 | E | 0
|
||||
/// 1100 | 12 | A, B | 1
|
||||
/// 1101 | 13 | C | 0
|
||||
/// 1110 | 14 | F | 0
|
||||
/// 1111 | 15 | F | 0
|
||||
/// Prefix | Int Value of Prefix | Symbols | Max bit length
|
||||
/// ------ | ------------------- | --------- | --------------
|
||||
/// 000 | 0 | G | 0
|
||||
/// 001 | 1 | G | 0
|
||||
/// 010 | 2 | H | 0
|
||||
/// 011 | 3 | H | 0
|
||||
/// 100 | 4 | D | 0
|
||||
/// 101 | 5 | E | 0
|
||||
/// 110 | 6 | A, B, C | 2
|
||||
/// 111 | 7 | F | 0
|
||||
///
|
||||
/// For each prefix, we build the table containing the Symbols,
|
||||
/// stripping prefix from the Binary Code.
|
||||
/// - Prefixes 0000-01111
|
||||
///
|
||||
/// Empty tables.
|
||||
/// - Prefix 000
|
||||
///
|
||||
/// - Prefixes 1000, 1001
|
||||
/// Symbol | Binary Code | Bit Length | Total Bit Length
|
||||
/// ------ | ----------- | ---------- | ----------------
|
||||
/// G | (none) | 0 | 2
|
||||
///
|
||||
/// - Prefix 001
|
||||
///
|
||||
/// Symbol | Binary Code | Bit Length | Total Bit Length
|
||||
/// ------ | ----------- | ---------- | ----------------
|
||||
/// G | (none) | 0 | 2
|
||||
///
|
||||
/// - Prefix 010
|
||||
///
|
||||
/// Symbol | Binary Code | Bit Length | Total Bit Length
|
||||
/// ------ | ----------- | ---------- | --------------
|
||||
/// H | (none) | 0 | 2
|
||||
///
|
||||
/// - Prefix 11
|
||||
///
|
||||
/// Symbol | Binary Code | Bit Length | Total Bit Length
|
||||
/// ------ | ----------- | ---------- | ----------------
|
||||
/// H | (none) | 0 | 2
|
||||
///
|
||||
/// - Prefix 100
|
||||
///
|
||||
/// Symbol | Binary Code | Bit Length | Total Bit Length
|
||||
/// ------ | ----------- | ---------- | ----------------
|
||||
/// D | (none) | 0 | 3
|
||||
///
|
||||
/// - Prefixes 1010, 1011
|
||||
/// - Prefix 101
|
||||
///
|
||||
/// Symbol | Binary Code | Bit Length | Total Bit Length
|
||||
/// ------ | ----------- | ---------- | --------------
|
||||
/// ------ | ----------- | ---------- | ----------------
|
||||
/// E | (none) | 0 | 3
|
||||
///
|
||||
/// - Prefix 1100
|
||||
/// - Prefix 110
|
||||
///
|
||||
/// Symbol | Binary Code | Bit Length | Total Bit Length
|
||||
/// ------ | ----------- | ---------- | ----------------
|
||||
/// A | 0 | 1 | 5
|
||||
/// B | 1 | 1 | 5
|
||||
/// A | 00 | 2 | 5
|
||||
/// B | 01 | 2 | 5
|
||||
/// C | 1 | 1 | 4
|
||||
///
|
||||
/// - Prefix 1101
|
||||
/// - Prefix 111
|
||||
///
|
||||
/// Symbol | Binary Code | Bit Length | Total Bit Length
|
||||
/// ------ | ----------- | ---------- | ----------------
|
||||
/// C | (none) | 0 | 4
|
||||
///
|
||||
/// - Prefixes 1110, 1111
|
||||
///
|
||||
/// Symbol | Binary Code | Bit Length | Total Bit Length
|
||||
/// ------ | ----------- | ---------- | ----------------
|
||||
/// F | (none) | 0 | 4
|
||||
///
|
||||
/// F | (none) | 0 | 3
|
||||
///
|
||||
/// With this transformation, we have represented one table
|
||||
/// with an initial max bit length of 5 as:
|
||||
///
|
||||
/// - 1 SingleLookupValue table with a max bit length of 3;
|
||||
/// - 8 empty tables;
|
||||
/// - 7 tables with a max bit length of 0;
|
||||
/// - 1 table with a max bit length of 1;
|
||||
/// - 1 table with a max bit length of 2;
|
||||
/// - 7 tables with a max bit length of 0.
|
||||
///
|
||||
/// Consequently, instead of storing 2^5 = 32 internal references,
|
||||
/// as we would have done with a SingleLookupHuffmanTable, we only
|
||||
/// need to store:
|
||||
///
|
||||
/// - 1 subtable with 2^3 = 8 references;
|
||||
/// - 7 subtables with 1 reference each;
|
||||
/// - 1 subtable with 2^1 = 2 references.
|
||||
/// - 1 subtable with 2^2 = 4 references.
|
||||
template <typename Subtable, uint8_t PrefixBitLength>
|
||||
class MultiLookupHuffmanTable {
|
||||
public:
|
||||
|
@ -677,11 +637,7 @@ class MultiLookupHuffmanTable {
|
|||
PrefixBitLength + Subtable::MAX_BIT_LENGTH;
|
||||
|
||||
explicit MultiLookupHuffmanTable(JSContext* cx)
|
||||
: cx_(cx),
|
||||
shortKeys_(cx, SingleLookupHuffmanTable::Use::ShortKeys),
|
||||
values_(cx),
|
||||
suffixTables_(cx),
|
||||
largestBitLength_(-1) {}
|
||||
: cx_(cx), values_(cx), subTables_(cx), largestBitLength_(-1) {}
|
||||
MultiLookupHuffmanTable(MultiLookupHuffmanTable&& other) = default;
|
||||
|
||||
// Initialize a Huffman table containing `numberOfSymbols`.
|
||||
|
@ -740,10 +696,6 @@ class MultiLookupHuffmanTable {
|
|||
private:
|
||||
JSContext* cx_;
|
||||
|
||||
// Fast lookup for values whose keys fit within 8 bits.
|
||||
// Such values are not added to `suffixTables`.
|
||||
SingleLookupHuffmanTable shortKeys_;
|
||||
|
||||
// The entries in this Huffman Table, sorted in the order of insertion.
|
||||
//
|
||||
// Invariant (once `init*` has been called):
|
||||
|
@ -761,7 +713,7 @@ class MultiLookupHuffmanTable {
|
|||
// Note that, to allow the use of smaller tables, keys
|
||||
// inside the subtables have been stripped
|
||||
// from the prefix `HuffmanKey(i, prefixBitLen)`.
|
||||
Vector<Subtable> suffixTables_;
|
||||
Vector<Subtable> subTables_;
|
||||
|
||||
// The maximal bitlength of a value in this table.
|
||||
//
|
||||
|
|
Двоичный файл не отображается.
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Двоичный файл не отображается.
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче